原标题:代码审计Day13 - 特定场合下addslashes函数的绕过

前言

大家好,我们是红日安全-代码审计小组。最近我们小组正在做一个PHP代码审计的项目,供大家学习交流,我们给这个项目起了一个名字叫PHP-Audit-Labs。现在大家所看到的系列文章,属于项目第一阶段的内容,本阶段的内容题目均来自PHP SECURITY CALENDAR 2017。对于每一道题目,我们均给出对应的分析,并结合实际CMS进行解说。在文章的最后,我们还会留一道CTF题目,供大家练习,希望大家喜欢。下面是第13篇代码审计文章:

Day 13 - Turkey Baster

代码如下:

这是一道典型的用户登录程序,从代码来看,考察的应该是通过SQL注入绕过登陆验证。代码第33行,通过POST方式传入user和passwd两个参数,通过isValid()来判断登陆是否合法。我们跟进一下isValid()这个函数,该函数主要功能代码在第12行-第22行,我们看到13行和14行调用sanitizeInput()针对user和password进行相关处理。

跟进一下sanitizeInput(),主要功能代码在第24行-第29行,这里针对输入的数据调用addslashes函数进行处理,然后再针对处理后的内容进行长度的判断,如果长度大于20,就只截取前20个字符。addslashes函数定义如下:

addslashes— 使用反斜线引用字符串

stringaddslashes( string$str)

