虞菊花,喬虹
(常州信息職業(yè)技術(shù)學(xué)院網(wǎng)絡(luò)空間安全學(xué)院,江蘇常州 213164)
在信息化時代,萬物皆可數(shù)據(jù)。互聯(lián)網(wǎng)中的信息可以用指定的數(shù)據(jù)形式表征,該表征數(shù)據(jù)以不同的方式被存儲,待使用者需要時再進(jìn)行獲取和處理。當(dāng)然,最常見的便是將數(shù)據(jù)存儲到數(shù)據(jù)庫中。但是,隨著網(wǎng)絡(luò)安全問題越來越嚴(yán)重,數(shù)據(jù)庫中的數(shù)據(jù)被不法分子通過各種技術(shù)手段非法竊取,成為了經(jīng)常發(fā)生的惡性安全事件。
OWASP(Open Web Application Security Project,開放式Web 應(yīng)用程序安全項目)組織發(fā)布的“十大安全漏洞列表”,具有較高的權(quán)威性。注入型漏洞在歷年發(fā)布的漏洞列表中都是榜上有名的,其中,SQL 注入漏洞是導(dǎo)致數(shù)據(jù)泄露的主要原因之一。為了研究SQL注入漏洞,像OWASP 研制的WebGoat、RandomStorm公司的開源項目DVWA 是漏洞分析和滲透測試實戰(zhàn)的首選[1]。
本文基于SQL 注入的工作原理,在DVWA 開源平臺的漏洞測試環(huán)境中進(jìn)行SQL 注入滲透測試實戰(zhàn),并根據(jù)SQL 注入初級滲透測試的流程,明確SQL 注入攻擊的實現(xiàn)方式,最后探索SQL 注入漏洞的防護(hù)方法。
DVWA(Damn Vulnerable Web App,非常脆弱的Web 應(yīng)用)存在著各種各樣的漏洞。在正式的生產(chǎn)環(huán)境中,安全技術(shù)人員如果對真實的上線網(wǎng)站進(jìn)行各種漏洞的滲透測試,會觸犯現(xiàn)存的網(wǎng)絡(luò)安全法律法規(guī),因此,安全相關(guān)從業(yè)人員需要一個合法的實戰(zhàn)環(huán)境來測試自己的技能和工具。DVWA 的出現(xiàn)就很好地解決了這個問題,為安全人員提供了一個滲透測試環(huán)境,讓其自主練習(xí),助其更好地理解各個漏洞的產(chǎn)生原理,以更好地防范各類攻擊的發(fā)生。
DVWA 的Web 應(yīng)用后端使用PHP 語言開發(fā)的,并且使用MySQL 數(shù)據(jù)庫存儲網(wǎng)站中的數(shù)據(jù)。該平臺主要包括暴力破解、命令注入、跨站請求偽造CSRF、文件包含、文件上傳、不安全的驗證碼、SQL 注入、SQL盲注、反射型跨站腳本XSS、存儲型跨站腳本XSS 共10 個經(jīng)典模塊以供使用者對學(xué)習(xí)的技能進(jìn)行驗證。
SQL 注入指攻擊者通過拼接正常的用戶輸入構(gòu)造特殊的SQL 語句,該語句通過HTTP 請求被傳輸?shù)胶蠖朔?wù)器,服務(wù)器在邏輯處理時沒有對其進(jìn)行嚴(yán)格的檢驗,導(dǎo)致SQL 語句傳輸?shù)綌?shù)據(jù)庫服務(wù)器中被執(zhí)行,攻擊者獲取到了惡意SQL 語句執(zhí)行后的結(jié)果,得到了相應(yīng)的數(shù)據(jù)信息[2]。
攻擊者在正常的Web 應(yīng)用訪問尋找SQL注入的用戶輸入點,如URL 參數(shù)、頁面表單的文本框等。在SQL 注入點的原輸入?yún)?shù)中拼接SQL 語句,從而構(gòu)造惡意的SQL 語句,實現(xiàn)攻擊者的目的;該語句隨著HTTP 請求發(fā)送到Web 服務(wù)器,Web 服務(wù)器處理后直接將其發(fā)給數(shù)據(jù)庫服務(wù)器執(zhí)行;數(shù)據(jù)庫服務(wù)器接收到SQL 語句后執(zhí)行該語句,并向Web 服務(wù)器返回執(zhí)行后的結(jié)果;Web 服務(wù)器將結(jié)果返回給攻擊者,攻擊者就看到了自己構(gòu)造的SQL 語句執(zhí)行后的信息,獲取到了相應(yīng)的數(shù)據(jù),或者根據(jù)執(zhí)行結(jié)果進(jìn)行下一步的攻擊。
SQL 注入主要分為2 種類型,數(shù)字型注入和字符型注入。數(shù)字型類型是指用戶輸入的參數(shù)為數(shù)值型,在類似PHP 的弱類型語言中,數(shù)字型SQL 注入類型較為常見,如常用的查詢指定ⅠD 的SQL 語句“SELECT*FROM TABLE WHERE id=3”;字符型類型是指用戶輸入的參數(shù)為字符串,如常用的查詢指定用戶名的SQL 語句“SELECT * FROM TABLE WHERE user='admin'”。由2 個示例語句可以看到,2 個SQL 注入類型最大區(qū)別在于是否用單引號將參數(shù)閉合。
DVWA平臺的SQL注入不同等級的滲透測試流程都是相同的,本文以SQL 注入初級為例,如圖1 所示。

