前言
人道是,
我心错付情深处,以为两情皆如初。
奈何春风扶柳意,独我梦中空自舞。
许久未见诸位,这段时间由于学业与其他事情,便没再继续写下去(其实很大一部分归咎于自己的懒惰//DOGE)
这次带来一道开胃小菜,希望能够帮到各位师傅们,也希望得到大家的指点
正文
主页面
信息收集
www.tar.gz的内容
因锤死听
代码审计
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
//这里使用了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:
<a href=\"{$url}\" target='_blank'>{$url}</a><br/>
<a href=\"/\">go back</a>";//上传成功后生成url供用户访问上传后的文件
} else {
exit("upload error");
}
} else {
print_r(error_get_last());
exit;
}
}
rename.php
<?php
/**
* Created by PhpStorm.
* User: phithon
* Date: 15/10/14
* Time: 下午9:39
*/
require_once "common.inc.php";
/*
讲一讲这里重命名的逻辑:
1.查询输入的oldname是否存在于filename字段中
2.如果存在则update,不存在则error
*/
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']);//使用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:
<a href=\"{$url}\" target='_blank'>{$url}</a><br/>
<a href=\"/\">go back</a>";
//这里和上一个php一样
}
}
?>
<!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>
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']}'");//根据提供的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("/")函数重定向到首页
}
}
?>
<!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>
common.inc.php
<?php
/**
* Created by PhpStorm.
* User: phithon
* Date: 15/10/14
* Time: 下午7:58
*/
$DATABASE = array(
//哇哦最近hvv的看到这个老馋了
"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);
}//简单来说就是放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
<?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>
其实不难发现,最有可能出问题的在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是一个经验积累的过程,多做题,你就能找到其中的奥秘于快乐.
也祝各位六一儿童节快乐!!!!
求赞求关注,感谢!!!!!!!!!!!