倪 萍,陳 偉
(南京郵電大學計算機學院,南京 210023)
(*通信作者電子郵箱chenwei@njupt.edu.cn)
隨著因特網技術的日益發展,現代萬維網(World Wide Web,WWW)應用程序呈現高度動態、交互性強的特點。Web 用戶是網站的瀏覽者,同時也是網站的創造者。通常,Web應用程序允許捕獲、處理、存儲以及傳輸敏感的客戶數據(比如個人詳細信息、信用卡號等)[1]以供客戶使用。因此,Web 應用程序已經成為黑客們的特別關注點,進而帶來的就是一系列的Web 安全威脅,如結構化查詢語言(Structured Query Language,SQL)注入、跨站腳本(Cross-Site Scripting,XSS)、文件上傳、命令執行等[2]。
根據White Hat Security 的統計分析,XSS 攻擊約占網絡攻擊的一半。在2004、2007、2010、2013 以 及2017 年 的OWASP TOP 10[3]中,XSS 分別位居第四、第四、第一、第三、第七名,并且,2019 年的互聯網安全威脅報告顯示,利用XSS 漏洞引起的釣魚攻擊和表單劫持給企業帶來了巨大損失。XSS攻擊主要是由于攻擊者向Web 應用程序頁面中嵌入惡意的腳本代碼,在用戶瀏覽相關頁面時,這些惡意腳本會在客戶端瀏覽器中執行,從而引發攻擊,竊取用戶隱私,損害用戶利益[4-5]。因此,積極應對并充分保護網站免受此類攻擊變得越來越重要。
傳統的XSS檢測方法一般是通過黑名單備份的方式進行過濾,當網絡一旦獲取到黑名單中存在的數據就進行攔截,從而避免了一些惡意請求。盡管該過濾器能對Web 用戶起到一定的保護作用,但是對于一些經過加密的數據就無法被準確地檢測到,檢測質量并不高。目前,盡管有許多研究人員通過靜態或動態的測試方法來對XSS 漏洞進行檢測,但也暴露出了一些問題:靜態分析是通過對應用程序的源代碼進行分析來發現系統中潛在的漏洞[6],但在很多情況下,研究人員無法輕易獲取到程序源碼;動態分析[7]雖然相較于靜態分析而言,適用性較強,并且無須源碼,但是不全面的攻擊向量可能會造成較高的誤報率,所以需要向漏洞點注入大量的攻擊向量來降低誤報率,可是這樣針對性不強,并且會大大增加檢測時間,降低效率。
針對以上問題,本文所做的主要工作如下:
1)傳統的網絡爬蟲技術是通過對給定的統一資源定位符(Uniform Resource Locator,URL)進行迭代爬取,直至達到爬取深度,從而獲得頁面上的注入點。但是由于當前許多Web網頁是通過AJAX 和Javascript 的形式動態產生內容,所以本文通過提取頁面中的JavaScript 腳本以及其中的一些事件屬性,使用JS 引擎進行編譯執行,從而獲取到更多的潛在注入點,為更好地挖掘漏洞奠定基礎。
2)在對模糊測試技術的研究和分析之上,開發和實現了一種基于設計規則和測試用例“變異”的模糊測試算法來生成攻擊語法。由于一般的模糊檢測方案生成攻擊載荷手段單一且容易造成誤報率,所以,本文的創新點在于對攻擊語法中的每個元素使用權重的方式進行標記,根據評估Web 應用程序的響應來進一步調整攻擊語法中的元素權重,由此找到最有潛力的攻擊載荷來發掘應用程序中存在的反射型XSS漏洞。
3)通過與其他兩個流行的XSS 攻擊檢測工具進行對比,實驗結果表明,本文對模糊測試方法的改進方式是有效的,該方法在漏洞檢測率和誤報率上呈現一定優勢。
XSS 漏洞作為Web 應用程序中最嚴重的安全威脅之一[8-9],自1996 年被發現以來便引起了國內外學者的廣泛關注,很多研究組織或機構人員已經對其檢測工作作了大量的研究并提出相關方法,主要包括三類:靜態分析方法、動態分析方法以及動靜結合的分析方法[10]。
Zheng 等[11]提出遠程執行代碼漏洞檢測Web 應用程序的路徑敏感靜態分析,這是一種通過路徑和上下文敏感的過程間分析來檢測遠程控制(Remote Control Equipment,RCE)漏洞的方法。分析的特點是以路徑敏感的方式分析Web 應用程序的字符串和非字符串行為。Medeiros 等[12]提出使用靜態分析和數據挖掘檢測來刪除Web應用程序漏洞。
由于靜態分析方法依賴于應用程序的源代碼,而在檢測過程中獲取應用程序源碼是一件非常困難的事情,并且靜態檢測方法也無法驗證漏洞的真實性,所以存在一定的局限性,于是,更多的人傾向于使用動態或動靜結合的方法來檢測漏洞。Duchene 等[13]提出了一種用于檢測Web 應用程序跨站腳本漏洞的黑盒模糊器。該模糊器通過遺傳算法來產生惡意輸入,使用攻擊語法作為算法參數,攻擊語法可以通過限制交叉和變異操作來減少搜索空間并模擬攻擊行為,又由于原始字符串匹配的方法可能無法精確地推斷出污點位置,因此它使用雙重污點推斷來獲得準確的結果。雖然此方法利用控制流依賴和數據流依賴來引導模糊測試并解決了大多數黑盒檢測器無法檢測反射型XSS 的問題,但該方法不支持AJAX 程序,應用范圍受限。程誠等[14]提出了一種基于模糊測試和遺傳算法的XSS漏洞檢測方法。該方法主要是通過分析服務端的過濾機制來定義攻擊向量的語法補全規則,再使用遺傳算法不斷分析和優化攻擊載荷以生成最優向量;可是該方法中使用的攻擊代碼需要手動輸入,人工操作量大,沒有實現自動化。黃文峰等[15]提出了一種使用擴展的巴科斯范式(Extended Backus-Naur Form,EBNF)和二次爬蟲策略相結合的方式檢測XSS 漏洞,但該方法并未涉及反爬蟲及如何對抗Web 應用防火墻(Web Application Firewall,WAF)的措施,而且在實驗階段使用的是自己開發的應用程序,可行性有待考證。
很多基于傳統的XSS漏洞檢測技術在挖掘漏洞注入點方面未考慮網站的反爬機制,亦或者是忽視了那些不支持AJAX的網站,因此導致用戶注入點采集不全面,并且,也因為XSS攻擊載荷種類單一或檢測覆蓋面不足等一系列問題,最終導致系統檢測性能低,無法全面有效地發現漏洞,所以本文提出一種基于模糊測試的反射型XSS漏洞檢測方法。該方法提取了頁面中的JavaScript 腳本,通過JS 引擎進行編譯執行,挖掘更多潛在的用戶注入點,降低了漏報率;同時,還考慮了因攻擊向量選取不足或選取過量而導致的檢測時間長等問題。本文根據探子向量注入獲取輸出點類型,根據輸出點類型選擇相應攻擊語法模式構造攻擊載荷并變異進行檢測,當然,為了更有針對性地利用對網站響應的攻擊載荷進行分析并生成更加高效的攻擊載荷從而更快地找到存在的漏洞,本文提出了一種基于模糊測試的反射型XSS 漏洞檢測技術,通過對攻擊語法中的每一個元素進行初始化權重值,再根據服務器響應情況調整權重由此生成更優質的攻擊載荷,進而節約了檢測時間、提高了檢測效率。
2.1.1 定義及其基本原理
網絡爬蟲[16]是根據一定的規則,自動地爬取互聯網信息的一個程序或者一段腳本,被廣泛應用于各種搜索引擎以及其他相關網站[17],能夠自動獲取其能訪問到的所有頁面內容信息。
網絡爬蟲從功能上來說一般分為數據采集、處理、存儲三個部分。首先從給定的一個或者若干個網站URL 開始,獲取初始URL,然后對頁面內容進行分析,尋找頁面中包含的其他鏈接地址存入待爬取隊列中,根據待爬取隊列中的鏈接依次出隊經過解析獲取其中的URL 信息,由此循環,直至滿足某個條件后停止工作。
2.1.2 抓取策略
在網絡爬蟲系統中,待爬取URL 隊列是特別重要的一個部分,在待爬取URL 隊列中URL 以一種什么樣的順序進行存儲是一個會直接決定爬取效率的因素,所以,如何選擇影響到這些URL 順序的抓取策略是至關重要的。以下是幾種常見的網絡爬蟲爬取策略:
1)深度優先遍歷策略。一般是從起始網頁開始,對該頁面進行分析,然后選擇其中的一個URL 再次進入解析,如此循環抓取,直至到達一個深度閾值,再返回上一層以同樣的方法進行爬取。由于一般網站,每深入一層,其網頁價值以及PageRank都會有所降低,因此該策略很少被使用。
2)最佳優先遍歷策略。就是根據特定的網頁分析算法來預測待選URL 中與目標網頁類似或相近的URL 進行爬取。因為這種算法只會涉及到網頁分析算法認為“有用”的URL,所以在爬取過程中會忽略掉許多相關頁面,從而降低了爬取質量。
3)廣度優先遍歷策略。是指在采集鏈接的過程中,將當前頁面的所有URL 鏈接都爬取下來,然后再對其子鏈接進行相同操作的分析獲取。該策略實現起來相對簡單,并且能夠較為全面地獲取到網頁中的URL 鏈接,提升了頁面爬取質量。
2.2.1 概念
模糊測試(Fuzzing test)[17]是最初由威斯康星大學的巴頓米勒在1989 年開發的一種軟件測試技術。模糊測試技術通過自動或者半自動地生成無效、意外或隨機數據作為計算機程序的輸入,然后監視程序是否出現異常,例如崩潰、內置代碼斷言失敗等情況,以發現程序中可能存在的錯誤。
和傳統的漏洞挖掘方法比起來,模糊測試更具優勢。由于模糊測試是通過動態實際執行的,而不是靜態分析,所以它比基于源代碼的白盒測試的適用范圍更廣、誤報率更低;模糊測試原理簡單,不存在大量的公式計算和理論推導;其自動化程度高,不同于逆向工程中需要大量的人工參與。模糊測試技術的這些優點讓其成為一種備受歡迎的漏洞挖掘技術。
2.2.2 類型
模糊測試可以分成基于生成的模糊器和基于變異的模糊器,區分它們的關鍵取決于輸入是從頭生成還是通過修改現有的輸入來生成:
1)基于生成的模糊器是從頭開始生成輸入,它不依賴于種子輸入語料庫的存在或質量。
2)基于變異的模糊器在模糊過程中是根據現有的種子輸入語料庫進行的,它通過修改或者突變提供的種子向量來生成輸入數據。
Selenium[18]是一個由ThoughtWorks 公司開發的,用來自動化測試Web 應用程序的工具。它能夠直接運行在瀏覽器上,像真正的用戶一樣操作網頁。
Webdriver 是一組由W3C 協會制定的用來描述瀏覽器操作的標準接口。Selenium Webdriver 無法在瀏覽器上直接運行,必須先運行部署在本地的Webdriver 驅動程序,接著根據驅動程序來啟動瀏覽器,從而控制瀏覽器去執行測試腳本。
本文設計的XSS 漏洞檢測系統整體結構分三個部分,分別是網頁爬蟲模塊、模糊測試用例生成模塊以及攻擊與分析調整模塊。網頁爬蟲模塊又包括爬取子模塊和網頁分析子模塊,爬取子模塊主要負責爬取網站中指定深度的所有有效鏈接,然后將其傳送到網頁分析子模塊來對頁面中的用戶輸入點進行提取,并保存到數據庫中。模糊測試用例生成模塊主要負責通過向爬取到的注入點注入探子向量來獲取輸出點類型,并且選擇對應的攻擊語法形式并用帶有權重值的元素進行填充,以此構造初始有效載荷并進行變異模糊化得到變異攻擊載荷進行測試。攻擊與分析調整模塊主要是將生成的有效載荷通過注入點發送到被測系統(System Under Test,SUT),并且通過觀察服務器返回的響應對元素權重進行調整,由此形成攻擊成功率更高的攻擊載荷進行檢測,從而發現漏洞。系統總體結構如圖1所示。

