CTF
Teaser CONFidence CTF 2019 - My admin panel
能拿到源码
|
|
可以发现,在判断session中的hash值是否与md5($cfg_pass)
相等时用了松散比较,于是随便用个0e开头的hash
当然没显示出flag,但是返回了000646464xxxxx
(忘了,题目也关了…)
他在与0xC0
做与运算是,如果是0-9,结果是0,如果是a-z,结果是64。可以得出,这个hash值前3位是数字
因为他用了松散比较,当数字与字符进行松散比较时,php会把字符转换成数字,比如”123asdasd”就会被转换成123,”asdasd”就会被转换成0,所以我们就能用在有限时间内爆破出前3位数字,拿到flag
|
|
深究
知其然还要知其所以然,于是对这一过程进行了分析
|
|
获得松散比较时的opcode
在Zend/zend_language_scanner.l
文件中我们找到==
对应的token
接下来就是语法解析,在Zend/zend_language_parse.y
中
最终分配到ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER
跟进compare_function
会发现针对op1
和op2
类型的操作,但是IS_LONG
跟IS_STRING
的情况不存在,就进入转换类型的分支
跟进zendi_convert_scalar_to_number
这个宏函数
op1因为是整数,所以不做处理,op2是字符串,所以进入IS_STRING分支
,跟进is_numeric_string
8说了继续
冲冲冲
这里就是字符转数字的关键步骤了,将字符串字符一个一个的处理,如果当前字符是数字就进行tmp_lval*10 + (*ptr) - '0'
运算,直到遇到第一个不是数字的字符
所以在松散比较中,字符串转数字的流程就是
ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER -> compare_function -> zendi_convert_scalar_to_number -> is_numeric_string -> is_numeric_string_ex -> _is_numeric_string_ex
这些都是gdb调试过后梳理的,并不是一上来就直接看源码233333
参考
http://www.phppan.com/2011/07/php-loose-and-strict-comparison/