攻防世界-WEB-filemanager
前言
人道是,
我心错付情深处,以为两情皆如初。
奈何春风扶柳意,独我梦中空自舞。
许久未见诸位,这段时间由于学业与其他事情,便没再继续写下去(其实很大一部分归咎于自己的懒惰//DOGE)
这次带来一道开胃小菜,希望能够帮到各位师傅们,也希望得到大家的指点
正文
主页面
信息收集
www.tar.gz的内容
因锤死听
代码审计
upload.php
quote($path_parts["filename"]);
// Fix
//这里使用了addslashes以转义字符,目的是减少SQL注入风险,不过个人认为没啥卵用
$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:
{$url}
go back";//上传成功后生成url供用户访问上传后的文件
} else {
exit("upload error");
}
} else {
print_r(error_get_last());
exit;
}
}
rename.php
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']);//使用basename()确保newname不包含路径信息,保留文件名部分
$re = $db->query("update `file` set `filename`='{$req['newname']}', `oldname`='{$result['filename']}' where `fid`={$result['fid']}");//数据库更新操作,失败返回error
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:
{$url}
go back";
//这里和上一个php一样
}
}
?>
file manage
Rename
old filename(exclude extension):
new filename(exclude extension):
delete.php
query("select * from `file` where `filename`='{$req['filename']}'");//根据提供的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("/");//调用redirect("/")函数重定向到首页
}
}
?>
file manage
Delete file
delete filename(exclude extension):
common.inc.php
"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);
}//简单来说就是放sql注入的
}
define("UPLOAD_DIR", "upload/");
//定义了一个名为redirect的函数,用于重定向到指定的URL。它发送HTTP重定向头,并退出脚本执行
function redirect($location) {
header("Location: {$location}");
exit;
}
xdctf.sql
#配置文件,没啥分析的
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;
还有一个完全不需要分析的index.php
file manage
Control
- Delete file
- Rename file
Content
其实不难发现,最有可能出问题的在rename.php中,我们来看这一段
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;
}
代码看着好像没问题,实则细心的师傅不难发现,它并没有对newname进行过滤,也就意味着我们可以构造恶意代码进行漏洞利用
——————————————————–
还有就是upload.php
它对传入的文件后缀进行验证,也对传入的filename做了转义
$path_parts['filename'] = addslashes($path_parts['filename']);
$sql = "select * from `file` where `filename`='{$path_parts['filename']}' and `extension`='{$path_parts['extension']}'";
但是这还不够,照样能够被利用
当我们传入这样一个值: ‘,extension=’.jpg
由于upload.php并未对传入的文件名做任何的限制(如不能使用’\@*等等),所以能够被成功上传
其次又由于传入的’,extension=’.jpg中的后缀.jpg符合白名单规则,所以能够被成功上传
我们来进行实践
——————————————————–
实践
验证成功
——————————————————–
接下来需要利用rename.php
old filename得这么写,不然’,extension=’.jpg无法被识别
重命名成功
这样rename.php中的
update `file` set `filename`='{$req['newname']}', `oldname`='{$result['filename']}' where `fid`={$result['fid']}
就变成了
update `file` set `filename`='MQ4.jpg',`oldname`='',extension='' where `fid`={$result['fid']}"
——————————————————–
接下来上传一个MQ4.jpg的马
——————————————————–
然后回到rename.php
——————————————————–
连接我们的小马
连接成功
成功获取flag
结尾
CTF是一个经验积累的过程,多做题,你就能找到其中的奥秘于快乐.
也祝各位六一儿童节快乐!!!!
求赞求关注,感谢!!!!!!!!!!!