圖1 系統總體結構Fig.1 Overall system structure
該模塊主要負責對指定網站中的用戶輸入點進行獲取并保存。首先,本文使用基于廣度優先遍歷的網絡爬蟲策略,通過用戶提供的起始URL 作為入口,爬取指定深度的所有有效URL 并將其發送到網頁分析子模塊,在對URL 頁面內容進行解析時,采用定位功能來對所需要的元素信息進行定位,從而獲取到頁面中存在的用戶輸入點,將其提交地址與輸入內容保存到數據庫中,以便之后的注入測試使用。
當然,現在大部分網站需要通過登錄用戶名和密碼才能訪問,所以該模塊可以提供網站的cookie 信息來獲取頁面的超文本標記語言(HyperText Markup Language,HTML)內容。在采集頁面中的信息時,由于目前的Web 網頁中很多內容都是非靜態的,需要通過點擊事件或滑動頁面等操作才能顯示出來,針對這些需要動態加載的數據,本文提取了頁面中的JavaScript 腳本以及其中的一些事件屬性,通過JS 引擎進行編譯執行,從而獲取到動態URL。
在爬取過程中,獲得的部分URL 可能并不是所需要的,比如一些資源文件鏈接、圖片鏈接、重復URL 等,所以,對爬取到的鏈接地址進行有效地過濾是必不可少的步驟。主要的過濾行為有以下幾種:
1)對無效URL 進行過濾。無效URL 包含非同源URL 和非正常URL 兩種情況。首先,同源是指協議名、域名以及端口號都相同的網站。由于每個網站都有可能引入一些站外鏈接,但XSS檢測僅僅是針對本站的URL,因此在爬取過程中只會采集同源URL,就是通過與被檢測的起始URL 進行協議、域名、端口號的比較,如果都一致,則判定為站內域名;否則丟棄。其次就是對一些不正常的URL 進行剔除,比如說一些標簽的src屬性的屬性值是空字符串或者偽協議,這一類的內容不應該加入到待爬取隊列中。
2)對重復URL 進行過濾。在采集過程中,每個頁面可能有重復的URL 會被多次獲取到,進而造成重復解析、浪費系統資源的情況,因此本文使用Bloom Filter+Redis 的方法進行去重,降低重復URL的概率。
3)對相似URL 進行過濾。許多URL 可能在協議、域名、端口號以及參數上完全相同,但參數值不同,對于這類URL也沒必要進行重復解析,占用資源。
4)去除不可訪問URL。通過發送超文本傳輸協議(HyperText Transfer Protocol,HTTP)請求獲取響應狀態碼,檢查狀態碼是否為200,對于那些不可訪問的URL,應予以剔除。
注入點提取模塊的主要流程如下:
步驟1 對用戶提供的初始URL 和爬取深度H進行判斷:若爬取深度是0,則不需要爬取網頁內容;否則,就將初始URL加入待爬取隊列。
步驟2 對待爬取URL 隊列進行遍歷,獲取該URL 對應的網頁源碼。
步驟3 定位查找網頁源碼中的全部URL 并分析其中可能的用戶交互點,對其進行過濾操作后添加到待爬取隊列中。
步驟4 若當前深度的待爬取URL 隊列遍歷結束,則將當前爬取深度加1。
步驟5 如果待爬取URL 隊列為空或者是檢測深度達到用戶提供的爬取深度,那么爬蟲結束;否則返回步驟2。
具體流程如圖2所示。

