过程
打开题目,是一道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