張慧琳 丁 羽 張利華 段 鐳 張 超 韋 韜 李冠成 韓心慧
1(北京大學(xué)計算機(jī)科學(xué)技術(shù)研究所 北京 100080)2(加州大學(xué)伯克利分校 加利福尼亞伯克利 94720)3(百度美國有限責(zé)任公司 加利福尼亞森尼韋爾 94089) (zhanghuilin@pku.edu.cn)
?
基于敏感字符的SQL注入攻擊防御方法
張慧琳1丁 羽1張利華1段 鐳1張 超2韋 韜3李冠成1韓心慧1
1(北京大學(xué)計算機(jī)科學(xué)技術(shù)研究所 北京 100080)2(加州大學(xué)伯克利分校 加利福尼亞伯克利 94720)3(百度美國有限責(zé)任公司 加利福尼亞森尼韋爾 94089) (zhanghuilin@pku.edu.cn)
SQL注入攻擊歷史悠久,其檢測機(jī)制也研究甚廣.現(xiàn)有的研究利用污點分析(taint analysis)結(jié)合SQL語句語法分析進(jìn)行SQL注入攻擊檢測,但由于需要修改Web應(yīng)用程序執(zhí)行引擎來標(biāo)記和跟蹤污點信息,難以部署,并且時間和空間性能損失過大.通過分析SQL注入攻擊機(jī)理,提出一種基于敏感字符的SQL注入攻擊防御方法.1)僅對來自常量字符串的可信敏感字符進(jìn)行積極污點標(biāo)記;2)無需修改Web應(yīng)用程序執(zhí)行引擎,利用編碼轉(zhuǎn)換將污點信息直接存儲在可信敏感字符的編碼值中,動態(tài)跟蹤其在程序中的傳播;3)無需SQL語句語法分析,只需利用編碼值判斷SQL語句中敏感字符的來源、轉(zhuǎn)義非可信敏感字符,即可防御SQL注入攻擊.基于PHP的Zend引擎實現(xiàn)了系統(tǒng)原型PHPGate,以插件方式實現(xiàn)、易部署.實驗證明:PHPGate可精確防御SQL注入攻擊,且有效提升污點傳播效率,頁面應(yīng)答的時間開銷不超過1.6%.
SQL 注入攻擊;可信敏感字符;動態(tài)污點分析;積極污點分析;編碼轉(zhuǎn)換
SQL注入(SQL injection)是一種代碼注入(code injection)攻擊[1-2],其根源是Web應(yīng)用程序中的SQL語句通常由程序中可信的常量字符串和用戶輸入等不可信的外來數(shù)據(jù)動態(tài)拼接而成,而Web應(yīng)用程序中存在輸入驗證漏洞,導(dǎo)致用戶輸入等不可信數(shù)據(jù)未經(jīng)充分凈化、過濾就被數(shù)據(jù)庫引擎當(dāng)作SQL代碼片段執(zhí)行.攻擊者可以通過構(gòu)造精巧的畸形輸入,生成惡意SQL語句進(jìn)入數(shù)據(jù)庫執(zhí)行,以此越權(quán)獲取數(shù)據(jù)庫中的數(shù)據(jù),或通過數(shù)據(jù)庫相關(guān)接口直接執(zhí)行系統(tǒng)指令.
開放式Web應(yīng)用程序安全項目組織(open Web application security project, OWASP)發(fā)布的Web安全威脅評估報告[3]顯示,SQL注入攻擊是當(dāng)前最嚴(yán)重的Web安全威脅.SQL注入攻擊泛濫的原因在于:首先,攻擊原理簡單、門檻較低,自動化攻擊工具眾多[4];其次,攻擊后得到的數(shù)據(jù)價值高,例如口令數(shù)據(jù)庫、用戶個人隱私等;最后,避免SQL注入漏洞需要在Web應(yīng)用程序代碼中縝密全面地對用戶輸入等不可信數(shù)據(jù)進(jìn)行驗證,或使用參數(shù)化查詢、存儲過程等來約束SQL語句語法結(jié)構(gòu)[5-6],但這種安全思維并不普遍存在于程序員群體[7-10].
研究人員基于污點分析來標(biāo)識SQL語句各部分的來源,依賴SQL語句語法解析進(jìn)行SQL注入攻擊檢測.主要分為3個步驟:1)污點標(biāo)記,即對用戶輸入等不可信數(shù)據(jù)或可信的常量字符串設(shè)置污點標(biāo)記(前者為消極污點標(biāo)記negative taint,后者為積極污點標(biāo)記positive taint),其中,標(biāo)記粒度通常在字符級別,即每個字符對應(yīng)一個污點狀態(tài);2)污點傳播(taint propagation),即在程序執(zhí)行過程中,對帶有污點的字符串進(jìn)行運算、移動操作時將污點標(biāo)記傳播到結(jié)果字符串的對應(yīng)位置;3)污點檢查,在SQL語句執(zhí)行點(sink點)解析SQL語句語法結(jié)構(gòu),分析各部分(如關(guān)鍵詞和操作符)的污點信息來檢測SQL注入攻擊.
現(xiàn)有的基于污點分析的SQL注入攻擊檢測方法在可部署性、檢測性能、檢測精度上均存在不足,難以實際應(yīng)用:1)現(xiàn)有方案需要修改Web應(yīng)用程序執(zhí)行引擎,通過在String類中增加污點屬性域來記錄其中每個字符的污點狀態(tài),或在內(nèi)存中專門分配一塊空間,以字符地址為索引,以0,1為值來記錄該字符的污點狀態(tài),污點標(biāo)記及污點傳播過程即是對這些屬性域或內(nèi)存空間的賦值與更新,該過程帶來不少的額外空間占用和時間性能損耗,并且修改引擎的實現(xiàn)方式不便于實際部署;2)在Sink點檢查時需對SQL語句語法分析[11-12],檢測的準(zhǔn)確率依賴語法分析的精度[12-13],并且語法分析本身也會帶來一定的性能損耗[12].
本文提出了基于敏感字符的SQL注入攻擊防御方法,無需修改Web應(yīng)用程序執(zhí)行引擎,無需依賴SQL語句語法分析,自動完成SQL注入攻擊防御.主要貢獻(xiàn)包括:
1) 分析SQL注入攻擊機(jī)理,提出了敏感字符和SQL安全條件的概念.無需依賴SQL語句語法解析進(jìn)行SQL注入攻擊檢測,僅對來自常量字符串的可信敏感字符進(jìn)行污點標(biāo)記和跟蹤,在SQL語句中識別并轉(zhuǎn)義來自不可信輸入的非可信敏感字符,從而保證SQL安全條件、防御SQL注入攻擊.
2) 無需修改Web應(yīng)用程序執(zhí)行引擎來標(biāo)記和跟蹤污點信息,提出了一種基于編碼轉(zhuǎn)換的輕量級污點標(biāo)記及傳播方法.利用編碼轉(zhuǎn)換將污點信息直接存儲在可信敏感字符的編碼值中,節(jié)約了污點信息的額外存儲空間;污點信息隨著字符串操作可直接傳播到結(jié)果字符串,節(jié)約了污點傳播的時間開銷.該方法廣泛適用于UTF-8編碼的Web應(yīng)用程序.
3) 整個方法實現(xiàn)為一個PHP插件——PHP-Gate,自動完成SQL注入攻擊防御.無需修改Web應(yīng)用程序執(zhí)行引擎,方便部署.
4) 實驗驗證防御效果和性能損失.證明PHP-Gate可以高效進(jìn)行污點傳播、準(zhǔn)確防御SQL注入攻擊,且頁面應(yīng)答的時間開銷不超過1.6%.
Web應(yīng)用程序?qū)⒖尚诺某A孔址陀脩糨斎氲炔豢尚诺耐鈦頂?shù)據(jù)動態(tài)拼接出SQL語句.SQL注入攻擊成功的本質(zhì)在于控制結(jié)構(gòu)(語法結(jié)構(gòu))和外來數(shù)據(jù)混合在同一傳輸通道中[6],攻擊者精心構(gòu)造的輸入沒有僅作為查詢值,而是破壞了約定的SQL語句的語法結(jié)構(gòu),導(dǎo)致輸入數(shù)據(jù)作為未授權(quán)的SQL代碼片段被執(zhí)行.如圖1中,攻擊者構(gòu)造圖1②所示的參數(shù)值與圖1①中的常量字符串拼接,從而在圖1③中生成的SQL語句中注入了OR ′1′=′1′ 永真式條件.
Fig. 1 An example of SQL injection and detection methods based on taint analysis.圖1 SQL注入攻擊實例與基于污點分析的檢測示例
圖1中④⑤展示了現(xiàn)有的消極或積極污點分析方法的污點檢查流程(圖1④中虛線框中為帶有消極污點標(biāo)記的部分,圖1⑤中實線框為帶有積極污點標(biāo)記的部分):1)解析SQL語句;2)發(fā)現(xiàn)OR ′1′=′1′條件語句含有消極污點標(biāo)記或者不含積極污點標(biāo)記,即檢測出未授權(quán)的SQL代碼片段(圖1④⑤中陰影部分).
進(jìn)一步分析圖1的SQL注入攻擊實例,SQL注入攻擊分為2步:
1) 閉合當(dāng)前語法結(jié)構(gòu),通過注入單引號′來閉合name查詢值;
2) 引入新的語法結(jié)構(gòu),通過OR ′1′=′1與常量字符串中的單引號′拼接來構(gòu)造永真式條件.
在該實例中,攻擊者精心注入引號、空格、等號等分隔符,使生成的SQL語句的語法和語義發(fā)生了變化.
本文的SQL注入攻擊防御方法基于2種現(xiàn)象:
1) SQL文法是上下文無關(guān)文法.其語法被一些語法相關(guān)字符(如空格、分號、引號等)所控制、約束;
2) 數(shù)據(jù)庫引擎最終執(zhí)行安全的SQL語句的語法和語義應(yīng)與Web程序開發(fā)時所約定的語法和語義一致.其充要條件為:最終執(zhí)行的SQL語句中,所有的語法相關(guān)字符一一對應(yīng)于Web程序開發(fā)時內(nèi)置的常量字符串中的語法分隔符.
上述條件保證SQL語句的語法結(jié)構(gòu)未被攻擊者篡改.由于SQL注入攻擊并不改變Web程序自身的執(zhí)行邏輯,且不能更改常量字符串中語法相關(guān)字符及其順序,因此上述條件放寬為:SQL語句中所有的語法相關(guān)字符都來自于常量字符串,也可以保證無SQL注入攻擊發(fā)生.我們稱之為“SQL安全條件”.
為了便于后文描述,首先進(jìn)行下述定義:
定義1. 敏感字符. SQL文法定義中,對SQL語句的語義和語法結(jié)構(gòu)敏感的字符①在SQL語句中,敏感字符既可以作為語法相關(guān)字符(如圖1中攻擊者輸入的空格),也可作為普通字符(如圖1示例中,若用戶輸入“張 三”,其中的空格即為普通字符).
定義2. 可信敏感字符和非可信敏感字符. 按照字符的不同來源,將敏感字符分為可信敏感字符和非可信敏感字符:可信敏感字符為來自Web應(yīng)用程序常量字符串的敏感字符;非可信敏感字符為來自不可信輸入的敏感字符.
基于上述定義,結(jié)合SQL安全條件,分析如下:
1) 如果SQL語句中的敏感字符全部為可信敏感字符,即全部來自可信的常量字符串,則可推出該SQL語句中的語法相關(guān)字符也一定全部來自常量字符串,符合SQL安全條件,不存在SQL注入攻擊.
2) 如果SQL語句含有來自不可信輸入的敏感字符,則這些敏感字符可能被數(shù)據(jù)庫引擎解析為語法相關(guān)字符,破壞SQL語句的語法結(jié)構(gòu),導(dǎo)致SQL注入攻擊.為了保證SQL安全條件,避免非可信敏感字符作為SQL語句的語法相關(guān)字符,可利用數(shù)據(jù)庫引擎特有的轉(zhuǎn)義特性,在這些非可信敏感字符前添加轉(zhuǎn)義符,實現(xiàn)SQL注入攻擊防御.
3) 為了區(qū)分SQL語句中敏感字符的來源,對常量字符串中的敏感字符進(jìn)行積極污點標(biāo)記(見2.1節(jié)、2.2節(jié)),使用編碼轉(zhuǎn)換的方式將污點信息直接存儲在字節(jié)值中(見2.3節(jié)),在程序動態(tài)執(zhí)行過程中進(jìn)行污點傳播,將污點標(biāo)記傳播到生成的SQL語句中.
基于敏感字符的SQL注入攻擊防御方法如圖2所示:在污點標(biāo)記時,將標(biāo)記對象(taint source)限定為常量字符串中的敏感字符(示例中的實線框部分),對其進(jìn)行編碼轉(zhuǎn)換;污點傳播過程與程序?qū)尚琶舾凶址牟僮飨喟?;污點檢查過程則在SQL語句被送往數(shù)據(jù)庫引擎執(zhí)行前,將可信敏感字符恢復(fù)為標(biāo)準(zhǔn)編碼,在非可信敏感字符前添加轉(zhuǎn)義符(本文以反斜線為例).
Fig. 2 SQL injection prevention based on sensitive characters.圖2 基于敏感字符的SQL注入攻擊防御方法設(shè)計
該方法可成功防御SQL注入攻擊.圖2的示例中,數(shù)據(jù)庫引擎將字符串中的和隨后字符當(dāng)作一個轉(zhuǎn)義序列,和單引號、空格、等號的組合被認(rèn)作轉(zhuǎn)義序列,數(shù)據(jù)庫引擎將在test表中查找name為1′ OR ′1′=′1的記錄,成功防御SQL注入攻擊.
該方法不會影響用戶與Web應(yīng)用程序、數(shù)據(jù)庫引擎的正常交互.圖2的示例中,若用戶輸入“張 三”(中間含有非可信敏感字符——空格),經(jīng)過處理后的查詢條件變?yōu)閃HEREname=′張 三′,數(shù)據(jù)庫引擎將字符串中的和隨后空格當(dāng)作一個轉(zhuǎn)義序列,仍將在test表中查找name為“張 三”(中間含有空格)的記錄.
2.1 敏感字符集
常見的SQL敏感字符有單引號、分號、破折號、反斜杠、@、星號等.若要達(dá)到完備的SQL注入攻擊防御效果,敏感字符集應(yīng)該包括所有能夠改變SQL語句的語法和語義的字符.通過對大量SQL注入攻擊的實例分析,逐一排查ASCII字符,可以得到33個字符,再另外加上SQL語句接受的換行符、回車符、制表符3個空白符,構(gòu)成容量為36的敏感字符集合,如表1所示.
表1的敏感字符是完備的:不包含SQL不接受的空白字符、非可見字符以及表1中敏感字符的字符串,只能由大小寫字母、數(shù)字以及中文、韓文等組成,這樣的字符串并不能引起SQL語句在語法和語義上的變化,攻擊者無法通過注入這樣的字符串來實現(xiàn)SQL注入攻擊,進(jìn)而越權(quán)讀取數(shù)據(jù)、越權(quán)執(zhí)行命令.
Table 1 Sensitive Characters and Their Encodings
2.2 積極污點標(biāo)記可信敏感字符
對敏感字符的污點標(biāo)記分為2種方式:對常量字符串中的可信敏感字符設(shè)置積極污點標(biāo)記和對不可信輸入中的非可信敏感字符設(shè)置消極污點標(biāo)記.本文采用積極污點標(biāo)記方式,其優(yōu)點在于:實際系統(tǒng)中,不可信輸入來自于諸多渠道參數(shù),并沒有一個簡單、可用的接口來對所有不可信輸入進(jìn)行標(biāo)記,消極污點標(biāo)記難以將所有的非可信敏感字符都標(biāo)記為污點數(shù)據(jù);而可信數(shù)據(jù)以常量字符串形式存在,對Web程序常量字符串中的可信敏感字符進(jìn)行積極污點標(biāo)記后,所有非可信敏感字符則會以未標(biāo)記的形式存在,標(biāo)記結(jié)果更加準(zhǔn)確.
2.3 編碼轉(zhuǎn)換方式記錄污點狀態(tài)
現(xiàn)有的污點標(biāo)記及傳播模型需要Web應(yīng)用程序執(zhí)行引擎修改String類數(shù)據(jù)結(jié)構(gòu)或者額外分配內(nèi)存空間來記錄污點信息,由于性能損耗較大而難以得到實用.
本文利用UTF-8編碼特性,通過編碼轉(zhuǎn)換來記錄污點狀態(tài),通過編碼值來區(qū)分可信敏感字符和非可信敏感字符.該方案減少了污點標(biāo)記和傳播的空間和時間開銷:把需要標(biāo)記的字符的字節(jié)值轉(zhuǎn)換為不符合UTF-8 編碼規(guī)則的字節(jié)值,編碼轉(zhuǎn)換之后的字節(jié)值自帶污點信息,無需額外分配空間記錄污點信息;污點傳播時,污點信息可被字符串操作自動傳播到結(jié)果字符串的相應(yīng)位置;污點檢查時,只需掃描字符串,找到非標(biāo)準(zhǔn)的UTF-8 編碼字節(jié)即為污點字符.方法屬于一種輕量級的污點標(biāo)記及分析方法,并且適用于所有UTF-8編碼的Web程序.
UTF-8編碼是Unicode字符集(U+0000~U+FFFF)的一種編碼方式.對于字符U+0000~U+007F,UTF-8與基本ASCII編碼方案一致,采用一個字節(jié)表示(二進(jìn)制表示為0xxxxxxx);對于之后的Unicode字符,UTF-8采用2~4個字節(jié)表示,其中首字節(jié)由n位連續(xù)的1加1位0開始(n為字符編碼所需的字節(jié)數(shù)),其后的每個字節(jié)的最高2 b固定位為“10”.例如3 B字符的UTF-8編碼結(jié)構(gòu)為“1110xxxx 10xxxxxx 10xxxxxx”,其中掩碼部分即Unicode字符的序號.
由于表1中的敏感字符在UTF-8編碼中均是單字節(jié)字符,而UTF-8單字節(jié)字符編碼規(guī)則中存在形如1xxxxxxx(0x80-0xFF)的“編碼空洞”.在標(biāo)準(zhǔn)的UTF-8編碼字節(jié)流中,形如10xxxxxx的字節(jié)一定是多字節(jié)字符的后續(xù)字節(jié),而不會是單字節(jié)或多字節(jié)字符的首字節(jié).根據(jù)UTF-8編碼的上述特性,在單字節(jié)字符編碼空洞10xxxxxx中為可信敏感字符劃分出編碼空間,使用編碼轉(zhuǎn)換的方式進(jìn)行污點狀態(tài)記錄:即在污點標(biāo)記階段,將常量字符串中的可信敏感字符的UTF-8編碼字節(jié)值一一轉(zhuǎn)換為0x80-0xA3這些特殊的“非法”編碼字節(jié)值,具體的編碼轉(zhuǎn)換映射關(guān)系如表1所示.這些非標(biāo)準(zhǔn)UTF-8編碼的單字節(jié)自帶污點信息,且可以在程序執(zhí)行中自動傳播到結(jié)果字符串中,并能與以0xxxxxxx原編碼形式存在的、未被污點標(biāo)記的非可信敏感字符進(jìn)行區(qū)分.
對可信敏感字符的編碼轉(zhuǎn)換并沒有為UTF-8解碼帶來二義性:本文只用了部分UTF-8單字節(jié)字符編碼“空洞”(0x80-0xBF),即被標(biāo)記的可信敏感字符具有形式“10xx xxxx”.在標(biāo)準(zhǔn)的UTF-8 編碼中,“10”開頭的字節(jié)不會存在于字符的首字節(jié),而在解碼帶有污點信息的UTF-8字節(jié)流時,若一旦遇到首字節(jié)就為“10xxxxxx”形式,則該字符一定是經(jīng)過編碼轉(zhuǎn)換后的可信敏感字符.對可信敏感字符的編碼轉(zhuǎn)換沒有使用編碼空洞的另一部分(0xC0-0xFF,具有形式“11xxxxxx”,其可能會是多字節(jié)字符的首字節(jié)),不會引起UTF-8解碼的二義性.
第2節(jié)提出將可信敏感字符的字節(jié)值轉(zhuǎn)換為非標(biāo)準(zhǔn)UTF-8編碼值,這種基于編碼轉(zhuǎn)換的污點狀態(tài)記錄方式,廣泛適用于采用UTF-8編碼的Web應(yīng)用程序.
本文的污點標(biāo)記、污點傳播、污點檢查過程分別對應(yīng)著UTF-8字節(jié)流的編碼轉(zhuǎn)換、字節(jié)值操作以及編碼檢查過程.本節(jié)詳細(xì)描述各個過程,為了便于后文描述,首先闡述下述定義.
定義3.C為UTF-8標(biāo)準(zhǔn)編碼的全集,具體分為4類:
1) 單字節(jié)字符,編碼字節(jié)為
0xxxxxxx;
2) 2個字節(jié)字符,編碼字節(jié)為
110xxxxx 10xxxxxx;
3) 3個字節(jié)字符,編碼字節(jié)為
1110xxxx 10xxxxxx 10xxxxxx;
4) 4個字節(jié)字符,編碼字節(jié)為
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx.
定義4.SC為所有敏感字符的UTF-8編碼集合.SC中共36個元素,均為單字節(jié)編碼,具體如表1所示(形如0xxxxxxx).
定義5.SSC為非標(biāo)準(zhǔn)的單字節(jié)字符編碼,共36個元素,值為10000000~10100011 (均具有形式10xxxxxx)
定義6. 編碼轉(zhuǎn)換map將SC中的標(biāo)準(zhǔn)編碼一一映射到SSC中的非標(biāo)準(zhǔn)編碼,具體的映射關(guān)系如表1所示,定義如下:
map:SC→SSC,
ε∈SC?map(ε)∈SSC,
ε∈SC∧γ∈SC∧γ≠ε?map(γ)≠map(ε).
定義7. 編碼恢復(fù)remap將SSC中的非標(biāo)準(zhǔn)編碼還原為SC中的標(biāo)準(zhǔn)編碼,具體的映射關(guān)系如表1所示,定義如下:
remap:SSC→SC,
ε∈SSC?remap(ε)∈SC,
ε∈SSC∧γ∈SSC∧γ≠ε?remap(γ)≠remap(ε).
上述定義具有4個性質(zhì):
性質(zhì)1.SC?C.
性質(zhì)2. 不可偽造性.SSC∩C=?使非標(biāo)準(zhǔn)編碼與標(biāo)準(zhǔn)UTF-8編碼完全區(qū)分,即非標(biāo)準(zhǔn)編碼不能被UTF-8標(biāo)準(zhǔn)編碼偽造.
性質(zhì)3. 編碼轉(zhuǎn)換map具有編碼唯一性,即:
?ε∈SC∧?γ∈SC∧γ≠ε?map(γ)≠map(ε).
性質(zhì)4. 編碼恢復(fù)remap具有解碼唯一性,即:
?ε∈SSC∧?γ∈SSC∧γ≠ε?
remap(γ)≠remap(ε).
3.1 基于編碼轉(zhuǎn)換的污點標(biāo)記
算法1完成對可信敏感字符的積極污點標(biāo)記.
算法1. 污點標(biāo)記算法TaintSC.
輸入:UTF-8常量字符串的集合ConststringSet;
輸出:編碼轉(zhuǎn)換后的常量字符串集合.
① for eachQinConststringSet:
② character_listcl=utf8_standard_decode(Q);
③ for eachμincl:
④Mark(μ);
⑤ end for
⑥ end for
步驟①遍歷Web應(yīng)用程序中常量字符串的集合ConststringSet,選定一個UTF-8常量字符串,其字節(jié)流為Q.
步驟②對Q進(jìn)行UTF-8標(biāo)準(zhǔn)解碼.即按照C的編碼集合,對Q進(jìn)行劃分,劃分出1個字節(jié)組序列cl,其中每個字節(jié)組含有1~4個字節(jié),對應(yīng)著1個UTF-8字符.
步驟③遍歷步驟②中字節(jié)組序列中的每個UTF-8字符.
步驟④對每個UTF-8字符,用定義8中的函數(shù)Mark將敏感字符的標(biāo)準(zhǔn)編碼字節(jié)值轉(zhuǎn)換為非標(biāo)準(zhǔn)編碼字節(jié)值,其他字符的編碼字節(jié)值則保持原樣.
定義8. 函數(shù)Mark:
Mark:C→SSC∪{C-SC},
(1)
污點標(biāo)記算法TaintSC完成了對常量字符串中可信敏感字符的標(biāo)記,可信敏感字符的編碼字節(jié)值均被SSC中的非標(biāo)準(zhǔn)編碼字節(jié)值替換,常量字符串中其余字符則保留原編碼字節(jié)值,被標(biāo)記后的常量字符串的編碼空間為SSC∪{C-SC}.
3.2 基于編碼轉(zhuǎn)換的污點傳播
Web應(yīng)用程序常量字符串中的可信敏感字符經(jīng)過TaintSC算法被轉(zhuǎn)換為SSC中的非標(biāo)準(zhǔn)編碼字節(jié)值,而用戶輸入等不可信數(shù)據(jù)中的非可信敏感字符則以SC中的標(biāo)準(zhǔn)編碼形式存在.程序執(zhí)行時,將二者混合在一起操作,字符串的編碼空間為SSC∪C.
污點傳播要求在字符串操作中跟蹤、存儲和更新結(jié)果字符串中相應(yīng)的污點信息.可信敏感字符以編碼轉(zhuǎn)換的方式在字節(jié)值中自動攜帶污點信息,污點傳播過程與程序?qū)尚琶舾凶址牟僮飨喟?字符字節(jié)值中自動攜帶的污點信息會隨著程序執(zhí)行自動傳播,不需要額外的跟蹤算法.但是,由于污點標(biāo)記后的字節(jié)流不符合標(biāo)準(zhǔn)UTF-8編碼規(guī)則,程序中的字符串函數(shù)需分為3種情況進(jìn)行處理:
1) 拼接、分割類函數(shù)
該類函數(shù)(如join,substr等)對字符串參數(shù)做拼接、分割處理.編碼轉(zhuǎn)換的污點標(biāo)記方式并不改變字符串長度和字符位置,因此無需對這些函數(shù)進(jìn)行額外處理,參數(shù)中可信敏感字符的非標(biāo)準(zhǔn)編碼字節(jié)可隨著函數(shù)執(zhí)行自動賦值到結(jié)果字節(jié)流中相應(yīng)位置.
2) 數(shù)值操作類函數(shù)
該類函數(shù)如md5等,直接對整個字符串取值后進(jìn)行字面值操作.對于這類函數(shù),在函數(shù)執(zhí)行前需對參數(shù)中的可信敏感字符進(jìn)行編碼恢復(fù)(即污點凈化),從而保證得到正確的函數(shù)執(zhí)行效果.
3) 含有字符匹配邏輯的函數(shù)
該類函數(shù)分為2個步驟:首先通過字符(串)匹配邏輯確定操作位置;然后在此位置上對字節(jié)流進(jìn)行增(如addcslashes函數(shù)增加反斜線)、刪(如trim函數(shù)刪除指定字符)、改(如replace函數(shù)用指定字符串替換)等操作.
字符匹配過程中,由于編碼轉(zhuǎn)換的污點標(biāo)記方式使每個敏感字符根據(jù)是否來自常量字符串存在2種字節(jié)值,所以需對該邏輯進(jìn)行修改:若2個字符α,β(無先后順序)滿足式(2)所述條件,則認(rèn)為二者匹配:
(α,β∈C∧α=β)∨(α,β∈SSC∧α=β)∨
(α∈SC∧β∈SSC∧α=remap(β)).
(2)
而增、刪、改操作會自動將參數(shù)中的污點標(biāo)記賦值到結(jié)果字節(jié)流中相應(yīng)位置,實現(xiàn)污點的自動傳播,所以無需做額外處理.
3.3 基于編碼轉(zhuǎn)換的污點檢查
在SQL語句傳入數(shù)據(jù)庫引擎執(zhí)行前,分析SQL語句的UTF-8字節(jié)流,進(jìn)行污點檢查,檢查SQL語句中所有的敏感字符是否都帶有污點標(biāo)記(SSC中的編碼形式,即可信敏感字符)以及是否存在未帶有污點標(biāo)記的敏感字符(SC中的原編碼形式,即非可信敏感字符),算法如下:
算法2. 污點檢查算法SQLCheck.
輸入:動態(tài)拼接出的SQL語句,其字節(jié)流為Q;
輸出:編碼恢復(fù)后的SQL語句字節(jié)流,非可信敏感字符的下標(biāo)集合UntrustIndex.
①UntrustIndex?;
② character_listcl=utf8_extended_decode(Q);
③ for eachμincl*μ∈{SSC∪C}*
④ ifμ∈SSC
⑤remap(μ);
⑥ end if
⑦ ifμ∈SC
⑧UntrustIndex.add(μ.index);
⑨ end if
⑩ end for
步驟②對Q進(jìn)行UTF-8擴(kuò)展解碼.即按照SSC∪C中的編碼集合對Q進(jìn)行劃分,劃分出1個字節(jié)組序列cl.其中每個字節(jié)組含有1~4個字節(jié),對應(yīng)著一個UTF-8字符或帶污點標(biāo)記的可信敏感字符.
步驟③遍歷步驟②中字節(jié)組序列中的每個字符μ.
步驟④~⑨對步驟③的每個μ,將可信敏感字符(μ∈SSC)的非標(biāo)準(zhǔn)編碼字節(jié)值恢復(fù)為標(biāo)準(zhǔn)編碼字節(jié)值,非可信敏感字符的編碼字節(jié)值(μ∈SC)則保持原樣,將其下標(biāo)加入UntrustIndex中,對于μ∈{C-SC}的字符,字節(jié)值保持原樣.
3.4 SQL注入攻擊自動防御
經(jīng)過SQLCheck算法的處理,SQL語句中的可信敏感字符已經(jīng)恢復(fù)為標(biāo)準(zhǔn)的UTF-8編碼字節(jié)值,整個SQL語句為標(biāo)準(zhǔn)的UTF-8編碼.通過算法3完成SQL注入攻擊的自動防御.
算法3. SQL注入攻擊自動防御算法SQLIn-jectionPrevention.
輸入:SQLCheck處理后的SQL語句字節(jié)流Q以及非可信敏感字符的下標(biāo)集合UntrustIndex;
輸出:在非可信敏感字符前添加轉(zhuǎn)義符,執(zhí)行SQL語句.
① ifUntrustIndex=?;
② SQL_exec(Q);
③ else
④ for eachiinUntrustIndex
⑤ prepend ‘’ beforeQ[i];
⑥ end for
⑦ SQL_exec(Q);
⑧ end if
步驟①~②若發(fā)現(xiàn)UntrustIndex=?,則說明SQL語句中不含有非可信敏感字符,SQL語句中的敏感字符全部來自可信的字符串常量,該SQL語句符合SQL安全條件,不存在SQL注入攻擊,被直接送往數(shù)據(jù)庫執(zhí)行.
步驟③~⑦若UntrustIndex≠?,則SQL語句含有來自不可信輸入的敏感字符,這些非可信敏感字符可能破壞SQL語句語法結(jié)構(gòu),造成SQL注入攻擊.在這些非可信敏感字符前添加轉(zhuǎn)義符來自動防御SQL注入攻擊(由于添加轉(zhuǎn)義符會使SQL語句長度發(fā)生變化,步驟④~⑥僅表示抽象邏輯).
針對PHP語言進(jìn)行原型系統(tǒng)實現(xiàn).本文的方法無需修改PHP執(zhí)行引擎源碼,而是將上節(jié)所述方法實現(xiàn)為PHP執(zhí)行引擎的一個插件——PHP-Gate.插件的實現(xiàn)方式較易部署,同時PHP執(zhí)行引擎是C語言編寫,插件也是C語言編寫,執(zhí)行效率高.
在一個典型的Web服務(wù)器中,PHP程序被執(zhí)行引擎——Zend解釋執(zhí)行.如圖3實線方框所示,過程分為2步:首先,生成中間碼(byte codes),其中,PHP程序中的常量字符串被解釋為中間碼的參數(shù);然后,執(zhí)行中間碼,執(zhí)行時調(diào)用相應(yīng)的處理函數(shù)(handler)完成功能.
Zend引擎提供了完整的插件開發(fā)API,使開發(fā)者可以在PHP解釋、執(zhí)行過程中插裝代碼,監(jiān)控并操作應(yīng)用層代碼的執(zhí)行細(xì)節(jié).如圖3虛線方框所示,PHPGate通過遍歷中間碼及其參數(shù)實現(xiàn)污點標(biāo)記,通過對Zend引擎中一系列函數(shù)的hook實現(xiàn)污點傳播、污點檢查.
Fig. 3 PHPGate implementation and working process.圖3 PHPGate系統(tǒng)工作流程
4.1 可信敏感字符標(biāo)記
可信敏感字符的污點標(biāo)記包括2個步驟:常量字符串提取和可信敏感字符編碼轉(zhuǎn)換.常量字符串提取負(fù)責(zé)從中間碼的參數(shù)中找到常量字符串.可信敏感字符編碼轉(zhuǎn)化則將常量字符串中敏感字符的標(biāo)準(zhǔn)編碼字節(jié)值轉(zhuǎn)變?yōu)楸?中的非標(biāo)準(zhǔn)編碼字節(jié)值.
PHPGate通過Zend引擎中zend_compile_file函數(shù)實現(xiàn)常量字符串提取和可信敏感字符編碼轉(zhuǎn)換.Zend引擎通過zend_compile_file函數(shù)把PHP程序解釋成一系列中間碼,PHPGate通過插件的相應(yīng)接口hook該函數(shù),在中間碼生成后遍歷所有的中間碼,檢查每一條中間碼的參數(shù):如果參數(shù)類型為字符串且具有屬性IS_CONST,則該參數(shù)為PHP程序中的常量字符串,按照3.1節(jié)所述的TaintSC算法完成可信敏感字符編碼轉(zhuǎn)換.
4.2 污點傳播及凈化的實現(xiàn)
1) 內(nèi)置字符串函數(shù)
PHPGate對PHP內(nèi)置字符串函數(shù)的handler進(jìn)行hook,按照3.2節(jié)所述的3種不同分類分別實現(xiàn)無操作、參數(shù)污點凈化(即編碼恢復(fù))以及重定義字符匹配邏輯.
2) 特殊的中間碼
可信敏感字符的編碼轉(zhuǎn)換改變了一些中間碼參數(shù)的字節(jié)值,為了保證程序正常邏輯不被破壞,還需要對下述5個中間碼進(jìn)行參數(shù)凈化處理:
ZEND_INCLUDE_OR_EVAL, ZEND_ECHO,
ZEND_PRINT, ZEND_DO_FCALL_BY_NAME, ZEND_DO_FCALL.
前3條中間碼在執(zhí)行時無法處理可信敏感字符的非標(biāo)準(zhǔn)編碼形態(tài),PHPGate修改它們的handler,使之指向一個wrap函數(shù).wrap函數(shù)首先對中間碼的字符串參數(shù)進(jìn)行污點凈化,將可信敏感字符編碼恢復(fù);接著調(diào)用原來的handler完成操作;最后在handler執(zhí)行完后將參數(shù)中的可信敏感字符重新編碼轉(zhuǎn)換為污點形態(tài)(污點重標(biāo)記),保證污點的正確傳播.
后2個中間碼的語義為根據(jù)參數(shù)指明的函數(shù)名查找對應(yīng)的內(nèi)置函數(shù).如果這2個中間碼的字符串參數(shù)(即函數(shù)名)中包含非標(biāo)準(zhǔn)編碼,也會引起邏輯錯誤,導(dǎo)致找不到所調(diào)用的函數(shù),所以也需對參數(shù)進(jìn)行污點凈化及污點重標(biāo)記.
4.3 污點檢查及SQL注入攻擊防御的實現(xiàn)
在SQL語句送入數(shù)據(jù)庫引擎前,需要對所有的敏感字符進(jìn)行檢查:對于污點形態(tài)的敏感字符,需要編碼恢復(fù);對于正常形態(tài)的敏感字符,需要進(jìn)行相應(yīng)處理,如在其之前加入‘’字符使其失去改變SQL語義的功能.
與hook內(nèi)置字符串函數(shù)的方式類似,PHP-Gate對數(shù)據(jù)庫操作函數(shù)指定了一個新的handler,實現(xiàn) SQLCheck算法和SQLInjectionPrevention算法.最后將處理過的SQL語句傳給數(shù)據(jù)庫引擎執(zhí)行.
4.4 偽標(biāo)記問題的處理
4.1節(jié)至4.3節(jié)實現(xiàn)的SQL注入攻擊防御方案基于一個前提:程序接受的用戶輸入都是UTF-8標(biāo)準(zhǔn)編碼的字符串,即用戶無法輸入非標(biāo)準(zhǔn)UTF-8單字節(jié).在PHP運行過程中會遇到類似md5等的Hash函數(shù),這些Hash函數(shù)會產(chǎn)生任意字節(jié)值.這些字節(jié)可能會被解釋為可信敏感字符,為了避免對這樣的字節(jié)進(jìn)行污點凈化,PHPGate在所有的凈化過程中對字符串加入UTF-8擴(kuò)展解碼合法性檢查.如果字符串不是一個合法的擴(kuò)展UTF-8編碼字符串,則不對這個字符串進(jìn)行污點凈化操作.
4.5 性能優(yōu)化
4.1節(jié)至4.4節(jié)實現(xiàn)的PHPGate可以保證邏輯正確運行,但是性能有待優(yōu)化.
在類似ZEND_ECHO的參數(shù)污點凈化和污點重標(biāo)記處理中,如果反復(fù)申請內(nèi)存以保存字符串的污點標(biāo)記形式又在之后釋放,將引起很大的性能開銷.
PHPGate使用一種基于棧的方法來優(yōu)化.PHPGate維護(hù)一個額外的“標(biāo)記棧”來輔助污點凈化、污點重標(biāo)記.標(biāo)記棧的運行和參數(shù)污點凈化、污點重標(biāo)記過程同步.每當(dāng)PHPGate進(jìn)行污點凈化操作時,PHPGate向標(biāo)記棧壓入額外信息,額外信息包括每個參數(shù)的:
1) 各個污點字符下標(biāo);
2) 字符串指針;
3) 污點字符數(shù).
最后,將參數(shù)數(shù)目壓棧.
如“”,2個單引號在污點標(biāo)記過程中被編碼轉(zhuǎn)換為0x8A;在執(zhí)行ECHO時,PHPGate會先對參數(shù)進(jìn)行污點凈化,同時在標(biāo)記棧依次壓入5和7(參數(shù)字符串中污點字符下標(biāo))、字符串參數(shù)指針、2(污點字符數(shù)為2)、1(參數(shù)數(shù)目為1).在ECHO操作執(zhí)行后,PHPGate依據(jù)標(biāo)記棧上彈出的信息直接對參數(shù)字符串中的可信敏感字符進(jìn)行污點重標(biāo)記,避免了多次申請內(nèi)存來分別保存污點凈化和污點重標(biāo)記前后的字符串參數(shù).
為了測試PHPGate對SQL注入攻擊的實際防御效果以及帶來的性能損失,搭建了LAMP(Linux,Apache,MySQL,PHP)框架,其中:操作系統(tǒng)版本為Debian Linux 7,Linux內(nèi)核為3.2.0-4-amd64,Apache版本為Apache 2.2.24,MySQL版本為5.5.35,PHP版本為 5.4.21.
防御效果測試中,一方面使用一個已有的SQL注入攻擊測試集T;另一方面重現(xiàn)了針對知名PHP應(yīng)用程序的SQL注入攻擊,觀察開啟PHPGate之后攻擊是否成功.
性能測試中,首先采用Zend自帶的2個測試集:ZendBenchmark(bench.php)和PHP Benchmark Script測試PHPGate在不同類型操作中的性能損失;其次,測試SQL注入攻擊測試集T的頁面應(yīng)答時間開銷;最后,針對真實頁面測試PHPGate的頁面應(yīng)答時間開銷.
5.1 防御效果實驗及討論
1) 防御測試集T中的SQL注入攻擊
選取了文獻(xiàn)[8]和文獻(xiàn)[12]的SQL注入攻擊測試集T,如表2所示,包含3個PHP應(yīng)用、19個SQL注入漏洞及攻擊.實驗表明,PHPGate能有效防御這19個SQL注入攻擊.
Table 2 Effectiveness of SQL Injection Prevention on
表3選取了其中的2個SQL注入攻擊實例,描述PHPGate對SQL注入攻擊的防御效果(下劃線為用戶輸入).示例1中,MySQL數(shù)據(jù)庫引擎將反斜線和其后字符當(dāng)作轉(zhuǎn)義序列,查找值為junk″ or 1=1--的記錄,從而成功防御了SQL注入攻擊.示例2中,反斜線未在字符串中,MySQL數(shù)據(jù)庫引擎將反斜線和其后字符當(dāng)作2個獨立字符,SQL語句語法解析失敗后無法執(zhí)行,從而阻止惡意SQL語句的執(zhí)行,防御SQL注入攻擊.
Table 3 Demonstration of SQL Injection Prevention
2) 防御真實SQL注入攻擊案例
從ExploitDB[14]選擇了5個公開的針對PHP應(yīng)用的SQL注入攻擊樣本,安裝相應(yīng)版本的PHP應(yīng)用,搭建實驗環(huán)境并且模擬攻擊.
表4列舉了這5個攻擊樣本所針對的漏洞編號和應(yīng)用名稱.實驗表明:PHPGate能有效防御這5個SQL注入攻擊.
3) 防御能力對比
PHPGate不依賴SQL語句的語法分析進(jìn)行攻擊檢測,避免了由于語法分析策略精度不夠造成的漏報.對于圖4中的SQL注入攻擊樣例(下劃線為用戶輸入),文獻(xiàn)[13]中的語法分析策略不能準(zhǔn)確檢測出SQL注入攻擊,而PHPGate通過轉(zhuǎn)義SQL語句的非可信敏感字符,成功防御SQL注入攻擊.
Table 4 PHPGate Prevent SQL Injection Attacks in the Wild
SELECTnameFROMaccountWHEREid=exit()
Fig. 4 A case of SQL injection.
圖4 一個SQL注入攻擊樣例
4) PHPGate局限性
下劃線_和百分號%是SQL語句的通配符,MySQL數(shù)據(jù)庫引擎僅在Like匹配語句中才將字符串中的\_和\%當(dāng)作轉(zhuǎn)義序列.因此,PHPGate在處理非可信的_和%時,需要使用輔助手段(如SQL語句語法分析)來判斷它們所在的語法結(jié)構(gòu)并予以相應(yīng)處理.
5.2 PHPGate性能測試
1) Zend測試集的性能測試
圖5展示了針對ZendBenchmark的性能測試結(jié)果.橫坐標(biāo)為18個測試?yán)?,柱狀圖(左坐標(biāo)軸,單位為秒)顯示了在關(guān)閉和開啟PHPGate的2種情況下運行時間的差別,深色柱為不加載PHPGate時的運行時間,淺色柱為開啟PHPGate的運行時間,折線圖顯示了開啟PHPGate后性能損失隨不同測試?yán)淖兓€(右坐標(biāo)軸).可以看出,在simplecall,strcat(200000)和simpleucall這3個測試?yán)螾HP-Gate的損失較大,分別為5.84%,10.91%和11.21%,而在其他測試?yán)系男阅軗p失均小于2%.此外,有些結(jié)果的性能損失為負(fù)數(shù)并不能說明開啟PHPGate后運行速度比關(guān)閉時更快,而是說明PHPGate在這些操作上的性能影響小于系統(tǒng)影響、外界環(huán)境影響.
Fig. 5 Overhead on ZendBenchmark.圖5 ZendBenchmark性能損失
Fig. 6 Overhead on PHP Benchmark Script.圖6 PHP Benchmark Script性能損失
圖6的PHP Benchmark Script從數(shù)學(xué)運算、字符串操作、循環(huán)和分支4個方面對PHPGate的性能進(jìn)行測試.圖6展示了針對PHP Benchmark Script的測試結(jié)果.可以看出,字符串操作測試?yán)螾HPGate的損失較大,但仍在可接受的范圍內(nèi)(12.76%),在其他測試?yán)系男阅軗p失均很小.
表5對比了PHPGate與WASP[11,15]在同類型字符串操作函數(shù)的性能損失.WASP對Java中String類重新進(jìn)行封裝,在新增的屬性域中存儲每個字符的污點信息,污點傳播需要對參數(shù)污點屬性域逐一遍歷,并按照污點傳播策略對結(jié)果字符串的污點屬性域逐一賦值.該過程對性能損失影響較大,實驗數(shù)據(jù)表明,WASP在字符串相關(guān)操作上的性能損失從125%~7100%不等.而本文的基于編碼轉(zhuǎn)換的污點狀態(tài)記錄方式,污點信息直接存儲在字節(jié)值中,隨著字符串操作直接賦值到結(jié)果字符串中.對比看出,本文的污點標(biāo)記及傳播方法有效降低了字符串操作函數(shù)上的性能損失.
Table 5 Overhead Comparison of Two Methods on String
Manipulation
表5 字符串操作性能比較
2) 測試集T上的性能損失及比較
選取了文獻(xiàn)[12]的SQL注入攻擊測試集T,使用腳本在服務(wù)器本機(jī)對Web應(yīng)用的首頁發(fā)送訪問請求,然后分別統(tǒng)計加載和不加載PHPGate的應(yīng)答時間.由于在服務(wù)器本機(jī)進(jìn)行測試,網(wǎng)絡(luò)延遲可以忽略不計,而且網(wǎng)絡(luò)延遲在PHPGate關(guān)閉和開啟的情況下可以認(rèn)為一致,不影響測試結(jié)果.對每個頁面進(jìn)行了50次請求,然后統(tǒng)計應(yīng)答時間的平均值以及時間損耗.
表6列出了測試集T中Web應(yīng)用的代碼規(guī)模(line of code, LOC)以及使用PHPGate帶來的性能損失,對比列出了文獻(xiàn)[12]的性能損失.
Table 6 Overhead Comparison on Benchmark T
diglossia[12]使用污點分析結(jié)合SQL語句語法分析進(jìn)行SQL注入攻擊檢測.表6中的列3和列4顯示了diglossia[12]在污點標(biāo)記、傳播中帶來的性能損耗以及加上SQL語句語法解析帶來的性能損耗.可以看出:一方面,diglossia[12]的污點分析在測試集T上帶來了一定的性能損耗;另一方面,SQL語句語法分析影響了diglossia[12]在測試集T上的性能.
在測試集T上,PHPGate的性能損失幾乎為0:一方面在于測試集T中的頁面相對簡單,字符串操作較少,并且PHPGate是輕量級的污點標(biāo)記及傳播方案(如表5所示);另一方面,PHPGate無需依賴SQL語句語法解析,直接轉(zhuǎn)義非可信敏感字符進(jìn)行SQL注入攻擊防御.
3) 真實頁面的性能損失
在使用測試集進(jìn)行性能測試之外,還針對真實頁面對PHPGate進(jìn)行性能評估.使用Python腳本在服務(wù)器本機(jī)對測試頁面以POST方式發(fā)送登陸請求,然后統(tǒng)計應(yīng)答時間.對每個頁面進(jìn)行了10 000次請求,然后統(tǒng)計應(yīng)答時間的平均值.表7展示了使用PHPGate前后頁面訪問服務(wù)器應(yīng)答時間的測試結(jié)果.可以看出,頁面訪問的應(yīng)答時間增加比例均在1.6%之內(nèi).
Table 7 Overhead on Popular Web Applications
圍繞SQL注入攻擊防御的研究一直在持續(xù)進(jìn)行[16-18].研究人員嘗試根據(jù)一定的策略來推理出SQL語句中的可信和不可信部分[19-22],這種方式依賴于推理策略的完備性,準(zhǔn)確性不能得到保證.而基于污點分析的方案能通過污點標(biāo)記、污點傳播直接、準(zhǔn)確地區(qū)分SQL語句中的可信和不可信部分,相對比較可靠,主要分為靜態(tài)污點分析和動態(tài)污點分析2種.
靜態(tài)污點分析中,Jovanovic等人提出的Pixy[23]采用流敏感、過程間和上下文敏感的靜態(tài)數(shù)據(jù)流分析方法來挖掘Web應(yīng)用漏洞.Livshits和Lam[24]利用靜態(tài)數(shù)據(jù)流分析技術(shù)檢查經(jīng)過標(biāo)記的用戶輸入是否到達(dá)SQL語句執(zhí)行點,以此來挖掘SQL注入漏洞.Wassermann和Su將SQL語句構(gòu)造過程抽象為一個上下文無關(guān)文法,用靜態(tài)污點分析方法判斷該文法中的非終止符是否與用戶輸入相關(guān)[25].Dahse 和Holz采用靜態(tài)污點分析方法挖掘二階式注入漏洞[26],更進(jìn)一步利用對900多個PHP內(nèi)置函數(shù)的分析和模擬來進(jìn)行更精確的靜態(tài)污點分析[27].但由于靜態(tài)污點分析方法無法很好地處理Web應(yīng)用程序語言的動態(tài)特性,所以會引入較高的漏報,加上其需要保守式的程序分析,所以也會帶來較多的誤報.
動態(tài)污點分析方法則能更好地應(yīng)對程序的動態(tài)特性:Nguyen-Tuong等人[28]修改PHP引擎中String類的數(shù)據(jù)結(jié)構(gòu)和函數(shù)操作,在字符級別對不可信數(shù)據(jù)進(jìn)行污點標(biāo)記與傳播,在Sink檢查點分析SQL語句的語法結(jié)構(gòu),不允許SQL敏感字符和關(guān)鍵字來自不可信數(shù)據(jù).Pietraszek和Berghe的CSSE[29]則是在PHP引擎中使用一個以變量指針為索引、以bitmap為值類型的查詢表來實現(xiàn)對不可信數(shù)據(jù)逐字符的污點標(biāo)記.Xu等人[30]基于C語言代碼的自動轉(zhuǎn)換,動態(tài)維護(hù)了一個以單個字節(jié)的地址為索引、以0或1為值的查詢表,通用地對C語言程序增強(qiáng)了污點標(biāo)記與跟蹤功能,并對PHP引擎進(jìn)行了實現(xiàn).
上述方法屬于消極污點分析,即對不可信輸入進(jìn)行污點標(biāo)記,并在程序執(zhí)行過程中對這些污點標(biāo)記進(jìn)行傳播.但是由于不可信輸入的類型和來源均比較廣泛[29],對這些數(shù)據(jù)的漏標(biāo)記很容易造成漏報.而相對來說,可信數(shù)據(jù)的來源一般比較固定,如程序員寫在Web程序中的常量字符串[29,31].基于這一思想,研究人員提出了積極污點分析的方法來檢測SQL注入攻擊:Halfond等人[11,15]提出了WASP,對程序中常量字符串設(shè)置可信標(biāo)記并動態(tài)跟蹤該可信標(biāo)記的傳播,通過該標(biāo)記來區(qū)分生成的SQL語句中的可信部分和不可信部分.由于所有的不可信輸入均以未標(biāo)記形式存在,該類方法能夠避免漏報,較精確地檢測SQL注入攻擊.
在邊界標(biāo)記方案中,Su和Wassermann在SQLCHECK中[13]用程序隨機(jī)選的4個字符起始標(biāo)記和結(jié)束標(biāo)記來對不可信的用戶輸入進(jìn)行標(biāo)識,將SQL語句的上下文無關(guān)文法轉(zhuǎn)換為一個支持該起始標(biāo)記和結(jié)束標(biāo)記的上下文無關(guān)文法,若在檢查點不能根據(jù)新的文法對帶有起始和結(jié)束標(biāo)記的SQL字符串進(jìn)行解析,則說明用戶輸入影響了SQL的語法結(jié)構(gòu),從而判定發(fā)生了SQL注入攻擊.李舟軍等人的PHPHard[32]則基于類似的邊界標(biāo)記思想,積極污點標(biāo)記PHP應(yīng)用中常量字符串和內(nèi)聯(lián)HTML代碼,通過邊界標(biāo)記的傳播來動態(tài)跟蹤響應(yīng)頁面的安全區(qū)間,用來檢測跨站腳本攻擊.
在隨機(jī)化方案中, Boyd和Keromytis認(rèn)為影響SQL語句語義結(jié)構(gòu)的關(guān)鍵詞必須來自于程序員寫的常量字符串,而不能來自不安全的用戶輸入,他們設(shè)計的SQLrand[33]是一種類似指令集隨機(jī)化的防護(hù)方案,將常量字符串中的SELECT、WHERE等關(guān)鍵詞后附加一個隨機(jī)整數(shù)進(jìn)行隨機(jī)化,通過隨機(jī)化來標(biāo)記可信的關(guān)鍵詞,然后在應(yīng)用程序和數(shù)據(jù)庫之間設(shè)置一個中間代理,該代理基于一個支持隨機(jī)化關(guān)鍵詞的SQL語法解析器來檢查SQL語句的合法性并將其去隨機(jī)化后傳輸給數(shù)據(jù)庫.攻擊者可以猜測作為污點標(biāo)記的隨機(jī)整數(shù)并嘗試構(gòu)造攻擊,此外,由于需要一個代理在應(yīng)用程序和數(shù)據(jù)庫之間進(jìn)行通信,SQLrand的部署也受到限制.
本文提出了基于敏感字符的SQL注入攻擊防御方法,結(jié)果表明該方法能夠高效、精確防御SQL注入攻擊.該方法首先基于積極污點分析思想,將污點標(biāo)記范圍從可信的常量字符串縮小到可信的SQL敏感字符;其次利用UTF-8單字節(jié)字符的編碼空洞,采用編碼轉(zhuǎn)換的方式對可信敏感字符進(jìn)行污點標(biāo)記,避免了額外開辟空間存儲污點信息;最后利用污點信息區(qū)分可信敏感字符和非可信敏感字符,在非可信敏感字符前添加轉(zhuǎn)義符,防御SQL注入攻擊.該方法實現(xiàn)為PHP插件,易于部署,可以自動和精確防御SQL注入攻擊,廣泛適用于UTF-8編碼的Web應(yīng)用程序.
本文的防護(hù)效果實驗驗證了PHPGate對SQL注入攻擊防御的有效性.盡管實驗中的攻擊案例都是利用已知漏洞來構(gòu)造攻擊輸入,但該方法同樣可以對利用未知漏洞的SQL注入攻擊進(jìn)行防御,因為無論漏洞成因以及攻擊輸入如何構(gòu)造,污點信息均以非標(biāo)準(zhǔn)單字節(jié)編碼的形式傳播到SQL語句,可以通過污點信息區(qū)分可信和非可信敏感字符,進(jìn)而通過對非可信敏感字符的轉(zhuǎn)義來防御針對未知漏洞的SQL注入攻擊.
[1]Ray D, Ligatti J. Defining code-injection attacks[C] //Proc of the 39th Annual ACM SIGPLAN-SIGACT Symp on Principles of Programming Languages. New York: ACM, 2012: 179-190
[2]Ray D, Ligatti J. Defining injection attacks[G] //LNCS 8783: Proc of the 17th Int Conf on Information Security. Berlin: Springer, 2014: 425-441
[3]The Open Web Application Security Project. OWASP TOP10 critical Web application security risks[EB/OL].[2015-11-05]. https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project
[4]Zhao Yufei, Xiong Gang, He Longtao, et al. Approach to detecting SQL injection behaviors in network environment[J]. Journal of Communications, 2016, 37(2): 88-97 (in Chinese)(趙宇飛, 熊剛, 賀龍濤, 等. 面向網(wǎng)絡(luò)環(huán)境的SQL注入行為檢測方法[J]. 通信學(xué)報, 2016, 37(2): 88-97)
[5]The Open Web Application Security Project. SQL Injection Prevention Cheat Sheet[EB/OL].[2015-11-05]. https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet
[6]Clarke J. SQL Injection Attacks and Defense[M]. Amsterdam: Elsevier, 2012(Clarke J. SQL注入攻擊與防御[M]. 施宏斌, 葉愫, 譯. 2版. 北京: 清華大學(xué)出版社, 2013)
[7]Balzarotti D, Cova M, Felmetsger V, et al. Saner: Composing static and dynamic analysis to validate sanitization in Web applications[C] //Proc of the 2008 IEEE Symp on Security and Privacy. Piscataway, NJ: IEEE, 2008: 387-401
[8]Kieyzun A, Guo P J, Jayaraman K, et al. Automatic creation of SQL injection and cross-site scripting attacks[C] //Proc of the 31st Int Conf on Software Engineering. Piscataway, NJ: IEEE, 2009: 199-209
[9]Martin M, Lam M S. Automatic generation of XSS and SQL injection attacks with goal-directed model checking[C] //Proc of the 17th USENIX Security Symp. Berkeley: USENIX Association, 2008: 31-43
[10]Appelt D, Nguyen C D, Briand L C, et al. Automated testing for SQL injection vulnerabilities: An input mutation approach[C] //Proc of the 2014 Int Symp on Software Testing and Analysis. New York: ACM, 2014: 259-269
[11]Halfond W G J, Orso A, Manolios P. Using positive tainting and syntax-aware evaluation to counter SQL injection attacks[C] //Proc of the 14th ACM SIGSOFT Int Symp on Foundations of Software Engineering. New York: ACM, 2006: 175-185
[12]Son S, Mckinley K S, Shmatikov V. Diglossia: Detecting code injection attacks with precision and efficiency[C] //Proc of the 2013 ACM SIGSAC Conf on Computer and Communications Security. New York: ACM, 2013: 1181-1192
[13]Su Z, Wassermann G. The essence of command injection attacks in Web applications[C] //Proc of the 33rd ACM SIGPLAN-SIGACT Symp on Principles of Programming Languages (POPL). New York: ACM, 2006: 372-382
[14]Offensive Security. Exploits Database[EB/OL].[2015-11-05]. https://www.exploit-db.com
[15]Halfond W G J, Orso A, Manolios P. WASP: Protecting Web applications using positive tainting and syntax-aware evaluation[J]. IEEE Trans on Software Engineering, 2008, 34(1): 65-81
[16]Medeiros I, Neves N F, Correia M. Automatic detection and correction of Web application vulnerabilities using data mining to predict false positives[C] //Proc of the 23rd Int Conf on World Wide Web. New York: ACM, 2014: 63-73
[17]Shar L K, Briand L C, Tan H K, et al. Web application vulnerability prediction using hybrid program analysis and machine learning[J]. IEEE Trans on Dependable and Secure Computing, 2015, 12(6): 688-707
[18]Shar L K, Tan H K, Briand L C. Mining SQL injection and cross site scripting vulnerabilities using hybrid program analysis[C] //Proc of the 2013 Int Conf on Software Engineering. Piscataway, NJ: IEEE, 2013: 642-651
[19]Naderi-Afooshteh A, Nguyen-Tuong A, Bagheri-Marzijarani M, et al. Joza: Hybrid taint inference for defeating Web application SQL injection attacks[C] //Proc of the 45th Annual IEEE/IFIP Int Conf on Dependable Systems and Networks(DSN). Piscataway, NJ: IEEE, 2015: 172-183
[20]Bandhakavi S, Bisht P, Madhusudan P, et al. CANDID: Preventing SQL injection attacks using dynamic candidate evaluations[C] //Proc of the 14th ACM Conf on Computer and Communications Security. New York: ACM, 2007: 12-24
[21]Sekar R. An efficient black-box technique for defeating Web application attacks[C] //Proc of the 16th Annual Network & Distributed System Security Symp. Reston, VA: Internet Society, 2009
[22]Liu A, Yuan Y, Wijesekera D, et al. SQLProb: A proxy-based architecture towards preventing SQL injection attacks[C] //Proc of the 24th Annual ACM Symp on Applied Computing. New York: ACM, 2009: 2054-2061
[23]Jovanovic N, Kruegel C, Kirda E. Pixy: A static analysis tool for detecting Web application vulnerabilities[C] //Proc of 2006 IEEE Symp on Security and Privacy. Piscataway, NJ: IEEE, 2006: 258-263
[24]Livshits V B, Lam M S. Finding security vulnerabilities in Java applications with static analysis[C] //Proc of the 14th Conf on USENIX Security Symp. Berkeley, CA: USENIX Association, 2005: 271-286
[25]Wassermann G, Su Z. Sound and precise analysis of Web applications for injection vulnerabilities[C] //Proc of the 28th ACM SIGPLAN Conf on Programming Language Design and Implementation. New York: ACM, 2007: 32-41
[26]Dahse J, Holz T. Static detection of second-order vulnerabilities in Web applications[C] //Proc of the 23rd USENIX Conf on Security Symp. Berkeley, CA: USENIX Association, 2014: 989-1003
[27]Dahse J, Holz T. Simulation of built-in PHP features for precise static code analysis[C] //Proc of the 2014 Network and Distributed System Security Symp(NDSS). Reston, VA: Internet Society, 2014
[28]Nguyen-Tuong A, Guarnieri S, Greene D, et al. Automatically hardening Web applications using precise tainting[C] //Proc of the 20th IFIP Int Information Security Conf. Berlin: Springer, 2005: 295-307
[29]Pietraszek T, Berghe C V. Defending against injection attacks through context-sensitive string evaluation[G] //LNCS 3858: Proc of the 8th Int Conf on Recent Advances in Intrusion Detection. Berlin: Springer, 2005: 124-145
[30]Xu W, Bhatkar S, Sekar R. Taint-enhanced policy enforcement: A practical approach to defeat a wide range of attacks[C] //Proc of the 15th Conf on USENIX Security Symp. Berkeley, CA: USENIX Association, 2006: 121-136
[31]Mui R, Frankl P. Preventing Web application injections with complementary character coding[G] //LNCS 6879: Proc of the 16th European Symp on Research in Computer Security. Berlin: Springer, 2011: 80-99
[32]Wang Yi, Li Zhoujun, Guo Tao. Literal tainting method for preventing code injection attack in Web application[J]. Journal of Computer Research and Development, 2012, 49(11): 2414-2423 (in Chinese)(王溢, 李舟軍, 郭濤. 防御代碼注入式攻擊的字面值污染方法[J]. 計算機(jī)研究與發(fā)展, 2012, 49(11): 2414-2423)
[33]Boyd S W, Keromytis A D. SQLrand: Preventing SQL injection attacks[G] //LNCS 3089: Proc of the 2nd Int Conf in Applied Cryptography and Network Security. Berlin: Springer, 2004: 292-302
[34]Mui R. Techniques for injection-safe Web applications[D]. New York: Polytechnic Institute of New York University, 2013
[35]Ahuja B K, Jana A, Swarnkar A, et al. On preventing SQL injection attacks[G] //AISC 395: Advanced Computing and Systems for Security. Berlin: Springer, 2016: 49-64
[36]Heart K. Process Using Universal Sanitization to Prevent Injection Attacks: USA, US20150156209A1[P]. 2015-06-04
[37]Zekan B, Shtern M, Tzerpos V. Protecting Web applications via unicode extension[C] //Proc of the 22nd IEEE Int Conf on Software Analysis, Evolution and Reengineering (SANER). Piscataway, NJ: IEEE, 2015: 419-428
[38]Masri W, Sleiman S. SQLPIL: SQL injection prevention by input labeling[J]. Security and Communication Networks, 2015, 8(15): 2545-2560
Zhang Huilin, born in 1987. PhD candidate in the Institute of Computer Science and Technology, Peking University. Her main research interests include software and Web security.
Ding Yu, born in 1988. PhD. His main research interests include software and system security (dingelish@pku.edu.cn).
Zhang Lihua, born in 1991. Master. Her main research interests include software and system security (zhanglh@pku.edu.cn).
Duan Lei, born in 1989. Master. His main research interests include software and system security (lei_duan@pku.edu.cn).
Zhang Chao, born in 1986. Postdoctor at University of California, Berkeley. His main research interests include software and system security (chaoz@berkeley.edu).
Wei Tao, born in 1975. PhD. Chief Security Scientist of Baidu Inc and the Co-organizer of UC Berkeley BitBlaze Group. His main research interests include mobile security, network and Web security (lenx.wei@gmail.com).
Li Guancheng, born in 1993. Master candidate in Peking University. His main research interests include software and system security (sunatum@outlook.com).
Han Xinhui, born in 1969. PhD. Senior engineer in Peking University. Member of China Computer Federation. His main research interests include network security and Web security.
SQL Injection Prevention Based on Sensitive Characters
Zhang Huilin1, Ding Yu1, Zhang Lihua1, Duan Lei1, Zhang Chao2, Wei Tao3, Li Guancheng1, and Han Xinhui1
1(InstituteofComputerScienceandTechnology,PekingUniversity,Beijing100080)2(UniversityofCaliforniaatBerkeley,Berkeley,CA, 94720)3(BaiduUSALimitedLiabilityCompany,Sunnyvale,CA, 94089)
SQL injection attacks are prevalent Web threats. Researchers have proposed many taint analysis solutions to defeat this type of attacks, but few are efficient and practical to deploy. In this paper, we propose a practical and accurate SQL injection prevention method by tainting trusted sensitive characters into extended UTF-8 encodings. Unlike typical positive taint analysis solutions that taint all characters in hard-coded strings written by the developer, we only taint the trusted sensitive characters in these hard-coded strings. Furthermore, rather than modifying Web application interpreter to track taint information in extra memories, we encode the taint metadata into the bytes of trusted sensitive characters, by utilizing the characteristics of UTF-8 encoding. Lastly, we identify and escape untrusted sensitive characters in SQL statements to prevent SQL injection attacks, without parsing the SQL statements. A prototype called PHPGate is implemented as an extension on the PHP Zend engine. The evaluation results show that PHPGate can protect Web applications from real world SQL injection attacks and introduce a low performance overhead (less than 1.6%).
SQL injection attack; trusted sensitive character; dynamic taint analysis; positive taint analysis; UTF-8 encoding
2016-06-16;
2016-08-11
國家自然科學(xué)基金項目(61572149,61402125)
韓心慧(hanxinhui@pku.edu.cn)
TP393.08
This work was supported by the National Natural Science Foundation of China (61572149, 61402125).