漏洞原理:我们上传一个zip的压缩包,它会解压然后删除其中不是.jpg .gig .png的文件
function check_dir($dir):这是一个PHP函数的定义,它接受一个参数 $dir,代表要检查的目录路径。
$handle = opendir($dir);:使用 opendir 函数打开指定目录,并将返回的目录句柄赋值给变量 $handle。
while (($f = readdir($handle)) !== false):使用 readdir 函数循环读取目录中的文件,每次循环将文件名赋给变量 $f。
if (!in_array($f, array('.', '..'))) { ... }:在每次循环中,检查当前文件名是否为当前目录(.)或父目录(..),如果不是,则执行下面的操作。
$ext = strtolower(substr(strrchr($f, '.'), 1));:使用 strrchr 函数找到文件名中的最后一个 .,然后使用 substr 截取文件扩展名,并用 strtolower 将其转换为小写。
if (!in_array($ext, array('jpg', 'gif', 'png'))) { unlink($dir . $f); }:如果文件的扩展名不是jpg、gif或png,则使用 unlink 函数删除该文件。
- header("Content-Type:text/html; charset=utf-8");
- require_once('pclzip.lib.php');
-
- $file = $_FILES['file'];
- if ($file['size'] == 0) {
- exit("请勿上传空文件");
- }
- $name = $file['name'];
- $dir = 'uploads/';
- $ext = strtolower(substr(strrchr($name, '.'), 1));
-
-
- function check_dir($dir)
- {
- $handle = opendir($dir);
- while (($f = readdir($handle)) !== false) {
- if (!in_array($f, array('.', '..'))) {
- $ext = strtolower(substr(strrchr($f, '.'), 1));
- if (!in_array($ext, array('jpg', 'gif', 'png'))) {
- unlink($dir . $f);
- }
- }
- }
- }
-
-
- if (!is_dir($dir)) {
- mkdir($dir);
- }
-
- $temp_dir = $dir . 'member/1/';
- if (!is_dir($temp_dir)) {
- mkdir($temp_dir);
- }
-
- if (in_array($ext, array('zip', 'jpg', 'gif', 'png'))) {
- if ($ext == 'zip') {
- $archive = new PclZip($file['tmp_name']);
- if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {
- exit("解压失败");
- }
- check_dir($temp_dir);
- exit('上传成功!');
- } else {
- move_uploaded_file($file['tmp_name'], $temp_dir . '/' . $file['name']);
- check_dir($temp_dir);
- exit('上传成功!');
- }
- } else {
- exit('仅允许上传zip、jpg、gif、png文件!');
- }
如果我们把图片和php一句话木马文件一起压缩,上传后就会发现php被删除了。
绕过方法:我们把php文件单独放在一个文件夹中,然后将这个文件夹和图片一起压缩成zip,然后上传


这个bbb文件夹里面的111.php就没有被删除了,然后就可以连接蚁剑了

上面主要是没有进行递归删除导致的绕过,后面进行了递归删除
- header("Content-Type:text/html; charset=utf-8");
- require_once('pclzip.lib.php');
-
- $file = $_FILES['file'];
- if ($file['size'] == 0) {
- exit("请勿上传空文件");
- }
- $name = $file['name'];
- $dir = 'uploads/';
- $ext = strtolower(substr(strrchr($name, '.'), 1));
-
-
- function check_dir($dir)
- {
- $handle = opendir($dir);
- while (($f = readdir($handle)) !== false) {
- if (!in_array($f, array('.', '..'))) {
- if (is_dir($dir . $f)) {
- check_dir($dir . $f . '/');
- } else {
- $ext = strtolower(substr(strrchr($f, '.'), 1));
- if (!in_array($ext, array('jpg', 'gif', 'png'))) {
- unlink($dir . $f);
- }
- }
- }
- }
- }
-
-
- if (!is_dir($dir)) {
- mkdir($dir);
- }
-
- $temp_dir = $dir . 'member/1/';
- if (!is_dir($temp_dir)) {
- mkdir($temp_dir);
- }
-
- if (in_array($ext, array('zip', 'jpg', 'gif', 'png'))) {
- if ($ext == 'zip') {
- // $zip = new ZipArchive;
- // if(!$zip->open($file['tmp_name'])) {
- // echo "fail";
- // return false;
- // }
-
- // if(!$zip->extractTo($temp_dir)) {
- // // check_dir($temp_dir);
- // exit('fail to zip');
- // }
- $archive = new PclZip($file['tmp_name']);
- if ($archive->extract(PCLZIP_OPT_PATH, $temp_dir, PCLZIP_OPT_REPLACE_NEWER) == 0) {
- exit("解压失败");
- }
- check_dir($temp_dir);
- exit('上传成功!');
- } else {
- move_uploaded_file($file['tmp_name'], $temp_dir . '/' . $file['name']);
- check_dir($temp_dir);
- exit('上传成功!');
- }
- } else {
- exit('仅允许上传zip、jpg、gif、png文件!');
- }

我们发现,bbb中的111.php就被删除了
但是代码逻辑是先解压,后删除,我们就用条件竞争来绕过
因为我发现,同时使用burp上传和访问,经过多次尝试没有成功,我换了个操作,使用手动上传zip,burp访问php,多次手动上传之后,成功了

在我们的uploads下面生成了一句话木马文件,直接连蚁剑

至此,phpcms告一段落