addslashes防注入的绕过案例(AFSRC获奖白帽子情痴)
代码审计中遇到的一些绕过addslashes的案例
From ChaMd5安全团队核心成员 无敌情痴
MMMMM叫我写一篇文章发到公众号,然而我是ChaMd5安全团队第一弱的大菜逼,于是就写篇基础的审计文章,在实际情况中,会出现各种各样的绕过防注入的手法,我这里只是列举了我在实际审计中遇到的比较常见的绕过方法。
前段时间审计过不少PHP开源系统,而很多PHP开源系统针对sql注入都喜欢用addslashes来防止注入,也就是把’ “ %00 这些符号转义在前面加个。
根据实际的情况,也有各种绕过addslashes的方法,今天写写几个代码审计中绕过addslashes的实例。
第一种情况:虽然使用了addslashes转义,但是缺没有加引号,直接无视过滤。
$money=$_GET['money'];//相当于交易中的支付金额
mysql_query("update `go_member`set money=money+$money where uid='$uid'"); //会员表加款
这套系统是有对$_GET,$_POST,$_COOKIE这些可控数据做addslashes的,但是这里的$money便利在带入sql语句的缺没有加引号,本来addslashes防止sql注入的原理就是转义’ “ %00这些有特殊含义的符号,防止它逃出引号,但是这里没有加引号,所以可以直接构造任意sql语句了,无视过滤
成功得到数据
第二种情况:宽字节注入
具体原理可以参考一下P神的文章
http://www.freebuf.com/articles/web/31537.html
简单的说有两种情况可能会造成宽字节注入,这样设置数据库的字符集为gbk
mysql_query(“SET NAMES ‘gbk'”);
<?php
if(is_null($_REQUEST[‘username’]) || is_null($_REQUEST[‘password’]))
{
die();
}
$link=mysql_connect(“localhost”,”root”,”root”);
mysql_query(“SET NAMES ‘gbk'”);
mysql_select_db(“test”,$link);
$username=$_REQUEST[‘username’];
$password=md5($_REQUEST[‘password’]);
$sql=”select count(*) as num from admin where name='”.addslashes($username).”‘ and pass='”.$password.”‘”;
$query=mysql_query($sql);
$res=mysql_fetch_array($query);
$count=$res[‘num’];
if($count==1)
{
echo “login success”;
}
else
{
echo “login failed”;
}
?>
比如说这段代码就存在宽字节注入,或者是在使用iconv,mb_convert_encoding转换字符编码函数导致宽字节注入,来一个自己审计中发现的宽字节注入案例
elseif($act == 'get_company')
{
$type=trim($_GET['type']);
$key=trim($_GET['key']);
if (strcasecmp(QISHI_DBCHARSET,"utf8")!=0)
{
$key=iconv("utf-8",QISHI_DBCHARSET,$key);
}
if ($type=="getuname")
{
$sql = "select * from ".table('members')." AS m LEFT JOIN ".table('company_profile')." AS c ON m.uid=c.uid where m.username like '{$key}%' AND m.utype=1 LIMIT 20";
}
elseif ($type=="getcomname")
{
$sql = "select * from ".table('company_profile')." where companyname like '%{$key}%' LIMIT 30";
}
else
{
exit();
}
$result = $db->query($sql);
while($row = $db->fetch_array($result))
{
if (empty($row['companyname']))
{
continue;
}
$row['addtime']=date("Y-m-d",$row['addtime']);
$row['company_url']=url_rewrite('QS_companyshow',array('id'=>$row['id']));
$info[]=$row['id']."%%%".$row['companyname']."%%%".$row['company_url']."%%%".$row['addtime'];
}
if (!empty($info))
{
exit(implode('@@@',$info));
}
}
同样这套系统也是有做addslashes的,但是
$key=iconv("utf-8",QISHI_DBCHARSET,$key);
$key这个可控变量在addslashes之后用iconv函数转换编码,造成宽字节注入
第三种情况是可控做了addslashes之后,可控变量进入了各种函数比如,base64_decode,urldecode,json_encode,stripslashes,举个案例以前在审计某套系统的时候,发现那套系统有这样一个url解码函数,于是搜索了一下,发现这套系统很多地方都调用了这个函数,所有调用这个函数对可控变量进行处理之后带入sql语句的地方都存在sql注入
function unescape($str){
$code = PHP_OS == 'Linux' ? 'UCS-2BE' : 'UCS-2';
$str = rawurldecode($str);
preg_match_all("/%u.{4}|&#x.{4};|&#d+;|.+/U", $str, $r);
$ar = $r[0];
foreach($ar as $k => $v){
if(substr($v, 0, 2) == "%u"){
if(function_exists('mb_convert_encoding')){
$ar[$k] = mb_convert_encoding(pack("H4", substr($v, -4)), strtoupper(IN_CHARSET), "UCS-2");
}else{
$ar[$k] = iconv($code, strtoupper(IN_CHARSET).'//IGNORE', pack("H4", substr($v, -4)));
}
}elseif(substr($v, 0, 3) == "&#x"){
if(function_exists('mb_convert_encoding')){
$ar[$k] = mb_convert_encoding(pack("H4", substr($v, 3, -1)), strtoupper(IN_CHARSET), "UCS-2");
}else{
$ar[$k] = iconv($code, strtoupper(IN_CHARSET).'//IGNORE', pack("H4", substr($v, 3, -1)));
}
}elseif(substr($v, 0, 2) == "&#"){
if(function_exists('mb_convert_encoding')){
$ar[$k] = mb_convert_encoding(pack("H4", substr($v, 2, -1)), strtoupper(IN_CHARSET), "UCS-2");
}else{
$ar[$k] = iconv($code, strtoupper(IN_CHARSET).'//IGNORE', pack("H4", substr($v, 2, -1)));
}
}
}
return join("", $ar);
}
比如这里
elseif($ac == 'send'){
$userlogined or exit("{send:-1}");
$text = unescape(SafeRequest("text","get"));
$uname = unescape(SafeRequest("uname","get"));
$uid = SafeRequest("uid","get");
$setarr = array(
'in_uid' => $erduo_in_userid,
'in_uname' => $erduo_in_username,
'in_uids' => $uid,
'in_unames' => $uname,
'in_content' => $text,
'in_isread' => 0,
'in_addtime' => date('Y-m-d H:i:s')
);
inserttable('message', $setarr, 1);
echo "{send:1}";
}
$text = unescape(SafeRequest("text","get"));
$uname = unescape(SafeRequest("uname","get"));
Saferequest对变量进行addslashes,但是因为做了addslashes之后,又使用了unescape函数进行url解码,所以直接双重编码来绕过addslashes
http://127.0.0.1/xxxxxsourcepluginwebimapijson.php?ac=send&text=%2527%2520%2561%256e%2564%2520%2573%256c%2565%2565%2570%2528%2535%2529%2520%2561%256e%2564%2520%2527%2531%2527%253d%2527%2531&uname=aaa
因为这里是从$_Get接受数据,web服务器会自动进行一次url解码%2527就变成%27,%27在addslashes的时候不会被转义,但是经过addslashes之后,又进入了unescape函数对数据一次url解码,这样%27就被解码成了’,带入sql语句,成功闭合了引号。
最后再举一个字符截断绕过addslashes的案例,这个个人觉得比较有趣
这套系统也是通过addslashes来防御sql注入的
.......
$content=substr(trim($_POST["content"]),0,200);
$face=@$_POST["face"];
然后带入sql语句
mysql_query("insert into zzcms_pinglun (about,content,face,username,ip,sendtime)values('$about','$content','$face','$user','$ip','".date('Y-m-d H:i:s')."')");
这个时候有一个比较有趣的绕过思路$_POST[“content”]第两百个字符设置成’,然后被addslashes后就变成’,然后进过substr函数,只截取前两百个字符,留下了,’因为是第201个,所以就没被截取下来。sql语句中'$content','$face',$content后面的内容$face也是可控的,用闭合引号,然后$face就逃出引号造成注入
查看数据库内容,可以看到我们构造的sql语句执行成功了
- 巧用枚举类型,实现项目的多语言切换
- 影响Java调用性能有哪些因素
- 如何为可扩展系统进行Java Socket编程
- 如何使用Windows卷影拷贝服务恢复文件和文件夹
- .net字符串数组查找方式效率比较
- 使用Ring Buffer构建高性能的文件写入程序
- 一行代码调用实现带字段选取+条件判断+排序+分页功能的增强ORM框架
- PDF.NET数据开发框架实体类操作实例
- 利用Burp Suite对OWASP Juice Shop进行渗透测试
- Java同步问题面试知识学习
- Android UI控件系列:LinearLayout(线性布局)
- 使用操作符重载,生成ORM实体类的SQL条件语句
- Dance In Heap(四):一些堆利用的方法(下)
- Mac系统的Proton恶意软件:卷!土!重!来!
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python识别验证码
- 多线程爪巴虫下载进击的巨人
- 利用selenium实现自动翻页爬取某鱼数据
- 20行Python代码爬取下载应用宝所有APP软件
- 爬虫 -- 天天基金网数据简单爬取
- python爬虫-唯品会商品信息实战步骤详解
- go框架中使用CGO,docker build image打包镜像注意事项
- python爬虫汽车之家全车型及基本参数入数据库(截止50524个数据)(详解)
- C语言最全入门笔记
- 如何实现oVirt与Tungsten Fabric的集成
- 一文让你学完C++,干货收藏!!!
- 缓冲区溢出
- 指针变量的传值和传址
- 又被限速,我决定用 Serverless 搭建一款私人网盘
- C语言与C++常见面试题