攻防世界-WEB-filemanager

前言

人道是,

我心错付情深处,以为两情皆如初。
奈何春风扶柳意,独我梦中空自舞。

许久未见诸位,这段时间由于学业与其他事情,便没再继续写下去(其实很大一部分归咎于自己的懒惰//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是一个经验积累的过程,多做题,你就能找到其中的奥秘于快乐.

也祝各位六一儿童节快乐!!!!

求赞求关注,感谢!!!!!!!!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值