PHP CTF tricks parse_str and loose comparison
0x00 题目
|
|
0x01 解题
要得到flag首先要使if ($url[0] != 'QNKCDZO' && md5($url[0]) == md5('QNKCDZO'))
成立,也就是$url[0] != 'QNKCDZO'
和md5($url[0]) == md5('QNKCDZO')
都成立,如果str正常传入情况下,$url[0]
的值是’w’,满足第一个条件$url[0] != 'QNKCDZO'
,但是不满足md5($url[0]) == md5('QNKCDZO')
,但是代码中写了@parse_str($str)
;,而parse_str()函数会把参数字符串当做php变量解析,也就是如果str传入的是url[0]=hello
,那么就会解析成一个数组url,且数组url的第一个值为hello,此时$url[0] != 'QNKCDZO'
成立,md5($url[0]) == md5('QNKCDZO')
不成立,但是至少$url[0]
的值可控了,仔细研究md5($url[0]) == md5('QNKCDZO')
,可以发现md5('QNKCDZO')
的值为字符型的’0e830400451993494058024219903391’,但是根据PHP手册的描述:如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换为数值并且比较按照数值来进行。其中0e是科学计数法,因为涉及到数字内容,所以就会转换为数值,而’0e830400451993494058024219903391’转换为数值也就是0*(10^830400451993494058024219903391) = 0,所以我们只需要使url[0]
的MD5值为类似0e开头后面全为数字的字符串就可以让md5($url[0]) == md5('QNKCDZO')
成立,通过搜索发现很多字符串都满足条件,具体满足条件的列表可看。
我们选取240610708作为url[0]
的值,也就是使str传入的值为url[0]=240610708
,此时$url[0] != 'QNKCDZO'
成立,且md5($url[0]) == md5('QNKCDZO')
也成立: