wh1te说PHP黑魔法-弱类型比较

弱类型比较

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获取文章目录

官方微信群请输入:二维码 获取二维码扫码进入,失效请联系公众号人工客服

是否属于作者投稿:是

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181201A00PA700?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券