继续ctf的旅程 开始攻防世界web高手进阶区的8分题 本文是filemanager的writeup
进来是这样的 这应该是个文件上传漏洞 先看源码和御剑扫描 发现/www.tar.gz可以获得源码
数据库结构
SET NAMES utf8; SET FOREIGN_KEY_CHECKS = 0; DROP DATABASE IF EXISTS `xdctf`; CREATE DATABASE xdctf; USE xdctf; DROP TABLE IF EXISTS `file`; CREATE TABLE `file` ( `fid` int(10) unsigned NOT NULL AUTO_INCREMENT, `filename` varchar(256) NOT NULL, `oldname` varchar(256) DEFAULT NULL, `view` int(11) DEFAULT NULL, `extension` varchar(32) DEFAULT NULL, PRIMARY KEY (`fid`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; SET FOREIGN_KEY_CHECKS = 1;common
对传入的参数进行了addslashes()转义数据库连接和遍历数组基本没有直接的注入漏洞
<?php /** * Created by PhpStorm. * User: phithon * Date: 15/10/14 * Time: 下午7:58 */ $DATABASE = array( "host" => "127.0.0.1", "username" => "root", "password" => "ayshbdfuybwayfgby", "dbname" => "xdctf", ); $db = new mysqli($DATABASE['host'], $DATABASE['username'], $DATABASE['password'], $DATABASE['dbname']); $req = array(); foreach (array($_GET, $_POST, $_COOKIE) as $global_var) { foreach ($global_var as $key => $value) { is_string($value) && $req[$key] = addslashes($value); } } define("UPLOAD_DIR", "upload/"); function redirect($location) { header("Location: {$location}"); exit; } ?>upload
白名单限制了后缀名查询文件名是否存在,进行了addslashes()转义oldname和filename拼接的后缀查出的结果都是相同的也不存在直接注入漏洞
<?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; } } ?>delete 就是删除,没什么好讲
<?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("/"); } } ?>rename
filename=$req['oldname']是从数据库查询输入的oldname是否在于filename字段,然后进行update修改oldname={$result['filename']}将之前从数据库中查询出的filename更新到oldname当中,再次入库造成二次注入可以通过sql注入,影响其extension为空,再修改文件时加上.php后缀绕过file_exists()只需要再次上传一个与数据库当中filename的值相同的文件名即可 <?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>"; } } ?>先上传一个空文件 命名为
',extension='.jpg去使extension为空 然后把它rename为即将上传的木马文件名
此时数据库中
update `file` set `filename`='upload.jpg', `oldname`='',extension='' where `fid`={$result['fid']}"上传一句话木马文件 rename 上啊 蚁剑
成功获取flag
比较老的题目 知识点
代码审计二次注入