寬位元組SQL注入原理
0x01:
經典的SQL注入利用的是沒有任何防範措施的PHP使用SQL查詢語句時可以通過URL輸入造成該語句恆成立,從而可以獲得資料庫中的其他資訊。
舉個例子:
<?php
$name=$_GET['name'];
$conn=mysql_connect('localhost','root','root');
if($conn==null){exit("connect error !<br>");}
mysql_select_db("aaa",$conn);
$sql="select * from a1 where name='" .$name."'";
$result=mysql_query($sql,$conn);
while($val=mysql_fetch_row($result)){
print_r($val);
print("<br>");
}
?>
0x02:
如果使用轉義符號對傳入變數進行過濾的話,則經典的SQL注入語句就不能生效了。
這些轉義函式包括:
addslashes() :
函式返回在預定義字元之前新增反斜槓的字串。 預定義字元是:單引號(') 雙引號(") 反斜槓(\) NULL
mysql_real_escape_string() :
函式轉義 SQL 語句中使用的字串中的特殊字元。下列字元受影響:
\x00 \n \r \ ' " \x1a
mysql_real_escape_string() :
函式轉義 SQL 語句中使用的字串中的特殊字元。下列字元受影響:
\x00 \n \r \ ' " \x1a
如果成功,則該函式返回被轉義的字串。如果失敗,則返回 false。
這時候,我們就只能利用另一種被稱為寬位元組注入的方法進行注入了。
0x03:
寬字元是指多個位元組寬度的編碼,如UNICODE、GBK、BIG5等。轉義函式在對這些編碼進行轉義時會丟掉轉義字元“\”(將它轉換為%5C),你可以在它前面再輸入一個單字元編碼與它組成一個新的多字元編碼,使得轉義實際上沒有發生作用(轉義就是要留下“\”防範注入的)。
舉個例子:
輸入……php?name=a%df’ or 1=1;%20%23
轉義函式會將%df’改成%df\’,如果你的編碼是GBK,%df\’就對應著%df%5c’,在GBK中,這兩個位元組%df%5c又對應著一個漢字“運”,也就是說\已經失去了作用,a%df’被認為是a運’,成功消除了轉義函式的影響。
0x04:
總結一下,可以進行寬位元組注入的條件有兩個:
(1)需要設定寬節字符集。
(2)這個寬位元組字符集第二個字元編碼的%5c與第一個字元編碼組成的多字元編碼要有意義。
0x05:
舉一個典型的寬位元組注入例子:
<?php
$name=$_GET['name'];
$name=addslashes($name);
$conn = mysqli_connect('localhost', 'root', 'root', 'test');//連線MySQL服務
if (!$conn) {
die('Could not connect to MySQL: ' . mysqli_connect_error());
}
$conn->set_charset("GBK");
@mysql_select_db("test",$conn);
$sql="select * from user where username='".$name."'";
$result=mysqli_query($conn,$sql);
@$row = mysqli_fetch_assoc($result);
echo "Hello ".$row['username']."</br>";
echo "Your password is:".$row['password']."</br>";
?>
若將這段程式碼儲存為1.php,資料庫如圖設定:
則注入語句:
..php?name=a%df’ or 1=1; %20%23
得到結果: