首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

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

01

简介

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

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

02

PHP弱类型是什么

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

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

03

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进行比较:

松散比较(==)情况

严格比较(===)情况

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

04

实战中导致的漏洞解析

下面以实战中遇到的真实场景为例介绍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和case3保持$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和case3分支,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”;

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

变相信息泄露

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

那么我们来扩展一下:

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

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

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

这样既可通过反证法采集目标信息了,当然还有其他扩展大家可以自己开开脑洞。

其他

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

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

06

防护方案

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

05

参考链接

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

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

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券