轉自維基百科: SQL註入是一種代碼註入技術,用於攻擊數據驅動的應用程式,在這種應用程式中,惡意的SQL語句被插入輸入欄位中執行(例如將資料庫內容轉儲給攻擊者)。[1] SQL註入必須利用應用程式軟體中的安全漏洞,例如,當用戶輸入被錯誤地過濾為嵌入在SQL語句中的字元串文字 轉義字元,或者用戶輸入沒 ...
轉自維基百科:
SQL註入是一種代碼註入技術,用於攻擊數據驅動的應用程式,在這種應用程式中,惡意的SQL語句被插入輸入欄位中執行(例如將資料庫內容轉儲給攻擊者)。[1] SQL註入必須利用應用程式軟體中的安全漏洞,例如,當用戶輸入被錯誤地過濾為嵌入在SQL語句中的字元串文字 轉義字元,或者用戶輸入沒有強類型和意外執行時。SQL註入通常被稱為網站的攻擊媒介,但可以用來攻擊任何類型的SQL資料庫。
SQL註入攻擊允許攻擊者欺騙身份,篡改現有數據,導致拒絕問題,如排除交易或更改餘額,允許完整披露系統上的所有數據,破壞數據或使其不可用,併成為資料庫伺服器
在2012年的一項研究中,觀察到平均每個月的網路應用程式收到4次攻擊活動,零售商受到的攻擊是其他行業的兩倍。
SQL註入(SQLI)被Open Web應用程式安全項目認為是2007年和2010年排名前10的Web應用程式漏洞之一。[5] 2013年,SQLI被評為OWASP前十名的頭號攻擊。[6] SQL註入有四個主要的子類:
- 經典的SQLI
- 盲或推理SQL註入
- 資料庫管理系統 - 特定的SQLI
- 複雜的SQLI
這個分類代表了SQLI的狀態,尊重它的發展到2010年 - 進一步的改進正在進行。[12]
技術實現[ 編輯]
錯誤地過濾了轉義字元[ 編輯]
當用戶輸入不是針對轉義字元進行篩選,然後傳遞給SQL語句時,會發生這種SQL註入形式。這導致了應用程式的最終用戶對資料庫執行的語句的潛在操縱。
以下代碼行說明瞭此漏洞:
statement =“ ”+ userName +“ ”SELECT * FROM users WHERE name = '
';
此SQL代碼旨在從其用戶表中提取指定用戶名的記錄。但是,如果“userName”變數是由惡意用戶以特定方式製作的,那麼SQL語句可能比代碼作者所期望的要多。例如,將“userName”變數設置為:
'或'1'='1
或者使用註釋甚至阻塞查詢的其餘部分(有三種類型的SQL註釋[13])。所有三條線在最後都有一個空格:
'OR'1'='1' - '或'1'='1'({ '或'1'='1'/ *
以父語言呈現下列SQL語句之一:
SELECT * FROM users WHERE name = '' OR'1 ' = '1' ;
SELECT * FROM users WHERE name = '' OR'1 ' = '1' - ';
如果在驗證過程中使用此代碼,則可以使用此示例強制從所有用戶中選擇每個數據欄位(*),而不是從編碼人員希望的一個特定用戶名中選擇,因為評估“1” =“1”始終為真(短路評估)。
下麵的語句“username”的下列值將導致“用戶”表中刪除,以及從“用戶信息”表中的所有數據的選擇(本質上揭示了每個用戶的信息),其使用API是允許多個語句:
一個';DROP TABLE users; SELECT * FROM userinfo WHERE 't' = 't
這個輸入呈現如下並指定的最終SQL語句:
SELECT * FROM users WHERE name = 'a' ; DROP TABLE 用戶; SELECT * FROM userinfo的 WHERE 'T' = 'T' ;
儘管大多數SQL伺服器實現允許以這種方式一次調用多個語句,但是由於安全原因,一些SQL API(如PHP的mysql_query()
函數)不允許這樣做。這可以防止攻擊者註入完全獨立的查詢,但不會阻止他們修改查詢。
類型處理不正確[ 編輯]
當用戶提供的欄位沒有強類型或未檢查類型約束時,就會發生這種SQL註入形式。當在SQL語句中使用數字欄位時,可能會發生這種情況,但是程式員不進行檢查來驗證用戶提供的輸入是否為數字。例如:
聲明:=“ ”+ a_variable +“;”
SELECT * FROM userinfo WHERE id =
從這個陳述中可以清楚地看到,作者希望變數是一個與“id”欄位相關的數字。但是,如果它實際上是一個字元串,那麼最終用戶可以按照他們的選擇操作語句,從而繞過了對轉義字元的需要。例如,設置a_variable為
1; DROP TABLE用戶
將從資料庫中刪除(刪除)“users”表,因為SQL變成:
SELECT * FROM userinfo WHERE id = 1 ; DROP TABLE 用戶;
盲目SQL註入[ 編輯]
當Web應用程式容易受到SQL註入的攻擊,但註入的結果對攻擊者不可見時,將使用Blind SQL Injection。帶有此漏洞的頁面可能不是顯示數據的頁面,而是根據註入到為該頁面調用的合法SQL語句中的邏輯語句的結果顯示不同。這種類型的攻擊傳統上被認為是時間密集型的,因為需要為恢復的每一位創建新的語句,並且根據其結構,攻擊可能包含許多不成功的請求。最近的進步已經允許每個請求恢復多個位,沒有不成功的請求,允許更一致和有效的提取。[14]一旦漏洞的位置和目標信息已經建立,有幾種工具可以自動執行這些攻擊。[15]
有條件的回應[ 編輯]
一種類型的盲註入強制資料庫在普通應用程式屏幕上評估邏輯語句。作為示例,書評網站使用查詢字元串來確定要顯示的書評。所以URL http://books.example.com/showReview.php?ID=5
會導致伺服器運行查詢
SELECT * FROM bookreviews WHERE ID = 'Value(ID)' ;
從其中將填充評論頁面,其中來自具有ID 5 的評論的數據存儲在表格書籍視圖中。查詢完全發生在伺服器上; 用戶不知道資料庫,表或欄位的名稱,用戶也不知道查詢字元串。用戶只能看到上面的URL返回書評。甲黑客可以載入的URL 和,這可能導致在查詢http://books.example.com/showReview.php?ID=5 OR 1=1
http://books.example.com/showReview.php?ID=5 AND 1=2
SELECT * FROM bookreviews WHERE ID = '5' 或 '1' = '1' ;
SELECT * FROM bookreviews WHERE ID = '5' 和 '1' = '2' ;
分別。如果使用“1 = 1”URL載入原始評論,並且從“1 = 2”URL返回空白或錯誤頁面,並且尚未創建返回的頁面以提醒用戶輸入無效,或者其他單詞已被輸入測試腳本捕獲,該網站可能容易受到SQL註入攻擊,因為在這兩種情況下,查詢可能已成功通過。黑客可能會繼續使用這個查詢字元串來顯示在伺服器上運行的MySQL的版本號,它將在運行MySQL 4的伺服器上顯示書評,否則將顯示一個空白或錯誤頁面。黑客可以繼續使用查詢字元串中的代碼來從伺服器收集更多信息,直到發現另一個攻擊途徑或達到他或她的目標。
[17]http://books.example.com/showReview.php?ID=5 AND substring(@@version, 1, INSTR(@@version, '.') - 1)=4
二階SQL註入[ 編輯]
當提交的值包含存儲而不是立即執行的惡意命令時,會發生二次SQL註入。在某些情況下,應用程式可能會正確編碼SQL語句並將其存儲為有效的SQL。然後,該應用程式的另一部分沒有控制,以防止SQL註入可能會執行存儲的SQL語句。這種攻擊需要更多的關於如何使用提交的值的知識。自動化Web應用程式安全掃描程式不會輕易檢測到這種類型的SQL註入,並且可能需要手動指示在哪裡檢查它正在嘗試的證據。
緩解[ 編輯]
SQL註入是眾所周知的攻擊,可以通過簡單的措施輕鬆防止。在2015 年Talktalk發生明顯的SQL註入攻擊後,英國廣播公司(BBC)報道說,安全專家驚呆了,這樣一家大公司會受到影響。[18]
參數化語句[ 編輯]
主要文章:編寫聲明對於大多數開發平臺,可以使用參數化的參數化語句(有時稱為占位符或綁定變數),而不是在語句中嵌入用戶輸入。占位符只能存儲給定類型的值,而不是任意的SQL片段。因此,SQL註入將被簡單地視為一個奇怪的(可能是無效的)參數值。
在很多情況下,SQL語句是固定的,每個參數是一個標量,而不是一個表。用戶輸入被分配(綁定)到一個參數。[19]
在編碼層面執行[ 編輯]
使用對象關係映射庫避免了編寫SQL代碼的需要。實際上,ORM庫將從面向對象的代碼生成參數化的SQL語句。
轉義[ 編輯]
一個簡單的,雖然容易出錯的防止註入的方法是轉義SQL中具有特殊含義的字元。SQL DBMS手冊解釋了哪些字元具有特殊含義,可以創建需要翻譯的字元的全面黑名單。例如,參數中每個出現的單引號('
)都必須被兩個單引號(''
)替換,形成一個有效的SQL字元串文字。例如,在PHP中,通常mysqli_real_escape_string();
在發送SQL查詢之前使用函數轉義參數:
$ mysqli = new mysqli ('hostname' , 'db_username' , 'db_password' , 'db_name' );
$ query = sprintf (“SELECT * FROM`Users` WHERE UserName ='%s'AND Password ='%s'” ,
$ mysqli - > real_escape_string ($ username ),
$ mysqli - > real_escape_string ($ password ));
$ mysqli - > query ($ query );
此功能前添加反斜杠以下字元:\x00
,\n
,\r
,\
,'
,"
和\x1a
。這個函數通常用於在向MySQL發送查詢之前使數據安全。[20]
有在PHP許多資料庫類型,如pg_escape_string()用於其它功能的PostgreSQL。該函數addslashes(string $str)
用於轉義字元,特別用於在PHP中查詢沒有逃逸函數的資料庫。它返回一個反斜杠的字元串需要在資料庫查詢被引用,等等。這些字元是單引號('),雙引號(“),反斜線(\)和NUL(空位元組)字元之前。[21]
常規地將轉義字元串傳遞給SQL是很容易出錯的,因為很容易忘記轉義給定的字元串。創建透明圖層來保護輸入可以減少這種容易出錯的情況,如果不能完全消除的話。[22]
模式檢查[ 編輯]
整型,浮點型或布爾型,如果字元串參數的值是給定類型的有效表示形式,則可以檢查它們。如果它們符合這種模式,則必須檢查必須遵循一些嚴格模式(日期,UUID,僅字母數字等)的字元串。
資料庫許可權[ 編輯]
將Web應用程式使用的資料庫登錄許可權限製為僅需要的許可權可能有助於降低任何利用Web應用程式中的任何錯誤的SQL註入攻擊的有效性。
例如,在Microsoft SQL Server上,可能會限制資料庫登錄在某些系統表上進行選擇,這將限制嘗試將JavaScript插入到資料庫的所有文本列中的漏洞利用。
拒絕在sys上選擇。系統對象到webdatabaselogon ; 拒絕在sys上選擇。對象到webdatabaselogon ; 拒絕在sys上選擇。表到webdatabaselogon ; 拒絕在sys上選擇。對webdatabaselogon的看法; 拒絕在sys上選擇。打包到webdatabaselogon ;