过程
打开题目,是一道PHP的代码审计。代码如下:
<?php
highlight_file(__FILE__);
include "./flag.php";
include "./result.php";
if(isset($_GET['aaa']) && strlen($_GET['aaa']) < 20){
$aaa = preg_replace('/^(.*)level(.*)$/', '${1}<!-- filtered -->${2}', $_GET['aaa']);
if(preg_match('/pass_the_level_1#/', $aaa)){
echo "here is level 2";
if (isset($_POST['admin']) and isset($_POST['root_pwd'])) {
if ($_POST['admin'] == $_POST['root_pwd'])
echo '<p>The level 2 can not pass!</p>';
// START FORM PROCESSING
else if (sha1($_POST['admin']) === sha1($_POST['root_pwd'])){
echo "here is level 3,do you kown how to overcome it?";
if (isset($_POST['level_3'])) {
$level_3 = json_decode($_POST['level_3']);
if ($level_3->result == $result) {
echo "success:".$flag;
}
else {
echo "you never beat me!";
}
}
else{
echo "out";
}
}
else{
die("no");
}
// perform validations on the form data
}
else{
echo '<p>out!</p>';
}
}
else{
echo 'nonono!';
}
echo '<hr>';
}
?>
分析代码,需要过三关,才能拿到flag。
- 需要传入一个参数,对其进行正则替换掉
/^(.*)level(.*)$/
得到$aaa
,再对$aaa
正则匹配,需匹配到pass_the_level_1#
; - 需要保证
$_POST['admin'] == $_POST['root_pwd']
,且要通过判断sha1($_POST['admin']) === sha1($_POST['root_pwd'])
- 需要传入一个
level_3
参数,经过json_decode()之后与内置的$result
变量弱类型比较相等(==)
bypass:
- 正则匹配单行模式
(?s)
下 ,.
号将匹配所有字符,包括换行符;但默认情况下点号不匹配换行符,因此给了绕过(.*)
的可能。payload:%0apass_the_level_1%23
,%0a、%23分别是换行符、井号的URL编码。 - 利用哈希函数无法处理数组,会返回结果null,传入两个数组参数令其不一致绕过
$_POST['admin'] == $_POST['root_pwd']
,再sha1($_POST['admin']) === sha1($_POST['root_pwd'])
时,null===null从而绕过。 - 利用json_decode()的缺陷与php弱类型比较,“json_decode()函数用于对json格式数据进行json解码操作,对于一个json类型的字符串,会解密成一个数组;存在一个0=="efeaf"的Bypass缺陷”,如下:
<?php
$key = "JsonTest";
if (isset($_GET['data'])) {
$data = json_decode($_GET['data']);
if ($data->key == $key) {
echo "Bypass json_decode()!";
} else {
echo "No...";
}
}
?>
因此最终payload:
acquisition
- 正则匹配默认不匹配换行来bypass
.
- 哈希函数处理数组时为null
- php弱类型比较中json_decode()函数的缺陷
reference
https://johnfrod.top/ctf/2021-%E9%B9%A4%E5%9F%8E%E6%9D%AF/
https://www.mi1k7ea.com/2019/06/21/PHP%E5%BC%B1%E7%B1%BB%E5%9E%8B%E5%B0%8F%E7%BB%93/#0x09-json-decode