首页
论坛
课程
招聘

PHP弱类型在实战中导致的漏洞总结

2018-04-11 15:38

简介

说到PHP弱类型大家肯定不陌生,但是对于PHP中==和===比较时存在的差异,哪一个安全哪一个不安全,肯定很多程序员并不清楚。

 

网络上有很多大佬们的文章都是介绍PHP弱类型原理,及其可能存在的问题理论,还有就是CTF里面经常出现的场景,然而在具体的实战当做却很少有案例或者文章,本文中将我在具体的项目和代码审计中遇到的由PHP弱类型引发的漏洞进行一个初步总结,例如由PHP弱类型导致的密码重置、登录绕过、SQL注入、命令执行、Hash碰撞等漏洞等等,后续遇到新场景继续补充。

PHP弱类型是什么

PHP作为最受欢迎的开源脚本语言,也被称为是世界上最好的语言,越来越多的应用于Web开发领域。

 

PHP属于弱类型语言,即定义变量的时候不用声明它是什么类型。作为一个程序员,弱类型确实给程序员书写代码带来了很大的便利,这一便利也是PHP语言的一个特性,但是在安全领域,特性既漏洞,这些特性在代码里面经常就是漏洞最容易出现的地方。

PHP比较操作符

在弄明白PHP操作符之前,需要明白PHP变量类型及它们的意义。例如,"42" 是一个字符串而 42 是一个整数。FALSE 是一个布尔值而 "false" 是一个字符串。HTML
表单并不传递整数、浮点数或者布尔值,它们只传递字符串。

 

PHP的比较操作符有==(等于)松散比较,它不会去检查条件式的表达式的类型;===(完全等于)严格比较,也就是恒等,它会检查查表达式的值与类型是否相等,所以这里面就会引入很多有意思的问题。例如NULL,0,”0”,array()使用==和false比较时,都是会返回true的,而使用===却不会,如下图:

 

 

在松散比较的时候,PHP会将他们的类型进行强制转换从而统一类型,比如说字符到数字,非bool类型转换成bool类型。一个数字和一个字符串进行比较,PHP会把字符串转换成数字再进行比较。PHP转换的规则的是:若字符串以数字开头,则取开头数字作为转换结果,若无则输出0。当有一个对比参数是整数的时候,会把另外一个参数强制转换为整数,如下图:

 

 

PHP官方也给出了类型比较表,表格中显示了PHP类型和比较运算符在松散和严格比较时的作用及返回值,应该是比较详细的,如下图:

 

使用PHP函数对变量\$x进行比较:

 

 

松散比较(==)情况

 

 

严格比较(===)情况

 

 

从上面的表格中已经很清晰的看到==和===比较时的区别了。

实战中导致的漏洞解析

下面以实战中遇到的真实场景为例介绍PHP弱类型导致的漏洞。

 

DedeCMS密码重置

 

2018年01月09日,Dedecms官方更新了DedeCMS V5.7
SP2正式版,在此版本及之前版本存在任意用户密码重置漏洞,具体导致漏洞的代码如图:

 

 

在找回密码时,当$dopost =safequestion时,通过传入的member_id查询出对应id用户的安全问题和答案信息,当我们传入的问题和答案不为空,并且等于系统设置的问题和答案时就进入sn()函数。

 

这里如果用户设置了问题和答案,我们并不知道问题和答案是什么,就无法进入sn()函数。但是如果此用户没有设置问题和答案呢?此时系统默认问题是”0”,答案是空。

 

那么我们传入答案$safeanswer = “”时:

 

$row[‘safeanswer’] == $safeanswer;成立。

 

但是传入问题$safequestion = “0”时:

 

empty(\$safequestion)为真,此时$safequestion = ””,而$row[safequestion] = “0”

 

此时$row[safequestion] == $safequestion;不成立。

 

 

所以现在要让问题相等,才能绕过if判断,此时如果熟悉PHP的话,会想到PHP的弱类型问题,如下图:

 

 

利用弱类型的特性,==松散比较,"0.0"、"0."、"0e123"在empty()函数是不为空,并且松散比较"0"时为真,成功进入if条件,进入sn()函数重置密码。此漏洞在渗透测试和众测时应该已经被刷很多遍了吧。详细漏洞分析见:https://mp.weixin.qq.com/s/MTES86qMVDquKrZq2oolVA

 

ZPanel密码重置

 

Sentora / ZPanel 由于设计缺陷,导致存在密码重置漏洞,具体漏洞代码如下:

 

 

生成一个随机的验证密码Token,然后更新数据库,发送重置密码链接。

 

 