作用:在单引号(')、双引号(")、反斜线()与 NUL(NULL字符)字符之前加上反斜线。

我们来看个例子:

那这题已经过滤了单引号,正常情况下是没有注入了,那为什么还能导致注入了,原因实际上出在了substr函数,我们先看这个函数的定义:

substr— 返回字符串的子串

stringsubstr( string$string, int$start[, int$length] )

作用:返回字符串string由start和length参数指定的子字符串。

我们来看个例子:

那么再回到这里,我们知道反斜杠可以取消特殊字符的用法,而注入想要通过单引号闭合,在这道题里势必会引入反斜杠。所以我们能否在反斜杠与单引号之间截断掉,只留一个反斜杠呢?答案是可以,我们看个以下这个例子。

在这个例子中,我们直接使用题目代码中的过滤代码,并且成功在反斜杠和单引号之间截断了,那我们把这个payload带入到题目代码中,拼接一下第17行-第19行代码中的sql语句。

selectcount(p) fromuseruwhereuser='1234567890123456789' AND password = '$pass'

这里的sql语句由于反斜杠的原因,user = '1234567890123456789'最后这个单引号便失去了它的作用。这里我们让pass=or 1=1#,那么最后的sql语句如下:

selectcount(p) fromuserwhereuser='1234567890123456789' AND password = 'or1=1#'

这时候在此SQL语句中,user值为1234567890123456789' AND password =,因此我们可以保证带入数据库执行的结果为True,然后就能够顺利地通过验证。

所以这题最后的payload如下所示:

user=1234567890123456789'&passwd=or 1=1#

这里的实例分析,我们选择苹果CMS视频分享程序 8.0进行相关漏洞分析。漏洞的位置是在inccommontemplate.php,我们先看看相关代码:

这里代码的第三行-第四行位置,$lp['wd']变量位置存在字符串拼接,很明显存在sql注入,但是这个cms具有一些通用的注入防护,所以我们从头开始一步步的看。

首先在incmodulevod.php文件中的,我们看到第一行代码当$method=search成立的时候,进入了第3行中的be("all", "wd")获取请求中wd参数的值,并且使用chkSql()函数针对wd参数的值进行处理。部分关键代码如下所示:

跟进一下be()函数,其位置在inccommonfunction.php文件中,关键代码如下:

这部分代码的作用就是对GET,POST,REQUEST接收到的参数进行addslashes的转义处理。根据前面针对be("all", "wd")的分析,我们知道wd参数的值是通过REQUEST方式接收,并使用addslashes函数进行转义处理。再回到incmodulevod.php文件中的,我们跟进一下chkSql()函数,该函数位置在inccommon360_safe3.php文件中,具体代码如下:

分析一下这部分代码的作用,其实就是在第8行-第12行针对接收到的的变量进行循环的urldecode(也就是url解码)动作,然后在第15行,使用StopAttack函数解码后的数据进行处理,最后将处理后的数据通过htmlEncode方法进行最后的处理,然后返回处理之后的值。

我们先跟进一下StopAttack函数,该函数位置在inccommon360_safe3.php文件中,我们截取部分相关代码如下:

我们看到代码的第13行-第19行调用正则进行处理,而相关的正则表达式是$ArrFiltReq变量。这里第13行的$ArrFiltReq变量就是前面传入的$getfilter,即语句变成:

preg_match("/".$getfilter."/is",1)

我们跟进一下$getfilter变量。该变量在inccommon360_safe3.php文件中,我们截取部分相关代码如下:

这串代码的功能显而易见,就是检测GET,POST,COOKIE中的恶意数据。刚刚在chkSql()函数最后有串代码是:return htmlEncode($s);,我们跟进一下htmlEncode函数。该函数位置在inccommonfunction.php文件中,相关代码如下:

这段代码的功能是针对&、'、空格、"、TAB、回车、换行、大于小于号等符号进行实体编码转换。但是这里百密一疏,没有针对其他的空白字符和反斜杠进行处理。这里先埋下一个伏笔,我们继续往下看。

首先注入点是在inccommontemplate.php,相关代码如下:

我们继续看看这个$lp['wd']的值是怎么获取的,在inccommontemplate.php文件中找到其相关代码:

上图第13行,当P['wd']不为空的时候,$lp['wd']是从P["wd"]中获取到数据的。根据前面我们的分析,在incmodulevod.php文件中的存在这样一行代码:$tpl->P["wd"] =$wd;

而wd是可以从REQUEST中获取到,所以这里的wd实际上是可控的。

漏洞验证

现在我们需要针对漏洞进行验证工作,这就涉及到POC的构造。在前面分析中,我们知道htmlEncode针对&、'、空格、"、TAB、回车、换行、大于小于号进行实体编码转换。但是这里的注入类型是字符型注入,需要引入单引号来进行闭合,但是htmlEncode函数又对单引号进行了处理。因此我们可以换个思路。

我们看到注入攻击的时候,我们的$lp['wd']参数可以控制SQL语句中的两个位置,因此这里我们可以通过引入反斜杠进行单引号的闭合,但是针对前面的分析我们知道其调用了addslashes函数进行转义处理,而addslashes会对反斜杠进行处理,但是这里对用户请求的参数又会先进行url解码的操作,因此这里可以使用双url编码绕过addslashes函数。

POST/maccms8/index.php?m=vod-searchHTTP/1.1

Host:127.0.0.1

User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3

Accept-Encoding:gzip, deflate

Content-Type:application/x-www-form-urlencoded

Content-Length:98

Connection:keep-alive

Upgrade-Insecure-Requests:1

wd=))||if((select%0b(select(m_name)``from(mac_manager))regexp(0x5e61)),(`sleep`(3)),0)#%25%35%63

payload传到程序里,经过拼接后的数据库语句如下所示:

漏洞修复

这里的防御手段其实已经很多了,但就是因为这么多防御手段结合在一起出现了有趣的绕过方式。

functionhtmlEncode($str)

