弱类型比较
php弱类型比较一直都是CTF中WEB题目的一大热门,通过一些存在漏洞的函数,或者是版本的缺陷,来考验参赛的选手们对于漏洞以及函数的理解和利用,本篇就介绍了关于这方面的知识。
php就是一门弱类型语言。弱类型就是不需要声明变量的类型,php会根据变量的值自动把变量转换为正确的数据类型。强类型的编辑语言在使用变量前必须声明变量的数据类型。
哈希比较缺陷
PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。
0E开头的md5值对应的一些字符串:
顺带放上一个经典CTF题目:
md5 sha1函数缺陷
当md5()函数与sha1()函数对参数进行加密处理时,如果碰到一个数组,md5()函数会返回null,sha1()函数也是一样。利用这个特性构造两个数组即可。(PS:之前忘记了get或post传递数组如何传递了,特地在这里记录一下,a[]=1,这就是表示一个数组)
数字比较缺陷(类型强制转换)
php中有两种比较的符号\==和===
===在进行比较的时候会先判断两种字符串的类型是否相等,再比较。
== 在进行比较的时候,会先将字符串的类型转换为相同,再比较
例:
经典例题:
intval()缺陷
intval函数用于获取变量的整数值。通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。
本来想写在php函数缺陷内的,但是这个函数,往往在进行比较时使用。
例如:
strcmp函数缺陷
这个函数也经常的被使用到,也是一个经典函数。
定义:
漏洞:
经典题目:
ereg(),eregi()函数缺陷
ereg函数存在两个漏洞:
%00截断,在遇到%00的时候会认为字符串结束了
ereg函数中的参数值如果为数组,会返回false
eregi跟ereg函数漏洞基本一样,区别在于++ereg区分大小写++(这里划重点,也是可以用来绕过的),eregi函数不区分大小写。
经典题目:
strlen()函数缺陷
这个函数也是CTF函数黑魔法中的经典函数,自我矛盾。用来进行判断长度,然后结合大小比较来进行出题。
但是可以通过科学计数法的方法来进行绕过。比如:
经典题目:
preg_match(),preg_match_all()函数缺陷
先说preg_match()函数,是为了弥补ereg函数的%00截断问题,替换了ereg函数。但是,在CTF中踩了那么多坑以后,终于发现了制裁它的方法,构造数组,就可以了。
经典题目:
preg_match()函数还存在另一个问题,preg_match 函数用于进行正则表达式匹配,返回 pattern 的匹配次数,它的值将是 0 次(不匹配)或 1 次,因为 preg_match() 在第一次匹配后将会停止搜索。如果在进行正则表达式匹配的时候,没有限制字符串的开始和结束(^ 和 $),则可以存在绕过的问题。
经典题目:
preg_match_all()这个函数还没有单独的碰到过,碰到了再做总结吧。(我不是标题党)
is_numeric()函数缺陷&trim()函数缺陷
is_numeric() 函数用于检测变量是否为数字或数字字符串。如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE。
好,那么问题来了,对于16进制的字符串,是怎么判断的呢?
它会默认16进制的字符串为整形,这样就可以构造16进制的payload来进行函数绕过。
例题:
is_numeric 检测的时候会自动过滤掉前面的 ‘ ‘, ‘\t’, ‘\n’, ‘\r’, ‘\v’, ‘\f’ 等字符,但是不会过滤 ‘\0’,如果这些字符出现在字符串尾,也不会过滤,而是返回 false
trim 函数会过滤空格以及 \n\r\t\v\0,但不会过滤过滤\f
利用trim函数以及is_numeric函数实现绕过:
in_array()函数缺陷
in_array()函数用来判断字符串是否存在与数组中,但是在判断的时候,会进行类型强制转换,就会出现数字比较的情况。
经典例题:
那这种情况,在SQL注入时,就可以产生很大的作用,比如:
strpos()函数缺陷
strpos() 函数查找字符串在另一字符串中第一次出现的位置(区分大小写)。
经典题目:
传入abc或会打印123,但是传入一个数组或者不传入数据一样也会打印123。这个函数也是只解析string类型的字符串,给他个数组就不知道如何解析,于是就返回为null。Null==0!当不传入数据的时候,也是一样的道理,还是返回null。
变量覆盖
extract()函数
用法:
其实很简单,就是变量覆盖,给个例题一看就知道了:
这样,输出privatel了。
经典题目:
parse_str()函数导致变量覆盖
parse_str() 函数用于把查询字符串解析到变量中,如果没有array 参数,则由该函数设置的变量将覆盖已存在的同名变量。 极度不建议 在没有 array参数的情况下使用此函数,并且在 PHP 7.2 中将废弃不设置参数的行为。此函数没有返回值。
当传递参数id=a[]=yaun的时候,经过parse_str()函数的处理将a变成变量。但是原来有同名的变量,于是就将原来的变量覆盖掉,同时覆盖的还有变量的值
$$变量覆盖
直接上代码看:
CTF经典题目:
json_decode()函数
先介绍下json字符串吧,json就是一种数据交换格式,在 JS 语言中,一切都是对象。因此,任何支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。但是对象和数组是比较特殊且常用的两种类型:
经典例题:
这个payload利用的还是php字符比较的漏洞,0==’admin’
switch()函数漏洞
switch函数是php中的条件分支语句,通过对switch中的参数值进行判断,选择case中的代码去执行,但是会将switch中的参数转换为int类型,那么问题就来了,在进行类型转换的时候,’1admin’==’1’的。
经典题目:
switch还有一个特别骚的坑,直接上代码去看:
这个代码,骚在哪里?
第一个分支判断语句,并不会成立,因为case的条件是 0>=0 ,也就是 true ,但是参数$a为0,两者并不相等,但是第二个分支语句的case条件为 0>=10 ,也就是false,参数$a的值为0,’0’==’false’,所以case $a>=10成立。
小结
从上面的一些案例去看,很多函数问题都是基于php是一个弱类型的语言,在进行类型转换的时候出现的问题。所以类型,是php黑魔法当中比较重要的一个环节。
本来是打算把php弱类型比较跟php函数缺陷写在一起的,然后写的时候发现,想的太简单了,一总结,一大堆,简直就是越写越多。写一点,想起来一点,再写一点,又想起来一点,简直是头大。搞了三天有余,终于加班加点完工……(PS:反序列化我会当成单独的一篇去写,莫着急)。
完
本篇文章的编号是 :47,在公众号聊天窗口输入编号直达本文
输入m获取文章目录
官方微信群请输入:二维码 获取二维码扫码进入,失效请联系公众号人工客服
是否属于作者投稿:是
领取专属 10元无门槛券
私享最新 技术干货