呂 誠,王軼駿,薛 質(zhì)
(上海交通大學(xué) 網(wǎng)絡(luò)空間安全學(xué)院,上海 200240)
隨著網(wǎng)絡(luò)技術(shù)及其應(yīng)用的快速發(fā)展,Web應(yīng)用在人們?nèi)粘I钪邪缪葜絹碓街匾慕巧?,如購物、社交、銀行服務(wù)、搜索等。但是,SQL注入、緩沖區(qū)溢出、文件上傳、信息泄露、跨站腳本、越權(quán)訪問等Web攻擊對(duì)用戶造成了極大的困擾。隨著傳統(tǒng)操作系統(tǒng)的日益成熟,應(yīng)用漏洞成為了攻擊者攻擊的焦點(diǎn),嚴(yán)重威脅Web應(yīng)用的安全性。Web應(yīng)用的安全性一直以來都受到安全從業(yè)人員的廣泛關(guān)注,對(duì)Web應(yīng)用的安全評(píng)估、Web應(yīng)用防火墻(簡稱WAF)的研究也在不斷發(fā)展[1]。但是,如何獲取用于評(píng)估Web應(yīng)用的安全性和驗(yàn)證WAF有效性的攻擊流量一直困擾著廣大安全研究人員。如果對(duì)受測試的Web應(yīng)用/設(shè)備進(jìn)行真實(shí)攻擊,可能會(huì)留下后門,造成難以預(yù)計(jì)的不良后果;如果直接從網(wǎng)絡(luò)中搜集,難度極大且存在大量噪聲;如果通過搭建靶機(jī)的方式搜集攻擊流量,費(fèi)時(shí)費(fèi)力,成本巨大,且同樣要進(jìn)行真實(shí)攻擊,可能會(huì)對(duì)網(wǎng)絡(luò)造成難以預(yù)計(jì)的影響。
針對(duì)上述情況,本文采用基于Python的符號(hào)執(zhí)行引擎PyExZ3對(duì)Python Web攻擊腳本進(jìn)行動(dòng)態(tài)分析,無需搭建靶機(jī)環(huán)境,無需進(jìn)行真實(shí)攻擊,就可以自動(dòng)提取完整的Web攻擊流量。PyExZ3是一款基于Microsoft開發(fā)的Z3 SMT實(shí)現(xiàn)的開源符號(hào)執(zhí)行引擎,可利用動(dòng)態(tài)符號(hào)執(zhí)行技術(shù)對(duì)Python腳本進(jìn)行動(dòng)態(tài)分析。動(dòng)態(tài)符號(hào)執(zhí)行技術(shù)可以遍歷腳本不同的分支,獲得更多的行為特征。相對(duì)地,在使用符號(hào)執(zhí)行遍歷分支的過程中,可能會(huì)面臨路徑爆炸的難題,產(chǎn)生大量無效分支,導(dǎo)致遲遲難以發(fā)現(xiàn)目標(biāo)分支。
因而,本文將首先對(duì)符號(hào)執(zhí)行技術(shù)進(jìn)行簡單介紹;其次說明為應(yīng)對(duì)路徑爆炸問題做出的改進(jìn),以及對(duì)原有的PyExZ3符號(hào)執(zhí)行引擎的改進(jìn);再次,介紹以改進(jìn)后的原型系統(tǒng)作為工具,對(duì)Web攻擊流量進(jìn)行采集和分類的方法;最后,通過使用改進(jìn)后的原型系統(tǒng)對(duì)Python Web攻擊腳本進(jìn)行動(dòng)態(tài)符號(hào)執(zhí)行分析,證明了開發(fā)的原型系統(tǒng)滿足預(yù)設(shè)目標(biāo),實(shí)現(xiàn)了對(duì)Web攻擊流量的高效采集和分類。
符號(hào)執(zhí)行技術(shù)是在分析源代碼的過程中將代碼中的變量替換為符號(hào)值,模擬程序執(zhí)行流程,通過構(gòu)建單元代碼的控制流圖選擇代碼路徑,當(dāng)遇到分支語句時(shí),提取并存儲(chǔ)不同分支的約束條件,使用約束求解器求解進(jìn)入某一分支所要滿足的條件,最后根據(jù)路徑調(diào)度算法對(duì)控制流圖中的所有路徑進(jìn)行遍歷分析。
自2005年以來,符號(hào)執(zhí)行技術(shù)已經(jīng)成為自動(dòng)化測試領(lǐng)域的重要技術(shù)之一[2]。例如:貝爾實(shí)驗(yàn)室提出的一種自動(dòng)化軟件測試工具DART(Directed Automated Random Testing)[3],大量用于軟件測試、逆向工程等領(lǐng)域;伊利諾亞大學(xué)提出的單元測試工具 CUTE(Concolic Unit Testing Engine for C), 用于處理程序中出現(xiàn)的動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu)指針符號(hào)化的情況[4];斯坦福大學(xué)實(shí)現(xiàn)的自動(dòng)化軟件測試工具KLEE及其前身EXE(Execution generated Executions)[5],用于分析LLVM中間代碼[6]。此外,還有加州大學(xué)伯克利分校的CREST、IBM的Apollo、加州大學(xué)圣芭芭拉分校的angr和Microsoft的PyExZ3等符號(hào)執(zhí)行引擎。
上述的符號(hào)執(zhí)行引擎可以分為三類:第一類是用來分析二進(jìn)制機(jī)器碼的,如angr;第二類是用來分析LLVM中間代碼的,如KLEE;第三類是針對(duì)特定語言的專用符號(hào)執(zhí)行引擎,如PyExZ3[7]。
PyExZ3是Microsoft開發(fā)的一款針對(duì)Python語言的開源符號(hào)執(zhí)行引擎,包含函數(shù)加載模塊、路徑探索模塊、求解器封裝模塊和基礎(chǔ)符號(hào)類型模塊。其中,求解器模塊使用Microsoft研究院設(shè)計(jì)開發(fā)的Z3約束求解器[8]。PyExZ3具有不錯(cuò)的分析性能,同時(shí)也存在一些不足。首先,PyExZ3目前只能對(duì)整型變量進(jìn)行符號(hào)執(zhí)行,不支持對(duì)字符串等其他類型的變量進(jìn)行符號(hào)執(zhí)行;其次,PyExZ3的求解性能依賴于Z3求解器,但一些約束求解問題在當(dāng)前計(jì)算理論發(fā)展的程度下無法求解,會(huì)產(chǎn)生一系列問題。目前主要關(guān)注的問題有:路徑爆炸問題和約束求解問題。
路徑爆炸問題。PyExZ3默認(rèn)使用DFS路徑搜索算法,容易產(chǎn)生路徑爆炸問題。因?yàn)槌绦蛟诿恳粋€(gè)判斷分支處都會(huì)產(chǎn)生兩個(gè)不同的約束,類似樹狀結(jié)構(gòu),所以符號(hào)執(zhí)行要探索的路徑分支以指數(shù)級(jí)增長,尤其在遇到循環(huán)分支時(shí),會(huì)產(chǎn)生大量分支路徑,從而形成路徑爆炸。路徑爆炸對(duì)于內(nèi)存有限的計(jì)算機(jī)設(shè)備而言,不可能遍歷程序所有可執(zhí)行路徑,會(huì)導(dǎo)致程序代碼覆蓋率不足的問題。雖然目前已經(jīng)提出了一些解決方案,如啟發(fā)式函數(shù)算法、緩存中間結(jié)果、剪枝冗余路徑等,但都不能從根本上解決路徑爆炸問題。
約束求解問題。Z3求解器的約束求解效率決定了PyExZ3符號(hào)執(zhí)行引擎的性能。隨著程序結(jié)構(gòu)和場景的日益復(fù)雜,求解復(fù)雜度不斷上升。對(duì)于大規(guī)模的復(fù)雜約束求解問題,會(huì)給約束求解器提出很大的挑戰(zhàn),求解效率會(huì)大幅下降。同時(shí),由于一些非線性約束求解問題的出現(xiàn),求解器無法準(zhǔn)確求解,導(dǎo)致求解失敗。由于約束求解問題在理論上沒有根本解決,故對(duì)于所有的約束求解器都存在這個(gè)問題,是當(dāng)前符號(hào)執(zhí)行發(fā)展的瓶頸之一[9]。
在對(duì)Web攻擊流量進(jìn)行采集的過程中,需要對(duì)字符串類型變量進(jìn)行符號(hào)執(zhí)行。所以,擴(kuò)展了PyExZ3符號(hào)執(zhí)行的基礎(chǔ)類型。同時(shí),針對(duì)它可能深陷循環(huán)而產(chǎn)生路徑爆炸的情況,采用新型循環(huán)優(yōu)化分析方法以提高其分析性能。本原型系統(tǒng)用于采集Python語言編寫的Web攻擊腳本所釋放的攻擊流量,會(huì)對(duì)Python腳本進(jìn)行預(yù)處理,以優(yōu)化原型系統(tǒng)對(duì)Web攻擊流量采集的效率。
PyExZ3目前只支持對(duì)整型變量進(jìn)行符號(hào)執(zhí)行,但PyExZ3基于的Z3約束求解器支持對(duì)整型、浮點(diǎn)型、字符串、數(shù)組、字典類型等變量進(jìn)行符號(hào)執(zhí)行。所以,對(duì)PyExZ3符號(hào)化類型的字符串集擴(kuò)展,只需要探索字符串類型變量的約束條件集,交給Z3求解器求解即可[7]。
設(shè)計(jì)SymbolicStr類和Z3String類來實(shí)現(xiàn)對(duì)字符串類型的符號(hào)執(zhí)行。對(duì)于字符串符號(hào)化處理主要包括三部分:對(duì)字符串長度有約束的情況、對(duì)字符串內(nèi)容有約束的情況和對(duì)子字符串有約束的情況。SymbolicStr類中實(shí)現(xiàn)了對(duì)這三種情況的處理。首先,判斷需要符號(hào)化的變量,如果需要符號(hào)化的變量是字符串類型,則通過SymbolicStr類對(duì)字符串符號(hào)化變量進(jìn)行初始化,初始化為“0”;其次,使用ExplorationEngine類探索代碼路徑,通過Predicate類提取每一個(gè)判斷分支的正反兩個(gè)約束條件,然后通過Constraint類進(jìn)行存儲(chǔ)(Constraint存儲(chǔ)了可以到達(dá)某一具體分支的所有約束條件);最后,Z3String類通過繼承Z3Expression類,將約束條件轉(zhuǎn)化為Z3表達(dá)式,由PathToConstraint類交給Z3約束求解器進(jìn)行求解。
其中,SymbolicStr類創(chuàng)建了符號(hào)化的字符串類型變量,并包含與符號(hào)化字符串處理相關(guān)的函數(shù),如獲取字符串長度函數(shù)getLength()、字符串分割函數(shù)split()和字符串中字符的替換函數(shù)replace()等。Z3String類繼承了Z3Expression類,把符號(hào)化字符串類型的約束轉(zhuǎn)化為Z3約束求解器可識(shí)別的表達(dá)式。針對(duì)字符串類型的符號(hào)執(zhí)行框圖如圖1所示。
SymbolicStr類具有符號(hào)長度屬性,可以根據(jù)路徑條件的不同調(diào)整字符串長度。例如,if len(str)==5,將代碼中長度相關(guān)的約束條件轉(zhuǎn)化為一個(gè)操作數(shù)數(shù)量為1、操作符為“str.len”的expression類實(shí)例,判斷語句根據(jù)長度屬性會(huì)提取正反兩個(gè)約束進(jìn)行下一步遍歷,同時(shí)原型系統(tǒng)也會(huì)動(dòng)態(tài)調(diào)整符號(hào)化字符串str的長度。
SymbolicStr類對(duì)字符串內(nèi)容約束的處理。Z3求解器包含了對(duì)符號(hào)化字符串內(nèi)容的求解,所以只要轉(zhuǎn)化并傳遞所有約束條件即可。
SymbolicStr類具有子字符串屬性,利用split()可以分拆、保存、拼接原始符號(hào)化的字符串。例如:有str、str1和str2三個(gè)字符串,滿足str=str1+str2,當(dāng)遇到控制判斷語句:if(str==“targetString”),原型系統(tǒng)可以給出一個(gè)滿足條件的解{a=“target”,b=“String”},而不僅僅只是{c=“targetString”}。這種特性可以使原型系統(tǒng)的符號(hào)對(duì)象具有良好的傳遞性。
當(dāng)符號(hào)執(zhí)行在遇到循環(huán)時(shí),由于循環(huán)中包含符號(hào)變量,無法確定具體的執(zhí)行次數(shù)。如果對(duì)于每一次迭代都生成兩條路徑,就會(huì)引起路徑爆炸問題。目前,對(duì)于符號(hào)執(zhí)行中的路徑爆炸問題沒有很好的解決方法。針對(duì)上述問題,研究人員嘗試提出了多種解決方案,如基于路徑分析的啟發(fā)式循環(huán)檢測算法,通過排除干擾路徑來解決路徑爆炸問題;通過設(shè)置循環(huán)次數(shù)上限的方式解決路徑爆炸問題。PyExZ3是通過限制循環(huán)最大次數(shù)來解決路徑爆炸問題的。這種方法比較粗暴,且依然會(huì)產(chǎn)生大量無用分支,因?yàn)檫@些分支依然會(huì)存在于待處理分支列表中。同時(shí),由于設(shè)置了循環(huán)次數(shù)上限,也有可能導(dǎo)致符號(hào)執(zhí)行結(jié)果的不精確。
上述第一種方法只有在符號(hào)變量的約束條件是線性時(shí)才有效,當(dāng)符號(hào)變量的約束條件是非線性時(shí)候不能有效降低路徑爆炸帶來的影響;第二種方法比較粗暴,會(huì)損失精度。鑒于此,提出一種針對(duì)循環(huán)中出現(xiàn)非線性約束情況的優(yōu)化方法。作為實(shí)際問題的抽象,以奇偶?xì)w一問題進(jìn)行說明:
def test(x):
while(x>1):
if(x%2==1):
x=3*x+1
else:
x=x/2
return x
當(dāng)程序執(zhí)行到第2行,生成約束x>1在第3行遇到判斷語句時(shí),生成約束x>1&&x%2==1和x>1&&x%2!=1以此類推,假設(shè)第4行的語句執(zhí)行了a次,分別為J1, J2,…, Ja,第6行的語句執(zhí)行了b次,分別為K1,K2,…,Kb,在第n次執(zhí)行循環(huán)時(shí),其中一條路徑約束為{xn-1>0}&&{xJ1%2==1}&&…&&{xJa%2==1}&&{xK1%2==1}&&…&&{xKb%2==1}顯然,這是一個(gè)非線性約束,約束求解器無法識(shí)別并求解,將堆積大量待求解約束,故當(dāng)循環(huán)中遇到非線性約束時(shí)會(huì)產(chǎn)生路徑爆炸問題。
在上述例子中,檢測出約束條件是一個(gè)高次方程f(x)針對(duì)這種情況,可以采用牛頓法對(duì)非線性約束進(jìn)行迭代擬合,將f(x)在x=0處泰勒展開:
取其中的線性部分,然后再繼續(xù)迭代,過程如圖2所示。
依次在xk,xk+1,…處迭代,其值就是符號(hào)變量在當(dāng)前循環(huán)中的值。迭代次數(shù)越多越精確,但也會(huì)耗費(fèi)太多時(shí)間,故可以設(shè)定最大迭代層數(shù)[10]。
<1),且各件產(chǎn)品是否為不合格品相互獨(dú)立.
圖2 牛頓迭代法
本原型系統(tǒng)的使用場景是分析Web攻擊腳本。網(wǎng)絡(luò)上的Web攻擊腳本規(guī)范不一,很難用統(tǒng)一的標(biāo)準(zhǔn)來加載腳本的目標(biāo)函數(shù)。針對(duì)這個(gè)情況,在對(duì)Web攻擊腳本進(jìn)行符號(hào)執(zhí)行前,先對(duì)其進(jìn)行預(yù)處理優(yōu)化。優(yōu)化主要集中在三個(gè)方面:調(diào)整符號(hào)執(zhí)行變量、統(tǒng)一腳本函數(shù)入口和統(tǒng)一Python腳本語言版本。
2.3.1 調(diào)整符號(hào)執(zhí)行變量
在Web攻擊腳本中,有些情況是無法直接進(jìn)行符號(hào)執(zhí)行的。例如,通過構(gòu)造請求來實(shí)現(xiàn)攻擊,構(gòu)造請求的變量不會(huì)出現(xiàn)在函數(shù)參數(shù)列表中,所以無法對(duì)其進(jìn)行符號(hào)執(zhí)行;有些變量雖然在函數(shù)的參數(shù)列表中,但是并不需要進(jìn)行符號(hào)執(zhí)行,如IP地址、端口號(hào)等變量。
針對(duì)這些情況,設(shè)計(jì)了調(diào)整符號(hào)執(zhí)行變量的方法對(duì)腳本進(jìn)行優(yōu)化。
優(yōu)化規(guī)則1:對(duì)需要進(jìn)行符號(hào)執(zhí)行但不在函數(shù)參數(shù)列表中的變量,首先刪除函數(shù)體中該變量的構(gòu)造代碼,然后在函數(shù)列表中添加同名變量;
優(yōu)化規(guī)則2:對(duì)不需要進(jìn)行符號(hào)執(zhí)行但卻在函數(shù)參數(shù)列表中的變量,首先在函數(shù)參數(shù)列表中刪除該變量,然后在函數(shù)體內(nèi)或者函數(shù)體外(全局變量)構(gòu)造同名變量的值;
優(yōu)化規(guī)則3:對(duì)于其他不需要進(jìn)行符號(hào)執(zhí)行但依賴于外部交互的變量,首先刪除函數(shù)體中該變量的構(gòu)造代碼,然后為同名變量指定一個(gè)值。
舉例一個(gè)簡單的POST請求,具體操作如下:
import sys,urllib,urllib2
def getDataFromPOSTRequest(url):
#構(gòu)造POST參數(shù)
wd=input(“search word:”)
data=urllib.urlencode([(‘wd’,wd)])
#構(gòu)造request
req=urllib2.Request(url)
fd=urllib2.urlopen(req,data)
res=“”
#讀取相應(yīng)結(jié)果
while True:
data=fd.read(1024)
if not len(data):
break
res=res+data
# do something with res
…
這個(gè)例子中,需要進(jìn)行預(yù)處理優(yōu)化的有如下幾個(gè)變量:wd、url、req、fd、data、res。
(1)對(duì)于wd,依賴用戶輸入,根據(jù)優(yōu)化規(guī)則3,需要把這一行刪除,然后指定一個(gè)wd值;
(2)對(duì)于url,不需要進(jìn)行符號(hào)執(zhí)行但是在函數(shù)參數(shù)列表中,根據(jù)優(yōu)化規(guī)則2,首先在函數(shù)參數(shù)列表中刪除這個(gè)變量,然后在函數(shù)體內(nèi)(外)構(gòu)造同名變量的值;
(3)對(duì)于req、fd、data,fd通過req請求獲得了一個(gè)類文件描述符,將內(nèi)容寫入緩存data中,根據(jù)優(yōu)化規(guī)則3,需要?jiǎng)h除函數(shù)體中req、fd、data的構(gòu)造代碼,并為其指定一個(gè)值;
(4)對(duì)于res,根據(jù)優(yōu)化規(guī)則1,首先需要?jiǎng)h除函數(shù)體中res的構(gòu)造代碼,然后在函數(shù)列表中添加變量名為res的參數(shù)。
經(jīng)過預(yù)處理優(yōu)化后的腳本如下:
import sys,urllib,urllib2
url=“http://www.baidu.com”
def getDataFromPOSTRequest(res):
wd=“aaa”
data=urllib.urlencode([(‘wd’,wd)])
req=urllib2.Request(url)
fd=urllib2.urlopen(req,data)
#do something with res
…
通過預(yù)處理優(yōu)化后,原型系統(tǒng)就可以在保留獲取到的網(wǎng)絡(luò)數(shù)據(jù)流的同時(shí),對(duì)目標(biāo)變量進(jìn)行符號(hào)執(zhí)行,以獲取完整的網(wǎng)絡(luò)流量。
2.3.2 統(tǒng)一腳本函數(shù)入口
Web攻擊腳本由于規(guī)范不統(tǒng)一,原型系統(tǒng)無法準(zhǔn)確獲取腳本中的核心攻擊函數(shù),導(dǎo)致不能對(duì)其進(jìn)行符號(hào)執(zhí)行。因此,首先需要對(duì)腳本的核心攻擊函數(shù)入口進(jìn)行統(tǒng)一。目前采用的方法是對(duì)腳本進(jìn)行掃描,依次尋找exploit()、run()和main(),將它們統(tǒng)一為exploit()。如果exploit()存在,則不做調(diào)整;如果不存在,查找是否有run();如果run()存在,則函數(shù)名修改為exploit(),并把所有調(diào)用run()的地方進(jìn)行替換;如果沒有run(),就查找是否有main();如果main()存在,則函數(shù)名修改為exploit(),并把所有調(diào)用main()的地方進(jìn)行替換;如果沒有main()則報(bào)錯(cuò),轉(zhuǎn)至人工查看。
2.3.3 統(tǒng)一腳本語言版本
本原型系統(tǒng)是用Python3實(shí)現(xiàn)。但是,在網(wǎng)絡(luò)上用Python語言編寫的Web攻擊腳本中,有的用Python2實(shí)現(xiàn),有的用Python3實(shí)現(xiàn)。兩個(gè)版本的Python之間存在兼容性問題,導(dǎo)致原型系統(tǒng)無法對(duì)Python2編寫的Web攻擊腳本進(jìn)行符號(hào)執(zhí)行。針對(duì)這個(gè)問題,通過使用Python3的官方工具2to3將Python2腳本轉(zhuǎn)化為Python3腳本。對(duì)于少數(shù)轉(zhuǎn)化失敗或者轉(zhuǎn)化出錯(cuò)的Python2腳本,需轉(zhuǎn)至人工查看原因。
利用上述原型系統(tǒng)對(duì)Web攻擊腳本進(jìn)行流量采集,同時(shí)根據(jù)各個(gè)攻擊階段的不同特征,對(duì)攻擊流量進(jìn)行分類,并存儲(chǔ)入庫。
先將Web攻擊腳本進(jìn)行預(yù)處理,統(tǒng)一腳本語言版本,調(diào)整符號(hào)執(zhí)行變量,統(tǒng)一函數(shù)入口,并把腳本中的IP地址和端口號(hào)設(shè)置成特定的值,便于之后的流量采集,然后通過流量的目的IP、目的端口、源IP、源端口進(jìn)行過濾采集流量。因?yàn)樵诜?hào)執(zhí)行過程中會(huì)遍歷代碼的所有分支,所以會(huì)產(chǎn)生多次流量。針對(duì)這種情況,選取其中流量最多的進(jìn)行采集。因?yàn)楣羰『蠊裟_本會(huì)直接退出,所以流量會(huì)比攻擊成功的流量少。
為了能夠更細(xì)致地操控Web攻擊流量,將其運(yùn)用于網(wǎng)絡(luò)靶場中,需要對(duì)Web攻擊流量按階段分類存儲(chǔ)。
3.2.1 分類方法
在真實(shí)的Web攻擊中,攻擊過程大致可以分為4個(gè)階段:檢測、掃描、攻擊、駐留。
根據(jù)上述的四個(gè)攻擊階段,需要先提取各個(gè)階段的Web攻擊流量特征,然后通過這些流量特征對(duì)采集的Web攻擊流量按階段分類。目前,主要的流量識(shí)別技術(shù)有以下三類[11]:基于深層包檢測(Deep Packet Inspection,DPI)的流量識(shí)別技術(shù)、基于行為特征的流量識(shí)別技術(shù)和基于流特征的流量識(shí)別技術(shù)。這三類流量識(shí)別技術(shù)都只能針對(duì)協(xié)議進(jìn)行區(qū)分,但在本項(xiàng)目中,僅根據(jù)協(xié)議的不同并不能對(duì)流量進(jìn)行有效分類,如圖3所示。
圖3 各階段流量和所用協(xié)議對(duì)照
可見,只是對(duì)協(xié)議進(jìn)行區(qū)分顯然不行。針對(duì)這種情況,結(jié)合實(shí)際使用場景,提出流量的尺度特征分析和流量的連接特征分析,從而對(duì)不同階段的流量進(jìn)行區(qū)分,具體執(zhí)行流程如圖4所示。
圖4 流量分類流程
(1)流量的尺度特征
網(wǎng)絡(luò)流量的尺度特征最早是用來作為DDos攻擊的檢測。然而,由于網(wǎng)絡(luò)業(yè)務(wù)流量種類的繁多,網(wǎng)絡(luò)流量的尺度特征檢測一直存在爭議。但在本項(xiàng)目中,只針對(duì)Web攻擊流量的四個(gè)階段的尺度特征進(jìn)行提取,很好地規(guī)避了上述問題。
網(wǎng)絡(luò)流量在總體分布和包長分布上具有明顯特征。在總體分布上,它具有的自相似特征和多分形特征已經(jīng)得到研究者們的普遍認(rèn)可;在包長分布上,它的包長分布呈現(xiàn)出明顯的雙峰特征。在網(wǎng)絡(luò)攻擊的不同階段,攻擊流量包長將發(fā)生一定變化,所以可將流量的尺度特征作為不同階段的流量特征的表現(xiàn)之一[12]。
根據(jù)研究表明,網(wǎng)絡(luò)流量在不同的分析尺度上體現(xiàn)出了不同的行為特征。在大時(shí)間尺度下(1 s及以上)表現(xiàn)出平穩(wěn)自相似特征,在小時(shí)間尺度下(1 s以下)的特征還存在爭議,但多數(shù)研究表明是呈現(xiàn)長相關(guān)特性(自相關(guān)過程具有長相關(guān)特性)。目前,自相似模型是最能描述網(wǎng)絡(luò)流量長相關(guān)的模型。自相關(guān)模型是指在從微秒到小時(shí)的范圍內(nèi),流量由一系列正常流量和一系列突發(fā)期流量組成。突發(fā)期是由一些突發(fā)的子周期組成,而這些子周期又由更小的突發(fā)子周期組成。數(shù)據(jù)流在不同時(shí)間尺度上都表現(xiàn)出相似的特征[13]。在本項(xiàng)目中,雖然時(shí)間尺度屬于大時(shí)間尺度,但由于流量分布較為稀疏,因此采用小時(shí)間尺度的分析方法,采用長相關(guān)特征分析,使用自相似模型。檢測階段通常是ping包,包長較短;掃描階段需要獲取目標(biāo)主機(jī)上安裝的服務(wù)及服務(wù)版本號(hào),所以需要提交表單,故包長比檢測階段長;攻擊階段通常要添加有效載荷,包長較長;駐留階段通常是遠(yuǎn)程執(zhí)行代碼,故包長比攻擊階段短。具體地,把檢測階段流量和攻擊階段流量作為“正?!绷髁?,把掃描階段流量和駐留階段流量作為“突發(fā)期”流量,使用一階分形進(jìn)行檢測。
采用R/S分析法對(duì)網(wǎng)絡(luò)流量時(shí)間序列的分形特征進(jìn)行分析[14],求出自相似指數(shù)Hurst值,根據(jù)Hurst值判斷流量是否具有自相似性。Hurst值是用來描述和刻畫網(wǎng)絡(luò)流量自相似程度大小、強(qiáng)弱程度的唯一參數(shù)。Hurst值的取值范圍為0~1。當(dāng)Hurst=0.5時(shí),該過程為泊松過程,流量之間不存在自相似性;當(dāng)0<Hurst<0.5時(shí),表示負(fù)相關(guān),該過程不具有自相似性;當(dāng)0.5<Hurst<1時(shí),表示正相關(guān),該過程具有自相似性,且Hurst值越大,自相似性程度越強(qiáng)。
具體操作如下。設(shè)Zi=Z1,Z2,Z3,…,Zk是其中一個(gè)時(shí)間序列的連續(xù)k個(gè)值,取對(duì)數(shù)后執(zhí)行一次差分計(jì)算,把數(shù)據(jù)分成相鄰子區(qū)間N,長度為L,NL=k,先對(duì)各子區(qū)間的均值進(jìn)行計(jì)算:
對(duì)各子區(qū)間的標(biāo)準(zhǔn)差進(jìn)行計(jì)算:
求出其均值的累積橫距:
然后計(jì)算其組內(nèi)極差,即:
最后求出Hurst值:
其中,RN表示極差,SN表示標(biāo)準(zhǔn)差,N表示觀察值數(shù)量,H*表示Hurst值。
本項(xiàng)目借鑒網(wǎng)絡(luò)流量異常檢測技術(shù)中常用的分形理論來區(qū)分不同階段的網(wǎng)絡(luò)攻擊流量,一定程度上解決了流量分類問題,但由于本項(xiàng)目中用于自相關(guān)模型計(jì)算的流量較少,可能會(huì)出現(xiàn)分類偏差,需要后續(xù)改進(jìn)。
(2)流量的連接特征
通過對(duì)實(shí)際流量的分析發(fā)現(xiàn),在不同階段,網(wǎng)絡(luò)流量的連接數(shù)也有一定的特征。在檢測和掃描階段,需要對(duì)目標(biāo)系統(tǒng)的IP地址段、開放端口、所用的服務(wù)類型、服務(wù)版本信息等進(jìn)行嘗試連接和掃描因此在這兩個(gè)階段會(huì)有很多發(fā)包,但是收包會(huì)很少。在攻擊和駐留階段,通過前期檢測和掃描階段,已經(jīng)獲得了攻擊目標(biāo)和攻擊點(diǎn),所以對(duì)于每一組連接,發(fā)包和收包基本都是對(duì)應(yīng)的。所以,通過對(duì)網(wǎng)絡(luò)流量中源IP地址、目的IP地址、端口號(hào)等信息的分析和過濾,可以獲得流量的全部連接特征,得知哪些流量是屬于前期的嘗試掃描流量并沒有收到相應(yīng)的回應(yīng)流量包,哪些流量是屬于后期的執(zhí)行攻擊流量能夠收到相應(yīng)的回應(yīng)流量包。
根據(jù)流量的連接特征分析,可以把檢測、掃描階段和攻擊、駐留階段區(qū)分開,再通過流量的尺度特征分析進(jìn)一步把檢測和掃描階段、攻擊和駐留階段區(qū)分開,并打上標(biāo)記。
3.2.2 存儲(chǔ)入庫
根據(jù)上述的對(duì)Web攻擊腳本的預(yù)處理優(yōu)化、符號(hào)執(zhí)行和對(duì)流量的按階段分類,獲得了Web攻擊腳本的名稱、攻擊類型、對(duì)應(yīng)的漏洞編號(hào)和各個(gè)階段的流量。采用MySQL數(shù)據(jù)庫存儲(chǔ)這些信息,其中對(duì)于各個(gè)階段的流量只保存具體的流量信息并保證其時(shí)序性,對(duì)于流量之間的時(shí)間間隔信息并不保存,因?yàn)闀r(shí)間間隔存在一定的隨機(jī)性,會(huì)隨著網(wǎng)絡(luò)狀況的變化而變化。具體過程如圖5所示。
圖5 流量存儲(chǔ)流程
通過使用OSX Sierra系統(tǒng)下的MySQL管理工具Sequel Pro對(duì)MySQL數(shù)據(jù)庫進(jìn)行管理,使用的數(shù)據(jù)庫版本為MySQL 5.7.21,創(chuàng)建表名為WebAttackFlow的數(shù)據(jù)表:
CREATE TABLE `WebAttackFlow`(
`id` INT NOT NULL AUTO_INCREMENT,
`script_name` VARCHAR(100) NOT NULL,
`attack_type` VARCHAR(1000) NOT NULL,
`vulnerability` VARCHAR(100) NOT NULL,
`testingFlow` VARCHAR(5120) NOT NULL,
`scaningFlow` VARCHAR(5120) NOT NULL,
`attackFlow` VARCHAR(5120) NOT NULL,
`residentFlow` VARCHAR(5120) NOT NULL,
PRIMARY KEY(`id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
其中:id為編號(hào),是自增量;script_name為腳本名稱;attack_type為攻擊類型;vulnerability為相應(yīng)漏洞編號(hào);testingFlow為檢測階段流量;scaningFlow為掃描階段流量;attackFlow為攻擊階段流量;residentFlow為駐留階段流量。
為了驗(yàn)證本原型系統(tǒng)針對(duì)Web攻擊腳本生成流量的可靠性,選取針對(duì)Java Struts2 Web框架下多個(gè)漏洞的攻擊腳本(如表1所示)進(jìn)行測試。
表1 測試腳本信息
Struts2是目前企業(yè)主流的JavaEE開發(fā)架構(gòu),具有一定的代表性。首先捕獲真實(shí)流量,在Linux 16.04 LTS虛擬機(jī)中搭建Tomcat服務(wù)器,Tomcat服務(wù)器的版本為apache-tomcat-7.0.90。在Tomcat服務(wù)器上分別用Struts 2.1.8.1(S2-005、S2-009、S2-013、S2-016)、Struts 2.3.18(S2-032)、Struts 2.3.5(S2-045)框架搭建三個(gè)測試環(huán)境作為靶機(jī),然后配置一個(gè)Windows 7虛擬機(jī),將攻擊者IP和靶機(jī)IP調(diào)整至同一個(gè)局域網(wǎng)。運(yùn)行Tomcat服務(wù)器,在攻擊端手動(dòng)執(zhí)行攻擊,并使用Wireshark對(duì)網(wǎng)絡(luò)攻擊流量進(jìn)行捕獲,從而獲得真實(shí)的攻擊流量。獲取符號(hào)執(zhí)行流量,使用本原型系統(tǒng)對(duì)漏洞的攻擊腳本進(jìn)行符號(hào)執(zhí)行,獲取相應(yīng)的攻擊流量。對(duì)攻擊腳本進(jìn)行符號(hào)執(zhí)行的情況如表2所示。
表2 符號(hào)執(zhí)行情況
以S2-009.py為例,選取符號(hào)執(zhí)行流量最多的分支進(jìn)行分析,截取部分流量如表3所示。
表3 符號(hào)執(zhí)行流量摘要
將它與真實(shí)攻擊流量進(jìn)行比對(duì),結(jié)果表明:真實(shí)攻擊流量和符號(hào)執(zhí)行生成的流量相似度很高,內(nèi)容、時(shí)序性和流量類型都是一致的,差別主要集中在時(shí)間間隔上。由于網(wǎng)絡(luò)狀況的瞬息萬變,時(shí)間間隔不同很正常。Web攻擊腳本的攻擊階段往往較為精短,分支語句主要集中在檢測漏洞階段,需要結(jié)合網(wǎng)絡(luò)協(xié)議庫對(duì)攻擊腳本進(jìn)行符號(hào)執(zhí)行,來獲取所有的攻擊流量。檢測失敗的流量較短,其中最長的那一條流量就是完整的攻擊流量。從上述結(jié)果來看,原型系統(tǒng)對(duì)測試腳本具有較好的代碼覆蓋率,能完整地獲取Payload和攻擊流量。
隨后,針對(duì)獲取的完整攻擊流量,利用流量連接特征對(duì)流量進(jìn)行初步區(qū)分,再利用流量的尺度特征對(duì)流量進(jìn)一步分類。同樣,以S2-009.py為例進(jìn)行流量尺度特征分析,如圖6所示。
圖6 流量尺度特征分析
通過對(duì)Hurst值的計(jì)算發(fā)現(xiàn),這些流量具有自相似特征,屬于攻擊階段的流量。S2-009支持GetShell/獲取物理路徑/執(zhí)行CMD命令,故本次攻擊階段的六個(gè)大流量包利用該漏洞分別獲取了目標(biāo)系統(tǒng)的六個(gè)信息:
(1)執(zhí)行CMD命令:whoami;
(2) 獲 取 Web應(yīng) 用 地 址: …/apachetomcat-7.0.90/webapps/S2-009/;
(3)獲取操作系統(tǒng)類型:Linux;
(4)獲取操作系統(tǒng)版本:4.15.0-33-generic;
(5)獲取操作系統(tǒng)架構(gòu):amd64;
(6)獲取當(dāng)前用戶名。
另外,Web攻擊腳本往往較為簡單,沒有復(fù)雜的循環(huán)邏輯。為了測試原型系統(tǒng)對(duì)非線形約束循環(huán)處理的表現(xiàn),利用2.2節(jié)中奇偶?xì)w一問題的代碼對(duì)其進(jìn)行測試。由于采用了牛頓法對(duì)非線性約束進(jìn)行迭代擬合,程序順利跳出循環(huán),沒有因?yàn)槎逊e大量無法求解的非線性約束而造成路徑爆炸問題。
本文基于PyExZ3提出了一種能夠?qū)eb攻擊流量進(jìn)行高效采集和分類的方法。原型系統(tǒng)在PyExZ3基礎(chǔ)上通過對(duì)基礎(chǔ)符號(hào)類型的擴(kuò)展、對(duì)非線性約束循環(huán)的優(yōu)化和針對(duì)Web攻擊腳本的預(yù)處理優(yōu)化三種方式,實(shí)現(xiàn)了對(duì)攻擊流量的采集,解決了傳統(tǒng)Web攻擊流量采集過程中出現(xiàn)的諸多問題,如搭建靶機(jī)環(huán)境費(fèi)時(shí)費(fèi)力,無法控制對(duì)靶機(jī)進(jìn)行攻擊后產(chǎn)生的潛在不良后果等。同時(shí),根據(jù)Web攻擊不同階段的流量特征,實(shí)現(xiàn)了對(duì)攻擊流量的高級(jí)分類,以獲取Web攻擊在不同階段的流量信息并加以存儲(chǔ)。后續(xù)需要進(jìn)一步分析不同階段的Web攻擊流量的特征,以提高對(duì)攻擊流量高級(jí)分類的準(zhǔn)確性,同時(shí)要對(duì)更多的基于Python的Web攻擊腳本所釋放的攻擊流量進(jìn)行采集和分類,為之后搭建網(wǎng)絡(luò)靶場打下基礎(chǔ)。
本原型系統(tǒng)只能針對(duì)Python語言編寫的Web攻擊腳本所釋放的攻擊流量進(jìn)行采集和分類,不適用于其他腳本語言。針對(duì)其他腳本語言的符號(hào)執(zhí)行功能,不是擴(kuò)展本原型系統(tǒng)就能夠完成的,需要針對(duì)特定語言另行搭建專用的流量采集分類系統(tǒng)。因此,完善對(duì)多語言的支持也是后續(xù)工作的努力方向之一。