圖1 SQL 注入滲透測試流程圖
SQL 注入滲透測試需要在Web 頁面中現(xiàn)查找注入點,如搜索框、用戶名和密碼的文本框、URL 等,判斷是否存在SQL 注入漏洞;找到SQL 注入點后,判斷SQL 注入是數(shù)字型還是字符型的注入;根據(jù)SQL 注入類型判斷的結(jié)果,在正常的用戶輸入?yún)?shù)后,使用特定的方式拼接構(gòu)造SQL 語句獲取當(dāng)前數(shù)據(jù)庫的數(shù)據(jù)庫名;獲取數(shù)據(jù)庫名后,構(gòu)造SQL 語句獲取當(dāng)前數(shù)據(jù)庫的所有數(shù)據(jù)表的表名;根據(jù)表名判斷,獲取指定表所有字段的字段名;最后,獲取指定字段對應(yīng)的數(shù)據(jù)[3]。當(dāng)然,部分?jǐn)?shù)據(jù)是加密的,需要解密后才能看到原始數(shù)據(jù)。
初級SQL 注入的頁面是一個查找指定用戶ⅠD 的用戶信息的界面,只需要輸入用戶的ⅠD,則會顯示用戶的“First name”和“Surname”。在頁面的文本框中輸入“2'”,頁面返回報錯提示信息,表明單引號被帶入SQL 語句中被執(zhí)行了,即SQL 注入漏洞可能是存在的。用戶ⅠD 參數(shù)的輸入文本框為SQL 注入點。
SQL 注入可能是數(shù)字型的,也可能是字符型的,不同的類型對應(yīng)的SQL 語句構(gòu)造方式不同,需要通過永真條件“1=1”來判斷SQL 注入的類型。輸入“2'or 1=1#”,頁面返回了所用用戶的信息。這說明原參數(shù)存在閉合的成對單引號,右側(cè)的單引號被“#”注釋了,左側(cè)的單引號被數(shù)字2 后的單引號閉合,輸入?yún)?shù)閉合后正確執(zhí)行了該語句,因此,該SQL 注入為字符型注入。
基于SQL 注入點和注入類型的判斷結(jié)果,就可以開始構(gòu)造獲取數(shù)據(jù)庫相關(guān)信息的SQL 語句。首先獲取的是當(dāng)前數(shù)據(jù)庫的數(shù)據(jù)庫名。
獲取數(shù)據(jù)庫名的路徑為:首先考慮使用MySQL數(shù)據(jù)庫中的database()函數(shù)獲取數(shù)據(jù)庫名,使用該函數(shù)就需要使用union 語句,使用union 語句就需要該語句前后兩個SELECT 子句的字段數(shù)相同。由于頁面顯示了每個用戶的“First name”和“Surname”,可判斷SELECT 語句可能是2 個字段。因此,輸入“2'union select 1,database()#”,頁面在用戶的“Surname”即第2個字段處顯示了“dvwa”,表明union 前的select 子句確實是2 個字段,當(dāng)前數(shù)據(jù)庫名為“dvwa”。
獲取數(shù)據(jù)庫名后就可以構(gòu)造SQL 語句獲取該數(shù)據(jù)庫的所有數(shù)據(jù)表名。
MySQL 數(shù)據(jù)庫中沒有函數(shù)能夠獲取所有數(shù)據(jù)表的名稱,因此,考慮通過MySQL 數(shù)據(jù)庫的默認(rèn)數(shù)據(jù)庫information_schema 的TABLES 表來獲取指定數(shù)據(jù)庫“dvwa”的數(shù)據(jù)表名。TABLES 表存儲了所有數(shù)據(jù)庫對應(yīng)的所有數(shù)據(jù)表名,表中的“TABLE_SCHEMA”字段為數(shù)據(jù)庫名,“TABLE_NAME”字段為數(shù)據(jù)表名。因此,使用MySQL 數(shù)據(jù)庫的group_concat()函數(shù)將所有的數(shù)據(jù)表名連接顯示,結(jié)合union語句,輸入“2'union select 1, group_concat(table_name) from information_schema.tables where table_schema='dvwa'#”,頁面在用戶的“Surname”處顯示了“guestbook,users”,表明“dvwa”數(shù)據(jù)庫中有2 個表,分別為“guestbook”和“users”。
從獲取到的數(shù)據(jù)表名“guestbook”和“users”,可以知道,首先猜解的應(yīng)該是“users”表中的數(shù)據(jù)。因此,接下來,獲取users 表中的所有字段名。
與獲取數(shù)據(jù)表名類似,使用information_schema數(shù)據(jù)庫的COLUMNS 表來獲取指定數(shù)據(jù)表“users”的字段名。COLUMNS 表存儲了所有數(shù)據(jù)表對應(yīng)的所有字段名,表中的“TABLE_NAME”字段為數(shù)據(jù)表名,“COLUMN_NAME”字段為字段名。因此,輸入“2'union select 1,group_concat (column_name) from information_schema.columns where table_name='users'#”,頁面在“Surname”處顯示了所有字段名連接后的字符串,觀察該字符串可以看到,較為關(guān)注的字段是“user”和“password”。
一般情況下,攻擊者只關(guān)注部分字段對應(yīng)的數(shù)據(jù),如用戶名、密碼、身份證號碼等,因此,接下來只獲取“user”和“password”對應(yīng)的數(shù)據(jù),輸入“2'union select user,password from users#”,顯示了數(shù)據(jù)庫中所有用戶名和MD5 加密后的密碼。通過在線網(wǎng)站或者加解密工具來進(jìn)行解密,如admin 的密碼通過CMD5 在線網(wǎng)站解密,可以得到為“password”。攻擊者獲取Web應(yīng)用的管理員賬號密碼后,就可以進(jìn)行后續(xù)的攻擊行為。
SQL 注入漏洞產(chǎn)生需要2 個條件:攻擊者能夠控制輸入?yún)?shù);惡意構(gòu)造的SQL 語句被執(zhí)行。只要阻止這2 個條件中的任意一個發(fā)生,就可以有效防范Web應(yīng)用中的SQL 注入攻擊[4]。
嚴(yán)格過濾輸入的參數(shù)或?qū)斎脒M(jìn)行數(shù)據(jù)驗證,是常用的防護(hù)方法之一。如:在輸入郵箱時,使用正則表達(dá)式進(jìn)行匹配,不滿足郵箱格式的字符串都被過濾;在輸入用戶ⅠD 時,用戶只能在文本框中輸入數(shù)字,不能輸入字符串。
采用SQL語句預(yù)編譯是目前較好的SQL注入防護(hù)方法[5]。預(yù)編譯保證SQL 語句的語法結(jié)構(gòu)不被改變,即使用戶構(gòu)造了拼接后的惡意語句,也只會被當(dāng)作字符串處理,不會被當(dāng)作SQL 命令被執(zhí)行。
不法分子通過SQL 注入攻擊獲取數(shù)據(jù)庫中存儲的數(shù)據(jù),給Web 應(yīng)用的維護(hù)者和使用者都帶來了信息安全的困擾。基于DVWA 平臺的SQL 注入滲透測試,明確了SQL 注入的工作原理,系統(tǒng)地實現(xiàn)了注入流程,并提出了相應(yīng)的防護(hù)方法。但是,在實際的Web 應(yīng)用中,業(yè)務(wù)更復(fù)雜、攻擊方式更多變,需要持續(xù)更新技術(shù)技能,才能更好地應(yīng)對各種網(wǎng)絡(luò)安全事件的發(fā)生。