{

if(!isN($str)){

$str=str_replace(chr(38), "&",$str);

$str=str_replace(">", ">",$str);

$str=str_replace("

$str=str_replace(chr(39), "'",$str);

$str=str_replace(chr(32), " ",$str);

$str=str_replace(chr(34), """,$str);

$str=str_replace(chr(9), " ",$str);

$str=str_replace(chr(13), "
",$str);

$str=str_replace(chr(10), "
",$str);

$str=str_replace(chr(92), "
",$str); //新增修复代码

}

return$str;

}

反斜杠的ascii码是92,这里新增一行代码处理反斜杠。

结语

看完了上述分析,不知道大家是否对htmlentities函数在使用过程中可能产生的问题,有了更加深入的理解,文中用到的代码可以从这里下载,当然文中若有不当之处,还望各位斧正。如果你对我们的项目感兴趣,欢迎发送邮件到hongrisec@gmail.com联系我们。Day13的分析文章就到这里,我们最后留了一道CTF题目给大家练手,题目如下:

//index.php

require'db.inc.php';

functiondhtmlspecialchars($string) {

if(is_array($string)) {

foreach($stringas$key=>$val) {

$string[$key] =dhtmlspecialchars($val);

}

}

else{

$string=str_replace(array('&', '"', '', '(', ')'), array('&', '"', '', '(', ')'), $string);

if(strpos($string, '') !==false) {

$string=preg_replace('/&((#(d{3,5}|x[a-fA-F0-9]{4}));)/', '&1', $string);

}

}

return$string;

}

functiondowith_sql($str) {

$check=preg_match('/select|insert|update|delete|'|/*|*|../|./|union|into|load_file|outfile/is', $str);

if($check) {

echo"非法字符!";

exit();

}

return$str;

}

// 经过第一个waf处理

foreach($_REQUESTas$key=>$value) {

$_REQUEST[$key] =dowith_sql($value);

}

// 经过第二个WAF处理

$request_uri=explode("?", $_SERVER['REQUEST_URI']);

if(isset($request_uri[1])) {

$rewrite_url=explode("&", $request_uri[1]);

foreach($rewrite_urlas$key=>$value) {

$_value=explode("=", $value);

if(isset($_value[1])) {

$_REQUEST[$_value[0]] =dhtmlspecialchars(addslashes($_value[1]));

}

}

}

// 业务处理

if(isset($_REQUEST['submit'])) {

$user_id=$_REQUEST['i_d'];

$sql="select * from ctf.users where id=$user_id";

$result=mysql_query($sql);

while($row=mysql_fetch_array($result))

{

echo"

";

echo"

". $row['name'] . "";

echo"

";

}

}

?>//db.inc.php

$mysql_server_name="localhost";

$mysql_database="ctf"; /** 数据库的名称 */

$mysql_username="root"; /** MySQL数据库用户名 */

$mysql_password="root"; /** MySQL数据库密码 */

$conn=mysql_connect($mysql_server_name, $mysql_username,$mysql_password,'utf-8');

?>//ctf.sql

# Host: localhost (Version: 5.5.53)

# Date: 2018-08-1821:42:20

# Generator: MySQL-Front 5.3(Build 4.234)

/*!40101 SET NAMES utf8 */;

#

# Structure for table"users"

#

DROPTABLEIF EXISTS `users`;

CREATETABLE`users` (

`Id` int(11) NOTNULLAUTO_INCREMENT,

`name` varchar(255) DEFAULT NULL,

`pass` varchar(255) DEFAULT NULL,

`flag` varchar(255) DEFAULT NULL,

PRIMARY KEY (`Id`)

) ENGINE=MyISAM AUTO_INCREMENT=2DEFAULT CHARSET=utf8;

#

# Data for table"users"

#

/*!40000 ALTER TABLE `users` DISABLE KEYS */;

INSERTINTO`users` VALUES(1,'admin','qwer!@#zxca','hrctf{R3qu3st_Is_1nterEst1ng}');

/*!40000 ALTER TABLE `users` ENABLE KEYS */;参考文章

PHP的两个特性导致waf绕过注入

request导致的安全性问题分析返回搜狐,查看更多

责任编辑:

mysql 绕过addslashes_代码审计Day13 - 特定场合下addslashes函数的绕过相关推荐

  1. PHP ctf addslashes,[红日安全]代码审计Day13 - 特定场合下addslashes函数的绕过

    本文由红日安全成员: l1nk3r 编写,如有不当,还望斧正. 前言 大家好,我们是红日安全-代码审计小组.最近我们小组正在做一个PHP代码审计的项目,供大家学习交流,我们给这个项目起了一个名字叫 P ...

  2. 特定场景下取代if-else和switch的方式

    look-up表代替if-else 比如某平台的信用分数评级: 超过700-950,信用极好, 650-700信用优秀, 600-650信用良好, 550-600信用中等, 350-550信用较差. ...

  3. swoole mysql 并发_如何用Swoole测试MySQL在特定SQL下的并发性能

    场景描述 从全文检索或者缓存中获取ID,根据ID查询数据库获取基础信息,进行页面展示 SQL:select * from table where id in(id1,id2,id3...id40) 此 ...

  4. 如何查找特定目录下最大的文件及文件夹

    如何查看特定目录下大小在前10位的文件 find 目录 -ls |sort -nrk7  |head 参数说明如下: -ls    True;  list  current  file  in ls ...

  5. 特定场景下Yolo改进算法:Poly-Yolo

    论文名称:Poly-YOLO: higher speed, more precise detection and instance segmentation for YOLOv3 论文地址:https ...

  6. mysql 必须安装php_非root模式下安装mysql php小记

    假设你的home目录为/home/work mysql-server 安装 1. 下载mysql.tar.gz wget http://dev.mysql.com/get/Downloads/MySQ ...

  7. mysql ibdata作用_mysql data文件夹下ibdata1 文件作用

    ibdata1这个文件超级大, 查了一下, 大概的作用如下 是储存的格式 INNODB类型数据状态下, ibdata用来储存文件的数据 而库名的文件夹里面的那些表文件只是结构而已 由于mysql4.1 ...

  8. 【MySQL】在centos7 纯IPv6环境下,安装mysql5.7

    参考链接:https://mirrors6.tuna.tsinghua.edu.cn/help/mysql/ 服务器环境: Centos7 纯IPv6环境(不能与IPv4互通) 按照 https:// ...

  9. C++中,有哪4种与类型转换相关的关键字?各有什么特点?应该在什么场合下使用?

    C++中,四个与类型转换相关的关键字:static_cast.const_cast.reinterpret_cast.dynamic_cast. 一.static_cast 特点:静态转换,在编译处理 ...

最新文章

  1. vc连接数据库,对数据的基本操作
  2. Java Se:自定义ClassLoader
  3. 第一篇读书笔记,关于UML和模式应用(1)--书籍简介
  4. 练习题 James and Dominoes
  5. 简易zlib库解压缩函数封装
  6. Redis操作hash类型
  7. mysql索引 倒排表_mysql倒排的优化
  8. 自己常用的分页SQL
  9. proteus微型计算机梯形波,接口芯片dac0832的应用 三角波、梯形波两种波形.doc
  10. QXDM5 中 Qt5WebKit.dll 丢失问题解决办法
  11. git操作时:遇到提示Unable to create ‘D:/xxx/.git/index.lock‘: File exists.的解决办法解决方案
  12. linux查看网卡百兆还是千兆网卡,linux下如何看网卡是千兆还是百兆的?
  13. C++ API中文文档分享
  14. python迅雷远程下载页面_迅雷远程下载
  15. 裁判文书网数据采集爬虫2021-08
  16. android apk u盘升级_android升级安装包--包解析错误
  17. OA协同办公系统-day01
  18. 利用redis生成订单号
  19. MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)
  20. Maven与Git速识

热门文章

  1. 全网最全Flutter的学习文档,不可转载
  2. java中右移_Java中的按位右移运算符
  3. 全球顶尖技术会议QCon上海2013开幕在即
  4. 「励志文章」我们都不是神的孩子
  5. Fiddler抓包手机代理配置
  6. 关于spyder闪退打不开的解决方法
  7. 蒙特卡洛方法、蒙特卡洛树搜索(Monte Carlo Tree Search, MCTS) 学习
  8. webLogic内存溢出解决方案
  9. linux内核中配置关闭无线功能
  10. SQL数据类型 bigint、int、mediumint、smallint、tinyint 取值范围,占位