PHP代码审计04之strpos函数使用不当
前言
根据红日安全写的文章,学习PHP代码审计的第四节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完题目会用一个实例来加深巩固,这是之前写的,有兴趣可以去看看:
PHP代码审计01之in_array()函数缺陷
PHP代码审计02之filter_var()函数缺陷
PHP代码审计03之实例化任意对象漏洞
漏洞分析
现在咱们看第一题,代码如下:
<?php
class Login {
public function __construct($user, $pass) {
$this->loginViaXml($user, $pass);
}
public function loginViaXml($user, $pass) {
if (
(!strpos($user, '<') || !strpos($user, '>')) &&
(!strpos($pass, '<') || !strpos($pass, '>'))
) {
$format = '<?xml version="1.0"?>' .
'<user v="%s"/><pass v="%s"/>';
$xml = sprintf($format, $user, $pass);
$xmlElement = new SimpleXMLElement($xml);
// Perform the actual login.
$this->login($xmlElement);
}
}
}
new Login($_POST['username'], $_POST['password']);
?>
题目分析
我们来看上面的代码,看第1214行,这里通过格式话字符串的方式,使用XML结构来存储用户的登陆信息,这样很容易造成注入,再看上面的代码,最后一行实例化了这个类,17行调用了login来进行登陆操作。下面到重点了,看代码810行,这里用到了strpos()函数来进行过滤<>符号,这个函数的用法如下:


如下:
<?php
var_dump(strpos("abcd","a"));
var_dump(strpos("abcd","y"));
?>

我们发现,找到子字符串的话就会返回对应的下标,没找到会返回false。而在PHP中,0和false的取反都是true,这点需要我们注意,这道题目就是开发者在使用这个函数时,只考虑了返回false的情况,而没有考虑当首字符匹配时返回0的情况。导致了过滤被绕过从而实施XML攻击。
现在知道了如何绕过,那么构造payload:user=<"><injected-tag%20property="&pass=<injected-tag>
为了更好的理解,来看一下构造这个payload时,strpos()函数的返回结果如下:
$user='<"><injected-tag property="';
$pass='<injected-tag>';
var_dump(strpos($user,'<'));
var_dump(!strpos($user,'<'));
var_dump(strpos($user,'>'));
var_dump(!strpos($user,'>'));

是不是理解了一些呢,现在看上面的代码,思考一下如果我们使用这个payload会返回什么呢。
var_dump((!strpos($user, '<') || !strpos($user, '>')) &&
(!strpos($pass, '<') || !strpos($pass, '>')));

返回了true,其实就是var_dump((true || false) &&(true || false))
成功绕过,可以进行XML注入。
通过上面的学习讲解是不是对strpos()函数了解更深一些了呢?下面咱们看一个实例,这个实例也是设计者没有考虑周全,导致任意用户密码重置。
实例分析
这次的实例是DeDecms V5.7SP2正式版,源码可以从网上下载搭建,这个很容易找到,就不详细说了,上面说了,这个漏洞是任意用户密码重置,下面我们来分析代码,漏洞的触发点在 member/resetpassword.php 文件中,是因为对接收的参数safeanswer没有进行严格的类型判断导致被绕过。下面看代码:

现在来对上面的代码做一个分析,当$dopost==safequestion时,通过$mid对应的id值来查询当前用户的safequestion,safeanswer,userid,email等值,现在来看第84行,这里的意思是当我们传入的安全问题和安全答案等于之前设置的值时,就传入sn()函数,重点来了,注意看,这里用的是双等于来验证,而没有用三等于,所以,这里是可以被绕过的。当用户没有设置安全问题时,那么默认情况安全问题值为0,安全答案值为null,这里指的是数据库中的值,而我们如果传入空值时,那么就是空字符串,84行语句也就变成了if('0' == '' && null == ''),也就是if(false&&true),所以我们只需要让前半部分转为true就可以了,通过测试如下图,都可以和0比较等于true。
if("0"=="0.0"){echo "成功1"."\n";}
if("0"=="0e1"){echo "成功2"."\n";}
if("0"=="0e12"){echo "成功3"."\n";}
if("0"=="0e123"){echo "成功4"."\n";}
if("0"=="0."){echo "成功5"."\n";}
上面的几种payload均能使得 safequestion 为 true,成功进入sn()函数

我们跟进sn()函数,代码如下:

在sn()内部,会根据id到pwd_tmp表中判断是否存在对应的临时密码记录,根据结果确定分支,走向 newmail 函数。现在我们假设第一次来进行忘记密码操作,那么现在的$row的值应该为空,也就会进入if(!is_array($row))分支,然后在newmail()函数中执行INSERT操作,具体代码在这个文件的上面,如图:

这个代码的功能是发送邮件到相关邮箱,并插入一条记录到dede_pwd_tmp表中,漏洞触发点在这里,我们现在看92~95行。如果 ($send == 'N') 这个条件为真,那就跳转到修改页,通过 ShowMsg 打印出修改密码功能的链接。拼接的url为:
http://www.dmsj.com/DedeCMS-V5.7-UTF8-SP2/uploads/member/resetpassword.php?dopost=getpasswd&id=$mid&key=$randval
现在咱们跟进dopost=getpasswd去看看,在member/resetpassword.php文件中,代码如下:

这里用empty()函数来判断$id和$row是否为空,如果不为空的话,就继续向下走,进入if(empty($setp))中,先判断是否超时,如果没超时的话进入修改页面,我圈起来了,现在跟过去看一下具体代码如下:

发现数据包中 $setp=2,所以代码功能又回到了member/resetpassword.php文件中,如下:

