SQL隱碼攻擊原理及程式碼分析(二)

雪痕*發表於2020-07-09

前言

上一篇文章中,對union注入、報錯注入、布林盲注等進行了分析,接下來這篇文章,會對堆疊注入、寬位元組注入、cookie注入等進行分析。第一篇文章地址:SQL隱碼攻擊原理及程式碼分析(一)
如果想要了解Access的詳細手工注入過程,可以看我的這篇文章:https://www.cnblogs.com/lxfweb/p/12643011.html
如果想要了解MySQL的詳細手工注入過程,可以看我的這篇文章:https://www.cnblogs.com/lxfweb/p/12655316.html
如果想要了解SQL server的詳細手工注入過程,可以看我的這篇文章:https://www.cnblogs.com/lxfweb/p/12675023.html

SQL隱碼攻擊原理

SQL隱碼攻擊漏洞的產生需要滿足兩個條件

  1. 引數使用者可控:前端傳給後端的引數內容是使用者可以控制的。
  2. 引數帶入資料庫查詢:傳入的引數拼接到SQL語句並帶入資料庫查詢。
    所以在實際環境中開發者要秉持“外部引數皆不可信原則”進行開發。

幾種常見的SQL隱碼攻擊

堆疊查詢注入

先說一下堆疊查詢,堆疊查詢可以執行多條語句,多語句之間以分號隔開。堆疊注入就是利用這個特點,在第二條SQL語句中構造自己要執行的句子。
然後看程式碼

<?php
try {
    $conn = new PDO("mysql:host=localhost;dbname=dvwa", "root", "XFAICL1314");
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $stmt = $conn->query("SELECT * FROM users where `user_id`='" . $_GET['id']."'");
    $result = $stmt->setFetchMode(PDO::FETCH_ASSOC);
    foreach ($stmt->fetchAll() as $k => $v) {
        foreach ($v as $key => $value) {
            echo $value;
        }
    }
    $dsn = null;
}
catch (PDOException $e)
{
    echo "error";
}
$conn = null;
?>

在堆疊注入頁面中,程式獲取GET引數id,使用PDO的方式進行資料查詢,但是還是將id拼接到SQL語句中,導致POD沒起到預編譯的效果。程式仍然存在SQL隱碼攻擊。使用PDO執行SQL語句時,可以執行多條語句,但只返回第一條執行的結果。所以第二條語句中可以使用時間盲注等來會獲取資料。時間注入上一篇文章分析了。
所以我們們構造的語句為:
';select if(substr(user(),1,1)=0x72,sleep(5),1)%23


我們發現構造的時間注入語句成功執行,之後可以通過這種方法猜解出,庫名,表名,欄位及內容。

寬位元組注入攻擊

先說一下寬位元組注入原理,如果我們注入的引數為字元型,我們構造自己的SQL語句的時候需要用單引號閉合前面的SQL語句,但是我們們輸入的單引號被轉義(反斜槓)了,導致引數無法逃逸單引號的包圍,一般情況是沒有SQL隱碼攻擊的,不過有一個特例,那就是當資料庫的編碼為GBK時,可能存在寬位元組注入,具體操作是先在url後新增%df,在新增單引號,因為反斜槓的編碼為%5c,而在GBK編碼中,%df%5c是繁體字"綅"。所以單引號逃逸,就可以執行我們們構造的SQL語句了。
然後看程式碼

<?php
$conn = mysql_connect('localhost','root','XFAICL1314') or die('abd!');
mysql_select_db('dvwa',$conn) OR emMsg("資料庫連線失敗");
mysql_query("SET NAMES 'gbk'",$conn);
$id = addslashes($_GET['id']);
$sql="select * from users where user_id='$id'limit 0,1";
$result = mysql_query($sql,$conn) or die(mysql_error());
$row = mysql_fetch_array($result);
if($row)
{
    echo $row['user'].":".$row['password'];
}
else
{
    print_r(mysql_error());
}
?>
</font>
<?php
echo "<br><br>SQL : ".$sql."<br><br>";
?>

在寬位元組注入頁面中,程式獲取GET引數id,並對引數id使用addslashes()轉義,然後拼接到SQL語句中,進行查詢。現在進行嘗試。
構造語句:%df' and 1=1%23

我們發現單引號成功逃逸,之後的過程就是和union注入一樣了,猜表,猜欄位,獲得資料。

cookie注入攻擊

先看程式碼

<?php
$id=$_COOKIE['id'];
$value="1";
setcookie("id",$value);
$con=mysqli_connect("localhost","root","XFAICL1314","dvwa");
if(mysqli_connect_error())
{
    echo "連線失敗:". mysqli_connect_error();
}
$result = mysqli_query($con,"select * from users where `user_id`=".$id);
if (!$result){
    printf("Error:%s\n",mysqli_error($con));
    exit();
}
$row= mysqli_fetch_array($result);
echo $row['user'].":". $row['password'];
echo "<br>";
?>

在cookie注入頁面中,程式通過$_COOKIE獲取到引數id,並直接將id拼接到select語句中進行查詢,如果有結果,將解惑輸出到頁面。
我們開啟頁面,發現url中沒有GET引數。通過抓包發現引數id在cookie中。

接著構造語句:and 1=2 拼接到cookie中,發現報錯了,可以注入,之後也是用union注入的一些語句。

包括用order by 判斷欄位,接著使用聯合查詢。得到表名,欄位名和資料。
cookie注入還有一種情況,那就是,程式用$_REQUEST[]來接收使用者的輸入,但是程式的防禦程式只是對GET和POST接收的輸入做了防禦。沒考慮cookie,這就導致了cookie注入。和上面的操作方式一樣,只需要抓包,將有注入點的引數移到cookie中就可以了。

XFF注入攻擊

XFF注入原理是通過修改X-Forwarded-For頭對帶入系統的dns進行sql注入,從而得到網站的資料庫內容。X-Forwarded-For:簡稱XFF頭,它代表客戶端,也就是HTTP的請求端真實的IP。
這裡用墨者學院的XFF注入靶場來做演示。
開啟靶場,發現是登陸頁面,隨便輸入賬號和密碼。發現返回客戶機ip,猜測是由XFF控制。

抓包,新增XFF頭,改為1.1.1.1,發現也更改,說明存在XFF注入。

接著使用報錯注入的方法,用updataxml()等函式將我們需要的資料查詢出來,詳細查詢過程這裡就不寫了,查詢到的賬號密碼的語句為:

' and updatexml(1,concat(0x7e,(select concat(username,0x7e,password) from user limit 0,1) ,0x7e),1) or '1'='1

小結

兩篇文章將常見的幾種SQL隱碼攻擊都簡單分析了一遍,並構造了相關有缺陷的程式碼用來加深理解。希望對大家有所幫助。
參考文獻:《Web安全攻防》

相關文章