然后点击重置密码链接后,验证token有效性,重置密码。

 

但是在重置密码完成后,系统又设置了ac_resethash_tx为空,那么我们就可以以空的token继续重置密码了!!!

 

具体漏洞细节:https://blogs.securiteam.com/index.php/archives/3386

 

HDwikiSQL注入

 

具体漏洞代码如图:

 

 

从代码中看到,首先从GET里获得doctype($doctype =
$this->get[2];),然后进入一个switch语句。如果进入case 2和case
3保持\$doctype的值不变,但是进入default将\$doctype改为1,最后看到这句$count=$this->db->fetch_total('focus',"type=$doctype");,直接将\$doctype带入SQL语句,所以只要这个switch语句不影响\$doctype的值也就是必须进入case
2和case 3分支,就导致SQL注入漏洞。

 

如果要进行SQL注入那么\$doctype必须是字符串,但是\$doctype必须进入case 2和case
3分支,case 2和case
3分支又是整型数字,所以就是很经典的弱类型问题进行松散比较的点了。

 

我们只需要将\$doctype的值,也就是GET获取的参数第一位设置为2或者3就好了,后面跟上sql语句就成功绕过进行sql注入了,如下图:

 

 

如上图成功绕过进行sql注入。

 

某产品命令执行

 

在偶然一次渗透测试项目中,登录到某产品中,发现如下代码(图为伪代码):

(图片丢了...)

 

从代码中看到\$file进入到命令执行,但是\$file中可控的变量是\$config,而且这里判断只有\$config==2时才能进入命令执行流程,所以利用弱类型的类型强制转换就可绕过判断进入命令执行。

 

 

WordPress Cookie伪造

 

在WordPress 3.8.2的官方补丁中有这样一个补丁

 

 

很明显,就改变松散比较和严格比较。

 

在WordPress中\$hmac来源于cookies,是我们可控的一个输入参数,结构如下:

 

 

\$hash是以下代码生成一个md5值,当\$hmac ==
\$hash 时,登录成功。由于是==松散比较,所以存在如下几种情况都可以登录成功:

//第一种情况,完全相等。

\$hmac = ‘1f253e501c301bf5bf293c40d7d92ded’;

\$hash = ‘1f253e501c301bf5bf293c40d7d92ded’;

//第二种情况,第一位为数字,第二位为字母

\$hmac = 1;

\$hash = ‘1f253e501c301bf5bf293c40d7d92ded’;

//第三种情况。第一位为字母

\$hmac = 0;

\$hash = ‘af253e501c301bf5bf293c40d7d92ded’;

//第四种情况,第一位为0,第二位为e,后面所有位为数字

\$hmac = “0”;

\$hash = ‘0e1234567890123456...32’;

 

由于\$hmac最后获取的是一个字符串,所以很显然第四种情况是可以成立的。所以最后这个漏洞的利用方式还可以是:让\$hmac =‘0’,通过生成\$hash,获得一个,第一位为0,第二位为e,后面所有位为数字的\$hash。

 

变相信息泄露

 

在PHP中进行比较运算时,如果遇到了0e\d+这种字符串,就会将这种字符串解析为科学计数法,例如0e10,‘e’会识别为次方,0的10次方为0,如下图所示,两个不同字符串但是在==下他们的md5值相等:

 

 

那么我们来扩展一下:

先注册密码为240610708的用户A。

然后用密码QNKCDZO尝试登录用户A。

倘若成功登录,则证明此网站采用了不完备的加密体制md5一次加密。

先注册密码为0e33455555的用户A。

然后用密码0e66788888尝试登录用户A。

倘若成功登录,则证明此网站采用了明文进行存储密码!

 

这样既可采集目标信息了,还有其他扩展大家自己开脑洞。

 

其他

 

除了在PHP的弱类型中存在强制类型转换外,MySQL中也同样存在类似的特性,在mysql里面,当字段类型为整型,而where语句中的值不为整型的时候,会被转换成整型才放入查询。也就是说,如果where
code='xxx',xxx不为整型的话,则会先将xxx转换成整数,才放入查询,也就是说,如果我们传入的字符串为0aaa,则会转换成0,再执行。详见P牛的博客:

 

https://www.leavesongs.com/PENETRATION/findpwd-funny-logic-vul.html

参考链接

http://php.net/manual/zh/types.comparisons.php

防护方案

为了避免意想不到的运行效果,根基实际场景应该使用严格比较。


声明:该文观点仅代表作者本人,转载请注明来自看雪专栏
最新评论 (0)
登录后即可评论