弱类型
相关文章 & Source & Reference
相关 writeup
松散比较
php中有两种比较的符号 == 与 ===
严格比较 :
===在进行比较的时候,会先判断两种字符串的类型是否相等,再比较松散比较 :
==在进行比较的时候,会先将字符串类型转化成相同,再比较,如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换成数值并且比较按照数值来进行
观察上述代码,"admin"==0 比较的时候,会将 admin 转化成数值,强制转化, 由于 admin 是字符串,转化的结果是 0 自然和 0 相等
"1admin"==1 比较的时候会将 1admin 转化成数值, 结果为 1
"0e123456"=="0e456789" 相互比较的时候,会将 0e 这类字符串识别为科学技术法的数字,0 的无论多少次方都是零,所以相等
“admin1“==1 却等于错误,也就是 "admin1" 被转化成了 0, 为什么呢??
当一个字符串被当作一个数值来取值,其结果和类型如下: 如果该字符串没有包含'.','e','E'并且其数值值在整形的范围之内该字符串被当作 int 来取值,其他所有情况下都被作为 float 来取值,该字符串的开始部分决定了它的值,如果该字符串以合法的数值开始,则使用该数值,否则其值为 0。
Hash比较缺陷
CTF 比赛中需要用到弱类型 HASH 比较缺陷最明显的标志便是管理员密码 MD5 之后的值是以 0e 开头
题目大意是要输入一个字符串和数字类型,并且他们的md5值相等,就可以成功执行下一步语句
在进行比较的时候,会先将两边的变量类型转化成相同的,再进行比较
0e 在比较的时候会将其视作为科学计数法,所以无论 0e 后面是什么,0 的多少次方还是 0。
以上字符 md5 开头都是 0e,即可绕过验证
可以用下列脚本寻找
双md5结果仍为0e开头字符串
$md5=md5($md5)
md5($str,true)注入
md5 强比较
MD4
MD2
shal
布尔欺骗
当存在 json_decode 和 unserialize 时,部分结构会被解释为 bool 类型,会造成欺骗
输入一个 json 类型的字符串,json_decode 函数解密成一个数组,判断数组中 key 的值是否等于 $key 的值,但是 $key 的值我们不知道,但是可以利用 0=="admin" 这种形式绕过
最终 payload message={"key":0}
数字转换欺骗
strcmp 绕过
strcmp 是比较两个字符串,如果 str1 < str2 则返回 < 0 如果 str1 大于 str2 返回> 0 如果两者相等 返回 0
我们是不知道 $password 的值的,题目要求 strcmp 判断的接受的值和 $password 必需相等,strcmp 传入的期望类型是字符串类型,如果传入的是个数组会怎么样呢
我们传入 password[]=xxx 可以绕过 是因为函数接受到了不符合的类型,将发生错误,但是还是判断其相等
payload: password[]=xxx
switch 绕过
switch() 其中 () 内的值会被弱类型转换
array_search is_array 绕过
先判断传入的是不是数组,然后循环遍历数组中的每个值,并且数组中的每个值不能和 admin 相等,并且将每个值转化为 int 类型,再判断传入的数组是否有 admin,有则返回 flag
payload test[]=0 可以绕过
下面是官方手册对 array_search 的介绍
mixed array_search ( mixed $needle , array $haystack [, bool $strict = false ] )
$needle,$haystack 必需,$strict 可选 函数判断 $haystack 中的值是存在 $needle,存在则返回该值的键值 第三个参数默认为 false,如果设置为 true 则会进行严格过滤
array_search 函数 类似于 == 也就是 $a=="admin" 当然是 $a=0 当然如果第三个参数为 true 则就不能绕过
preg_match 绕过
数组绕过
preg_match 只能处理字符串,当传入的 subject 是数组时会返回 false
PCRE 回溯次数限制
pcre.backtrack_limit 给 pcre 设定了一个回溯次数上限,默认为 1000000,如果回溯次数超过这个数字,preg_match 会返回 false
很多基于 PHP 的 WAF,如:
均存在上述问题,通过大量回溯可以进行绕过。
还有一种是
回溯次数随着 a 的数量增加而增加。所以,我们仍然可以通过发送大量 a,来使回溯次数超出 pcre.backtrack_limit 限制,进而绕过 WAF.
当使用 === 全等号匹配时,不会有这个问题
换行符
. 不会匹配换行符,如
只需要
而在非多行模式下,$ 似乎会忽略在句尾的 %0a
只需要传入