分析上面代码,我们发现如果传入的$key和数据库中的$row['pwd']相同时,则完成密码的重置,也完成了攻击的分析过程。
漏洞验证
现在注册两个账号,分别是test123和test456,查看mid的值如下,test456的mid为3。test123的mid为2。

我现在登陆test456账户,访问咱们构造的payload。来修改test123的密码。
http://www.dmsj.com/DedeCMS-V5.7-UTF8-SP2/uploads/member/resetpassword.php?dopost=safequestion&safequestion=0e1&safeanswer=&id=2
我现在登陆的是test456账户,访问url抓包。

获取到了key值,然后来访问修改密码的url:
http://www.dmsj.com/DedeCMS-V5.7-UTF8-SP2/uploads/member/resetpassword.php?dopost=getpasswd&id=2&key=xy8UzeOI

我们发现到了修改密码的页面,直接可以修改密码。我们将密码修改为abcdef,然后登陆test123,发现登陆成功,密码成功被修改。

小结
通过这篇文章的学习与讲解,是不是对strpos()函数和PHP弱类型绕过有了一定的了解了呢?下一篇文章会对escapeshellarg与escapeshellcmd使用不当来进行学习与讲解,一起努力吧!
PHP代码审计04之strpos函数使用不当的更多相关文章
- ***用php的strpos() 函数判断字符串中是否包含某字符串的方法
判断某字符串中是否包含某字符串的方法 if(strpos('www.idc-gz.com','idc-gz') !== false){ echo '包含'; }else{ echo '不包含'; } ...
- PHP strpos() 函数
定义和用法 strpos() 函数返回字符串在另一个字符串中第一次出现的位置. 如果没有找到该字符串,则返回 false. 语法 strpos(string,find,start) 参数 描述 str ...
- 字符串处理——strpos()函数
strpos() 函数返回字符串在另一个字符串中第一次出现的位置. 大小写敏感 如果没有找到该字符串,则返回 false. strpos(string,find,start) string 必需:规 ...
- PHP strlen()函数和strpos()函数
strlen() 函数返回字符串的长度(字符数) 代码: <?php echo strlen("Hello world!"); ?> 上面的代码将输出:12 ...
- php中strpos()函数
1,strpos()函数 mixed strops(]) 返回needle在haystack中首次出现的数字位置,从0开始查找,区分大小写. 参数:haystack,在该字符串中进行查找. needl ...
- php strpos() 函数介绍与使用方法详解
本文主要和大家介绍PHP中mb_strpos的使用技巧,通过使用语法以及实例给大家详细分析了用法,需要的朋友参考学习下.希望能帮助到大家.mb_strpos(PHP 4 >= 4.0.6, PH ...
- php strpos()函数 语法
php strpos()函数 语法 作用:寻找字符串中某字符最先出现的位置.大理石平台怎么选择 语法:strpos(string,find,start) 参数: 参数 描述 string 必需 ...
- PHP代码审计02之filter_var()函数缺陷
前言 根据红日安全写的文章,学习PHP代码审计审计的第二节内容,题目均来自PHP SECURITY CALENDAR 2017,讲完这个题目,会有一道CTF题目来进行巩固,外加一个实例来深入分析,想了 ...
- php基础04:字符串函数
<?php //1.strlen(),strlen() 函数返回字符串的长度,以字符计. echo strlen("hello world"); echo "< ...
随机推荐
- phpcms v9.6.0任意文件上传漏洞
距离上一次写博客已经过去很长一段时间了,最近也一直在学习,只是并没有分享出来 越来越发现会的东西真的太少了,继续努力吧. 中午的时候遇到了一个站点,看到群里好多人都在搞,自己就也去试了试,拿下来后发 ...
- Processing 状态量控制动画技巧
之前在CSDN上发表过: https://blog.csdn.net/fddxsyf123/article/details/62848357
- 关于SpringBoot的一点笔记
@SpringBootApplication /** * @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用 */ @SpringBootAppl ...
- gRPC-Protocol语法指南
语法指南 (proto3) Defining A Message Type Scalar Value Types Default Values Enumerations Using Other Mes ...
- Android App 侧边栏菜单的简单实现
效果图 Layout 注意事项 想要实现侧边栏,需要配合使用DrawerLayout.因为会用到嵌套布局,所以根布局不能是 ConstraintLayout,最好使用 LinearLayout 布局. ...
- [VBA原创源代码] excelhome 对花名册进行分类
最近在学习<菜鸟谈VBA最最基础入门<原创>>,其中第22节有一个VBA编程作业,实现对花名册进行分类. 自己花了点时间,自己丫丫学步,终于实现出来. 在原创聚集地cnblog ...
- 013 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 07 基本数据类型变量的存储
013 01 Android 零基础入门 01 Java基础语法 02 Java常量与变量 07 基本数据类型变量的存储 变量和它的值如何在内存中进行存储的? 前面学习过:Java中的数据类型分为基本 ...
- Allegro PCB 转 PADS Layout
操作系统:Windows 10 x64 工具1:Allegro PCB Design XL (legacy) version 16.6-2015 工具2:PADS Layout VX.2.3 参考1: ...
- 【题解】 [EZEC-4]求和
对于百分之十的数据:随便过. 下面推式子: \[\sum_{i=1}^n\sum_{j=1}^n\gcd(i,j)^{i+j} \] \[=\sum_{d=1}^n\sum_{i=1}^n\sum_{ ...
- AD(Altium Designer)PCB布线中的“格式刷”,助力快速布局布线
摘要:在AD(Altium Designer)进行电路板布线时,孔丙火(微信公众号:孔丙火)经常会碰到电路中有相同功能的模块,比如2路相同的RS485通信电路.多路相同继电器输出电路.多路相同的输入电 ...