feat: 修复反序列化漏洞

This commit is contained in:
chenping
2026-04-14 18:32:01 +08:00
parent a70b47a832
commit ce3dc57950

View File

@@ -21,6 +21,9 @@ class desktop_ctl_appmgr extends desktop_controller{
var $workground = 'desktop_ctl_dashboard';
var $require_super_op = true;
/** @var int GET data 最大长度,防止超大序列化串消耗资源 */
private static $appmgr_data_max_len = 65536;
public function __construct(&$app)
{
if(defined('WITHOUT_DESKTOP_APPMGR') && constant('WITHOUT_DESKTOP_APPMGR')){
@@ -86,10 +89,20 @@ class desktop_ctl_appmgr extends desktop_controller{
}
public function command(){
if(method_exists($this,'command_'.$_GET['command_id'])){
$this->{'command_'.$_GET['command_id']}(unserialize($_GET['data']));
echo "\nok.";
if(kernel::single('base_setup_lock')->lockfile_exists()){
echo "\nError: ".app::get('desktop')->_('系统已安装,禁止通过此接口执行应用命令。');
return;
}
if(!isset($_GET['command_id']) || !method_exists($this,'command_'.$_GET['command_id'])){
return;
}
$data = $this->_appmgr_unserialize_get_data('string');
if($data === false){
echo "\nError: invalid data.";
return;
}
$this->{'command_'.$_GET['command_id']}($data);
echo "\nok.";
}
public function maintenance(){
@@ -141,8 +154,8 @@ class desktop_ctl_appmgr extends desktop_controller{
}
public function install_options(){
$apps = unserialize($_GET['data']);
if(!$apps){
$apps = $this->_appmgr_unserialize_get_data('array');
if($apps === false){
return;
}
$rows = app::get('base')->model('apps')->getList('app_id,app_name',array('app_id'=>$apps));
@@ -322,5 +335,52 @@ class desktop_ctl_appmgr extends desktop_controller{
return $return;
}
/**
* 安全反序列化 $_GET['data']:禁止实例化类,防止对象注入 gadget如 CNVD 通报链)。
*
* @param string $expect string=单行 command 的 app_idarray=install_options 的 app_id 列表
* @return string|array|false
*/
private function _appmgr_unserialize_get_data($expect){
if(!isset($_GET['data']) || !is_string($_GET['data'])){
return false;
}
$raw = $_GET['data'];
if($raw === '' || strlen($raw) > self::$appmgr_data_max_len){
return false;
}
$data = @unserialize($raw, array('allowed_classes' => false));
if($expect === 'string'){
if(!is_string($data) || $data === ''){
return false;
}
if(!$this->_appmgr_is_valid_app_id($data)){
return false;
}
return $data;
}
if($expect === 'array'){
if(!is_array($data) || empty($data)){
return false;
}
foreach($data as $app_id){
if(!$this->_appmgr_is_valid_app_id($app_id)){
return false;
}
}
return $data;
}
return false;
}
/**
* app_id 白名单校验(目录名级,禁止路径与控制字符)
*/
private function _appmgr_is_valid_app_id($app_id){
if(!is_string($app_id) || $app_id === '' || strlen($app_id) > 64){
return false;
}
return (bool)preg_match('/^[a-zA-Z0-9_\\-]+$/', $app_id);
}
}