1. 程式人生 > >學點算法搞安全之HMM(下篇)

學點算法搞安全之HMM(下篇)

例如 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(下篇)