文章目录
前言一、漏洞演示二、漏洞分析三、利用四、修复五、总结完前言
作者:Ho1aAs
博客:/xxy605
一、漏洞演示
进入PHPOK的后台,右上角先切换到开发模式
进入左侧的应用管理界面
点击安装应用——导入应用,上传一个zip压缩的php文件
# 1.php<?php phpinfo();?>
轻易完成了上传,访问_app/1.php就能发现文件已经被解压了,而且没有改名
二、漏洞分析
导入应用并上传的功能首先调用了zip函数接收压缩包
这一步只限定了上传文件类型是zip,而不限制其内容,没有对内容进行过滤和判断,对任何zip都保存
/*** 制作压缩包* @参数 $dir,支持单个文件,目录及数组* @参数 $saveName,保存的ZIP文件名**/public function zip($dir, $saveName){if(@!function_exists('gzcompress')){return false;}ob_end_clean();$filelist = array();if(is_array($dir)){$filelist = $dir;}else{if(!file_exists($dir)){return false;}if(is_file($dir)){$filelist = array($dir);}else{$this->filelist($filelist,$dir);}}if(count($filelist) < 1){return false;}if(class_exists('ZipArchive')){$obj = new ZipArchive();$obj->open($saveName,ZipArchive::OVERWRITE|ZipArchive::CREATE);//创建一个空的zip文件foreach($filelist as $file){if(!file_exists($file) || !is_file($file)){continue;}$name = substr($file,strlen($this->dir_root));$obj->addFile($file,$name);}$obj->close();return true;}foreach($filelist as $file){if(!file_exists($file) || !is_file($file)){continue;}$fd = fopen($file, "rb");$content = @fread($fd, filesize($file));fclose($fd);$file = substr($file, strlen($this->dir_root));if(substr($file, 0, 1) == "\\" || substr($file, 0, 1) == "/"){$file = substr($file, 1);}$this->addFile($content, $file);}$out = $this->file();$fp = fopen($saveName, "wb");fwrite($fp, $out, strlen($out));fclose($fp);}
zip压缩包上传成功后,调用unzip函数对其解压
这一步也是单纯的解压,并没有对压缩包内容进行过滤就解压到了根目录
public function unzip($file,$to=''){if(class_exists('ZipArchive')){$zip = new ZipArchive;$zip->open($file);$zip->extractTo($to);$zip->close();return true;}# ...(略)
三、利用
将任意文件添加到zip压缩文件,通过该功能上传zip、解压到根目录
四、修复
建议对上传的非应用安装包进行检查,解压时过滤危险文件类型、内容等
五、总结
由于以下问题导致该漏洞的产生:
对安装应用功能的非法利用上传、解压zip文件无过滤