弱类型


相关文章 & 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

只需要传入