圖2 爬蟲提取模塊流程Fig.2 Flowchart of crawler extraction module
在對頁面進行解析時,一般包含兩種操作行為:提取新的URL 以及獲取當前頁面注入點。在HTML5中,URL 通常存在于href、src、action 等可以指定網站鏈接的屬性中。同樣,一般情況下,頁面的注入點則存在于form 表單的input 標簽、textarea 標簽或者是iframe 包含的表單中。當然,對于之前所說的潛在注入點,即那些可能導致頁面DOM 結構發生變化或者說是出現更多注入點的用戶交互點標簽,諸如鼠標懸浮、點擊事件等,此時,就需要對當前頁面重新解析并提取所謂的潛在注入點和URL。本文使用python 的第三方庫BeautifulSoup對頁面HTML 進行URL 和注入點搜索,并存于指定隊列中。主要流程如圖3所示。

圖3 注入點提取模塊流程Fig.3 Flowchart of injection point extraction module
檢測XSS 漏洞的主要步驟就是對攻擊向量的合理選取,直接關系到檢測系統的性能問題:若攻擊向量選取不足或者是不適當,則會導致最終的檢測結果誤報漏報情況嚴重;但如果攻擊向量選取過量又會造成檢測效率的下降。所以,為了有效、有質地檢測出XSS漏洞,本文開發了一個通過調整權重值方式來構造最有潛力攻擊載荷的模糊測試生成器,該生成器通過接收元素作為基礎數據,元素指的是JavaScript 和HTML的關鍵字和基本字符,使用配置文件的形式進行定義。
從理論可知,引發XSS 漏洞產生的根本原因是瀏覽器或者服務器端沒有對用戶輸入的內容進行嚴謹或充分的過濾,所以,在檢測該漏洞時要設計足夠且豐富的測試向量來繞過過濾器,從而找到網站漏洞。因此,本文的攻擊載荷生成模塊包括初始攻擊載荷生成和變異攻擊載荷生成。初始攻擊載荷生成模塊的設計主要是為了構建種類豐富的初始XSS攻擊載荷庫,由于攻擊載荷的選取會對漏洞的檢出率產生直接影響,所以使用盡量少的攻擊載荷來檢測更多的漏洞是系統的關鍵,因此在構建初始攻擊載荷庫時結合了目前經過檢驗后比較有效的攻擊向量,且盡量多地分析輸出點類型,以保證初始XSS 攻擊載荷庫豐富而精確,為漏洞檢測提供基礎數據;同樣,為了更多地繞過過濾機制,還對初始攻擊載荷進行模糊化,形成變異攻擊載荷,提高載荷精度。主要過程如圖4 所示。

