學點算法搞安全之HMM(下篇)
阿新 • • 發佈:2017-05-15
例如 continue 生成 fcc foo post 序列化 eas 重復 前言
上篇我們介紹了HMM的基本原理以及常見的基於參數的異常檢測實現,這次我們換個思路,把機器當一個剛入行的白帽子,我們訓練他學會XSS的攻擊語法,然後再讓機器從訪問日誌中尋找符合攻擊語法的疑似攻擊日誌。
通過詞法分割,可以把攻擊載荷序列化成觀察序列,舉例如下:
詞集/詞袋模型
詞集和詞袋模型是機器學習中非常常用的一個數據處理模型,它們用於特征化字符串型數據。一般思路是將樣本分詞後,統計每個詞的頻率,即詞頻,根據需要選擇全部或者部分詞作為哈希表鍵值,並依次對該哈希表編號,這樣就可以使用該哈希表對字符串進行編碼。
根據詞匯表生成詞集:
- 詞集模型:單詞構成的集合,集合自然每個元素都只有一個,也即詞集中的每個單詞都只有一個
- 詞袋模型:如果一個單詞在文檔中出現不止一次,並統計其出現的次數
dataset = [[‘my‘, ‘dog‘, ‘has‘, ‘flea‘, ‘problems‘, ‘help‘, ‘please‘], [‘maybe‘, ‘not‘, ‘take‘, ‘him‘, ‘to‘, ‘dog‘, ‘park‘, ‘stupid‘], [‘my‘, ‘dalmation‘, ‘is‘, ‘so‘, ‘cute‘, ‘I‘, ‘love‘, ‘him‘], [‘stop‘, ‘posting首先生成詞匯表:‘, ‘stupid‘, ‘worthless‘, ‘garbage‘], [‘mr‘, ‘licks‘, ‘ate‘, ‘my‘, ‘steak‘, ‘how‘, ‘to‘, ‘stop‘, ‘him‘], [‘quit‘, ‘buying‘, ‘worthless‘, ‘dog‘, ‘food‘, ‘stupid‘]]
1 vocabSet = set() 2 for doc in dataset: 3 vocabSet |= set(doc) 4 vocabList = list(vocabSet)
1 # 詞集模型 2 SOW = [] 3 for doc in dataset: 4 vec = [0]*len(vocabList) 5 for i, word in enumerate(vocabList): 6 if word in doc: 7 vec[i] = 1 8 SOW.append(doc)簡化後的詞集模型的核心代碼如下:
1 fredist = nltk.FreqDist(tokens_list) # 單文件詞頻 2 keys=fredist.keys() 3 keys=keys[:max] #只提取前N個頻發使用的單詞 其余泛化成0 4 for localkey in keys: # 獲取統計後的不重復詞集 5 if localkey in wordbag.keys(): # 判斷該詞是否已在詞集中 6 continue 7 else: 8 wordbag[localkey] = index_wordbag 9 index_wordbag += 1數據處理與特征提取 常見的XSS攻擊載荷列舉如下:
<script>alert(‘XSS‘)</script> %3cscript%3ealert(‘XSS‘)%3c/script%3e %22%3e%3cscript%3ealert(‘XSS‘)%3c/script%3e <IMG SRC="javascript:alert(‘XSS‘);"> <IMG SRC=javascript:alert("XSS")> <IMG SRC=javascript:alert(‘XSS‘)> <img src=xss onerror=alert(1)> <IMG """><SCRIPT>alert("XSS")</SCRIPT>"> <IMG SRC=javascript:alert(String.fromCharCode(88,83,83))> <IMG SRC="jav ascript:alert(‘XSS‘);"> <IMG SRC="jav ascript:alert(‘XSS‘);"> <BODY BACKGROUND="javascript:alert(‘XSS‘)"> <BODY ONLOAD=alert(‘XSS‘)>需要支持的詞法切分原則為:
● 單雙引號包含的內容 ‘XSS‘ ● http/https鏈接 http://xi.baidu.com/xss.js ● <>標簽 <script> ● <>標簽開頭 <BODY ● 屬性標簽 ONLOAD= ● <>標簽結尾 > ● 函數體 "javascript:alert(‘XSS‘);" ● 字符數字標量代碼實現舉例如下:
1 tokens_pattern = r‘‘‘(?x) 2 "[^"]+" 3 |http://\S+ 4 |</\w+> 5 |<\w+> 6 |<\w+ 7 |\w+= 8 |> 9 |\w+\([^<]+\) #函數 比如alert(String.fromCharCode(88,83,83)) 10 |\w+ 11 ‘‘‘ 12 words=nltk.regexp_tokenize(line, tokens_pattern)另外,為了減少向量空間,需要把數字和字符以及超鏈接範化,具體原則為:
#數字常量替換成8 line, number = re.subn(r‘\d+‘, "8", line) #ulr日換成http://u line, number = re.subn(r‘(http|https)://[a-zA-Z0-9\.@&/#!#\?]+‘, "http://u", line) #幹掉註釋 line, number = re.subn(r‘\/\*.?\*\/‘, "", line)範化後分詞效果示例為:
#原始參數值:"><img src=x onerror=prompt(0)>) #分詞後: [‘>‘, ‘<img‘, ‘src=‘, ‘x‘, ‘onerror=‘, ‘prompt(8)‘, ‘>‘] #原始參數值:<iframe src="x-javascript:alert(document.domain);"></iframe>) #分詞後: [‘<iframe‘, ‘src=‘, ‘"x-javascript:alert(document.domain);"‘, ‘>‘, ‘</iframe>‘] #原始參數值:<marquee><h1>XSS by xss</h1></marquee> ) #分詞後: [‘<marquee>‘, ‘<h8>‘, ‘XSS‘, ‘by‘, ‘xss‘, ‘</h8>‘, ‘</marquee>‘] #原始參數值:<script>-=alert;-(1)</script> "onmouseover="confirm(document.domain);"" </script>) #分詞後: [‘<script>‘, ‘alert‘, ‘8‘, ‘</script>‘, ‘"onmouseover="‘, ‘confirm(document.domain)‘, ‘</script>‘] #原始參數值:<script>alert(2)</script> "><img src=x onerror=prompt(document.domain)>) #分詞後: [‘<script>‘, ‘alert(8)‘, ‘</script>‘, ‘>‘, ‘<img‘, ‘src=‘, ‘x‘, ‘onerror=‘, ‘prompt(document.domain)‘, ‘>‘]結合詞集模型,完整的流程舉例如下: 訓練模型 將範化後的向量X以及對應的長度矩陣X_lens輸入即可,需要X_lens的原因是參數樣本的長度可能不一致,所以需要單獨輸入。
1 remodel = hmm.GaussianHMM(n_components=3, covariance_type="full", n_iter=100) 2 remodel.fit(X,X_lens)驗證模型 整個系統運行過程如下: 驗證階段利用訓練出來的HMM模型,輸入觀察序列獲取概率,從而判斷觀察序列的合法性,訓練樣本是1000條典型的XSS攻擊日誌,通過分詞、計算詞集,提煉出200個特征,全部樣本就用這200個特征進行編碼並序列化,使用20000條正常日誌和20000條XSS攻擊識別(類似JSFUCK這類編碼的暫時不支持),準確率達到90%以上,其中驗證環節的核心代碼如下:
1 with open(filename) as f: 2 for line in f: 3 line = line.strip(‘\n‘) 4 line = urllib.unquote(line) 5 h = HTMLParser.HTMLParser() 6 line = h.unescape(line) 7 if len(line) >= MIN_LEN: 8 line, number = re.subn(r‘\d+‘, "8", line) 9 line, number = re.subn(r‘(http|https)://[a-zA-Z0-9\.@&/#!#\?:]+‘, "http://u", line) 10 line, number = re.subn(r‘\/\*.?\*\/‘, "", line) 11 words = do_str(line) 12 vers = [] 13 for word in words: 14 if word in wordbag.keys(): 15 vers.append([wordbag[word]]) 16 else: 17 vers.append([-1]) 18 np_vers = np.array(vers) 19 pro = remodel.score(np_vers) 20 if pro >= T: 21 print "SCORE:(%d) XSS_URL:(%s) " % (pro,line)
學點算法搞安全之HMM(下篇)