php 在 ctf 中常见的特性
php的一些特性
谈谈一些在ctf中遇到的php的特性
php的弱比较
在php中有两个比较表达式
==
===
两个等号==
是弱比较,使用==
进行对比的时候,php解析器就会做隐式类型转换,如果两个值的类型不相等就会把两个值的类型转为同一类型进行对比
使用字符串与整型对比
"a"==0
原理是,当字符串开头是非数字的字符与数字时进行弱比较,php的解析器做隐式类型转换就会把非数字的字符转为
int
类型的0,再进行比较这样就会相等
如果是数字开头的就不一样了
因为php的解析器会获取开头的字符来进行校验,如果开头的字符是非数字的就整个值转成int类型的值为0,数字开头的则以数字为准
三个等号
===
是强对比,使用===
进行对比的时候,php解析器会校验两个值的类型是否相等,相等的时候再进行对比再三个等号
===
这里就和==
不相同,因为会先做类型校验
例题:
代审:
接收一个GET参数,判断是否长度为5,然后使用switch函数对比,对比为4就打印flag
根据官方文档所说的switch表达式对比是松散的对比
所以根据上面的所说的特性
php的解析器会获取开头的字符来进行校验,如果开头的字符是非数字的就整个值转成int类型的值为0,数字开头的则以数字为准
, 传入一个4开头长度为5的字符串即可
php的hash弱比较
进行hash加密出来的字符串如果存在0e开头进行弱比较的话会直接判定为true
例题:
代审:
接受两个GET参数,使用
ctype_alpha
判断参数a
是否为纯字符串,不是就logined
为false使用
is_numeric
判断参数b
是否为纯数字或者纯数字的字符串,不是就logined
为false然后判断参数
a
和参数b
经过md5
加密是否相等,不相等logined
为false
logined
为true则打印flag因为使用的是弱比较,所以只要是md5加密后的字符串是0e开头的进行对比就会变成
0==0
然后对比成立就返回true从而绕过以下是md5加密后为0e开头的字符串
QNKCDZO 0e830400451993494058024219903391 240610708 0e462097431906509019562988736854 s878926199a 0e545993274517709034328855841020 s155964671a 0e342768416822451524974117254469 s214587387a 0e848240448830537924465865611904 s214587387a 0e848240448830537924465865611904 s878926199a 0e545993274517709034328855841020 s1091221200a 0e940624217856561557816327384675 s1885207154a 0e509367213418206700842008763514
根据代审参数
a
传入GNKCDZO
参数b
传入240610708
php的json弱比较
例题:
代审:
接受GET参数,判断参数是否为空,然后
json_decode
转码为json数据,然后判断json的键key
映射的值是否为flag这里比较使用的是弱比较,所以可以使用特性0于任意开头非数字的字符串对比为true的特性进行绕过
php的编码比较绕过
例题:
代审:
接收两个GET参数,判断两个参数是否为空,然后依次对两个参数进行md5加密,sha1加密,base64编码然后再进行强对比,如果不相同
chake
变量就变为false但是这些加密编码函数无法对数组进行加密或编码,返回值就会变成NULL,如果传入两个参数都是数组的话就就是两个NULL进行强对比,所以表达式成立,结果为true即可得到flag
所以参数传入数组即可绕过
php函数in_array弱比较
例题:
php的函数
in_array
,在第三个参数没有选择的时候,进行检索使用的是弱比较代审:
接受GET参数,判断参数是否是数组,是则继续程序,循环遍历数组里的值,如果数组里的值是字符串则结束程序,如果数组里的值是flag则结束程序,然后转换数组里的值为数字,再判断数组里的值是否有存在flag,存在就打印flag
这道题很简单,根据上面所说的php弱比较的特性
当字符串开头是非数字的字符与数字时进行弱比较,php的解析器做隐式类型转换就会把非数字的字符转为int类型的0
,传入一个数组,里面的值为0即可
php函数strcmp
例题:
php的函数
strcmp
是用来做字符串比较的,如果两者相等返回0代审:
接受一个GET参数与flag进行比较,结果为0就打印flag
这里使用的是弱比较,函数
strcmp
和md5这些函数一样无法对数组进行有效的处理,如果函数传入的参数为数组,结果返回会是NULL,NULL类型与0进行弱比较的话表达式会成立,结果为true所以这一题也是传入一个数组即可
php可变变量
这里的
$$a
等同于$hello
,因为php是使用$
来表明变量的,如果再$
前再添加一个$
就变为了可变变量,即$$a
这个$a
的值是hello
,$a
解析后就是hello
,这个hello
再添加前面的$
符就变成了$hello
即$$a
同等于$hello
例题:
代审:
判断GET参数,是否为空,然后再正则匹配参数,如果是纯数字就退出程序,否则就打印可变变量
传入flag的字符串即可
代审:
foreach函数遍历GET参数的的键值,强判断键为error退出程序,然后给值的参数命名的可变变量赋值给键的参数命名的可变变量,然后再使用相同的函数遍历POST参数的键值,如果参数的值为flag,则退出,然后给值的参数命名的可变变量赋值给键的参数命名的可变变量
因为这一题没有指定传参名,所以可以指定任意的参数名,这样可以利用它已经存在的变量名来进行绕过
指定传入的参数名为suces然后值为flag,再根据
$$key=$$value
1这样就变量$suces
经过可变变量的改变变成了变量$flag
,然后再传入POST参数键为error
值为suces
因为$$key=$$value
2的原因变成了变量$suces
但是经过了第一个$$key=$$value
1的关系$suces
已经变成了$flag
所以最后的die($flag)
打印了flag
快来看看吧~
😋 大赞
学习了
好