圖4 攻擊載荷生成模塊過程Fig.4 Process of attack payload generation module
3.2.1 初始攻擊載荷生成
OWASP XSS Cheat Sheet[19]是由國外著名的安全工程師Rsnake 提出的一份XSS 攻擊腳本列表,可以用來對Web 應用程序中的XSS漏洞進行檢測。本文將它當作適當攻擊模式的參考來源,并且在對一些常見用戶輸出點類型分析之后,定義了自己的攻擊載荷語法形式。當然,為了將語法定義轉換成實際的攻擊載荷,有必要對元素進行分組歸類,分別將HTML標簽和HTML 事件定義符號為“TAG_HTML”和“EVENT”;同時,也確定了能夠被瀏覽器解釋為空白的字符,例如“ ”“ ”等;并且,其他的一些閉合元素也被定義,這些字符或符號都被保存在配置文件中。表1 展示了部分攻擊載荷語法的基本元素符號及其對應的元素。

表1 基本元素符號及其對應元素Tab.1 Basic element symbols and their corresponding elements
由于在測試過程中會對每一個注入點注入大量的生成載荷,從而導致客戶端與服務器的交互次數不斷增加,進而降低檢測效率,所以,本文在進行檢測之前先使用探子請求向量進行探測,即在測試之前,構造合法向量注入輸入點,然后根據響應頁面的輸出點類型對攻擊語法模式進行選擇,輸出點類型一般分為如下幾類:
1)HTML 普通標簽之間。HTML 普通標簽一般包括div、p、span、li 等,在這類標簽之間則會選用諸如以下序列組成的攻擊語法:

2)在HTML 標簽屬性值之內。此類輸出點一般存在于如img的src屬性、a標簽的href屬性。這種情況通常會先用閉合模塊將前面的屬性閉合,再進行正常攻擊。此時可以選擇諸如以下序列生成的攻擊語法模板:
3)在HTML 特殊標簽之間。此類標簽一般是指iframe、title、noscript 之類的標簽,因為在這類標簽中,js 腳本無法執行,所以需要先將此類標簽閉合再進行攻擊,這里可以選擇和第2)類一樣的攻擊模板,只不過在這樣的攻擊模板中,“OUTBREAK”不能是單純的符號閉合,而是根據實際情況產生的標簽閉合。
4)在Javascript 偽協議中。用戶輸出有時可能會作為js的一部分,此時可以選擇諸如以下序列組成的攻擊語法:

5)在層疊樣式表(Cascading Style Sheets,CSS)樣式中。CSS作為定義HTML的樣式,主要通過