SQL_約束攻擊

注:以下內(nèi)容轉(zhuǎn)載自:https://blog.csdn.net/wy_97/article/details/77972375
https://www.bilibili.com/watchlater/#/BV1Pf4y1U7Dw/p1

背景介紹

最近,我遇到了一個有趣的代碼片段,開發(fā)者嘗試各種方法來確保數(shù)據(jù)庫的安全訪問。當新用戶嘗試注冊時,將運行以下代碼:

<?php
// Checking whether a user with the same username exists
$username = mysql_real_escape_string($_GET['username']);
$password = mysql_real_escape_string($_GET['password']);
$query = "SELECT *
          FROM users
          WHERE username='$username'";
$res = mysql_query($query, $database);
if($res) {
  if(mysql_num_rows($res) > 0) {
    // User exists, exit gracefully
    .
    .
  }
  else {
    // If not, only then insert a new entry
    $query = "INSERT INTO users(username, password)
              VALUES ('$username','$password')";
    .
    .
  }
}

使用一下代碼驗證登陸信息:

<?php
$username = mysql_real_escape_string($_GET['username']);
$password = mysql_real_escape_string($_GET['password']);
$query = "SELECT username FROM users
          WHERE username='$username'
              AND password='$password' ";
$res = mysql_query($query, $database);
if($res) {
  if(mysql_num_rows($res) > 0){
      $row = mysql_fetch_assoc($res);
      return $row['username'];
  }
}
return Null;

安全考慮:

  • 過濾用戶輸入?yún)?shù)了嗎? — 完成檢查
  • 使用單引號(’)來增加安全性了嗎? — 完成檢查

按理說應該不會出錯了???
然而,攻擊者依然能夠以任意用戶身份進行登錄!

攻擊手法:

在談論這種攻擊手法之前,首先我們需要了解幾個關鍵知識點。

  1. 在SQL中執(zhí)行字符串處理時,字符串末尾的空格符將會被刪除。換句話說“vampire”等同于“vampire ???”,對于絕大多數(shù)情況來說都是成立的(諸如WHERE子句中的字符串或INSERT語句中的字符串)例如以下語句的查詢結(jié)果,與使用用戶名“vampire”進行查詢時的結(jié)果是一樣的。
    SELECT * FROM users WHERE username='vampire     ';
    
    但也存在異常情況,最好的例子就是LIKE子句了。注意,對尾部空白符的這種修剪操作,主要是在“字符串比較”期間進行的。這是因為,SQL會在內(nèi)部使用空格來填充字符串,以便在比較之前使其它們的長度保持一致。
  2. 在所有的INSERT查詢中,SQL都會根據(jù)varchar(n)來限制字符串的最大長度。也就是說,如果字符串的長度大于“n”個字符的話,那么僅使用字符串的前“n”個字符。比如特定列的長度約束為“5”個字符,那么在插入字符串“vampire”時,實際上只能插入字符串的前5個字符,即“vampi”。
    現(xiàn)在,讓我們建立一個測試數(shù)據(jù)庫來演示具體攻擊過程。
    vampire@linux:~$ mysql -u root -p
    mysql> CREATE DATABASE testing;
    Query OK, 1 row affected (0.03 sec)
    mysql> USE testing;
    Database changed
    
    接著創(chuàng)建一個數(shù)據(jù)表users,其包含username和password列,并且字段的最大長度限制為25個字符。然后,我將向username字段插入“vampire”,向password字段插入“my_password”。
    mysql> CREATE TABLE users (
     ->   username varchar(25),
     ->   password varchar(25)
     -> );
    Query OK, 0 rows affected (0.09 sec)
    mysql> INSERT INTO users
     -> VALUES('vampire', 'my_password');
    Query OK, 1 row affected (0.11 sec)
    mysql> SELECT * FROM users;
    +----------+-------------+
    | username | password    |
    +----------+-------------+
    | vampire  | my_password |
    +----------+-------------+
    1 row in set (0.00 sec)
    
    
    為了展示尾部空白字符的修剪情況,我們可以鍵入下列命令:
    mysql> SELECT * FROM users
     -> WHERE username='vampire       ';
    +----------+-------------+
    | username | password    |
    +----------+-------------+
    | vampire  | my_password |
    +----------+-------------+
    1 row in set (0.00 sec)
    
    現(xiàn)在我們假設一個存在漏洞的網(wǎng)站使用了前面提到的PHP代碼來處理用戶的注冊及登錄過程。為了侵入任意用戶的帳戶(在本例中為“vampire”),只需要使用用戶名“vampire[許多空白符]1”和一個隨機密碼進行注冊即可。對于選擇的用戶名,前25個字符應該只包含vampire和空白字符,這樣做將有助于繞過檢查特定用戶名是否已存在的查詢。
    mysql> SELECT * FROM users WHERE username='vampire                   1';
    Empty set (0.00 sec)
    
    需要注意的是,在執(zhí)行SELECT查詢語句時,SQL是不會將字符串縮短為25個字符的。因此,這里將使用完整的字符串進行搜索,所以不會找到匹配的結(jié)果。接下來,當執(zhí)行INSERT查詢語句時,它只會插入前25個字符。
    mysql>   INSERT INTO users(username, password)
     -> VALUES ('vampire                   1', 'random_pass');
    Query OK, 1 row affected, 1 warning (0.05 sec)
    mysql> SELECT * FROM users
     -> WHERE username='vampire';
    +---------------------------+-------------+
    | username                  | password    |
    +---------------------------+-------------+
    | vampire                   | my_password |
    | vampire                   | random_pass |
    +---------------------------+-------------+
    2 rows in set (0.00 sec)
    
    很好,現(xiàn)在我們檢索“vampire”的,將返回兩個獨立用戶。注意,第二個用戶名實際上是“vampire”加上尾部的18個空格?,F(xiàn)在,如果使用用戶名“vampire”和密碼“random_pass”登錄的話,則所有搜索該用戶名的SELECT查詢都將返回第一個數(shù)據(jù)記錄,也就是原始的數(shù)據(jù)記錄。這樣的話,攻擊者就能夠以原始用戶身份登錄。這個攻擊已經(jīng)在MySQL和SQLite上成功通過測試。我相信在其他情況下依舊適用。

防御手段

毫無疑問,在進行軟件開發(fā)時,需要對此類安全漏洞引起注意。我們可采取以下幾項措施進行防御:

  1. 將要求或者預期具有唯一性的那些列加上UNIQUE約束。實際上這是一個涉及軟件開發(fā)的重要規(guī)則,即使你的代碼有維持其完整性的功能,也應該恰當?shù)亩x數(shù)據(jù)。由于’username’列具有UNIQUE約束,所以不能插入另一條記錄。將會檢測到兩個相同的字符串,并且INSERT查詢將失敗。
  2. 最好使用’id’作為數(shù)據(jù)庫表的主鍵。并且數(shù)據(jù)應該通過程序中的id進行跟蹤
  3. 為了更加安全,還可以用手動調(diào)整輸入?yún)?shù)的限制長度(依照數(shù)據(jù)庫設置)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374