1. 程式人生 > >《web安全之機器學習入門》第5章K近鄰演算法讀書筆記【下】

《web安全之機器學習入門》第5章K近鄰演算法讀書筆記【下】

Rootkit是一種特殊的惡意軟體,它的功能是在安裝目標上隱藏自身及指定的檔案、程序和網路連線等資訊。

待分析資料集:
KDD-99資料集,連結:http://kdd.ics.uci.edu/databases/kddcup99/kddcup99.html
該資料集是從一個模擬的美國空軍區域網上採集來的9個星期的網路連線資料,分成具有標識的訓練資料和未加標識的測試資料。
資料集已經進行了資料採集、清洗、提取特徵、打標籤等動作。每一行包括41個特徵和1個標籤,總共42列。

根據書中,我們將第9列~第20列作為rootkit的關鍵特徵,描述如下:
第9列:hot:連續型別:訪問系統敏感檔案和目錄的次數;如訪問系統目錄、建立或執行程式等
第10列:num_failed_logins:連續型別:嘗試登陸失敗的次數
第11列:logged_in:離散型別:成功登陸則為1,否則則為0
第12列:num_compromised:連續型別:滿足被攻擊條件出現的次數(疑問,具體的被攻擊規則集合是什麼???)
第13列:root_shell:離散型別:獲得超級使用者許可權為1,否則為0
第14列:su_attempted:離散型別:出現su root命令則為1,否則為0
第15列:num_file_creations:連續型別:檔案建立的次數
第16列:num_shells:連續型別:使用shell命令的次數
第17列:num_access_file:連續型別:訪問被控制檔案的次數,如訪問/etc/passwd或者/etc/hosts檔案的訪問
第18列:num_outbound_cmds:連續型別:一個ftp會話中出站連線的次數
第19列:is_hot_login:離散型別:是否屬於hot登陸,即超級使用者或者管理員登陸

第20列:is_guest_login:離散型別:如果是guest登陸則為1,否則為0

程式碼如下:

#coding:utf-8
import os
import numpy as np 
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score

DATAPATH = os.path.normpath(os.path.dirname(os.path.abspath(__file__)) + "/data")

def parse_data():
    test_data = list()
    label_data = list()
    FULLPATH = DATAPATH + "/kddcup.data.corrected"
    with open(FULLPATH, "r") as f:
        for line in f.readlines():
            lines = line.split(",")
            test_data.append(lines[9:21])
            if lines[-1] == 'rootkit':
                label_data.append(1)
            else:
                label_data.append(0)

    return [test_data,label_data]

if __name__ == '__main__':
    test_data, label_data = parse_data()
    neigh = KNeighborsClassifier(n_neighbors = 3)
    scores = cross_val_score(neigh, test_data, label_data, cv=10)
    print scores
    print "precision:", np.mean(scores)*100

webshell就是以asp、php、jsp或者cgi等網頁檔案形式存在的一種命令執行環境,也可以將其稱做為一種網頁後門。黑客在入侵了一個網站後,通常會將asp或php後門檔案與網站伺服器WEB目錄下正常的網頁檔案混在一起,然後就可以使用瀏覽器來訪問asp或者php後門,得到一個命令執行環境,以達到控制網站伺服器的目的。

分析的資料集:https://www.unsw.adfa.edu.au/unsw-canberra-cyber/cybersecurity/ADFA-IDS-Datasets/
系統呼叫序列被廣泛認為是基於異常的系統在檢測入侵的時候的最準確的方式。ADFA資料集是澳大利亞國防學院(縮寫為ADFA)對外發布的一套主機級入侵檢測系統的資料集合,被廣泛應用於入侵檢測類產品的測試。資料集內已經將各類系統呼叫完成了特徵化,並針對攻擊型別進行了標註。該資料集包括Linux(ADFA-LD)和Windows(ADFA-WD)兩個OS平臺,分別記錄了各類系統呼叫次序。
資料裡每一個檔案,記錄了系統呼叫的序列,並且已經用數字標識了每一種系統呼叫。

演算法裡的特徵,是先把所有檔案裡的系統呼叫組成一個詞集,然後特徵就是用的每一個檔案裡的系統呼叫在詞集裡的分佈情況組成的向量空間。

程式碼如下:

#coding:utf-8
import os
import numpy as np 
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score

DATAPATH = os.path.normpath(os.path.dirname(os.path.abspath(__file__)) + "/data")

#生成詞集
def get_words():
    FULLPATH = DATAPATH + "/ADFA-LD/Attack_Data_Master"
    files = os.listdir(FULLPATH)
    words = set()
    for item in files:
        if item in ['.', '..']:
            continue
        CPATH = FULLPATH + "/" + item
        cfiles = os.listdir(CPATH)
        for citem in cfiles:
            if citem.endswith(".txt"):
                fullpath = FULLPATH + "/" + item + "/" + citem
                with open(fullpath, "r") as f:
                    for line in f.readlines():
                        lines = line.split()
                        for ccitem in lines:
                            words.add(ccitem)
    return list(words)

def parse_data(words):
    test_data = list()
    label_data = list()
    words_len = len(words)

    FULLPATH = DATAPATH + "/ADFA-LD/Attack_Data_Master"
    files = os.listdir(FULLPATH)

    for item in files:
        if item in ['.', '..']:
            continue
        CPATH = FULLPATH + "/" + item
        cfiles = os.listdir(CPATH)
        label = 0
        if item.startswith("Web_Shell"):
            label = 1
        for citem in cfiles:
            if citem.endswith(".txt"):
                fullpath = FULLPATH + "/" + item + "/" + citem
                with open(fullpath, "r") as f:
                    c_test_data = [0]*words_len
                    words_dict = dict()
                    for line in f.readlines():
                        lines = line.split()
                        for ccitem in lines:
                            if ccitem not in words_dict.keys():
                                words_dict[ccitem] = 1
                            else:
                                words_dict[ccitem] = words_dict[ccitem] + 1
                    for key in words_dict.keys():
                        for i in range(0, words_len):
                            if key == words[i]:
                                c_test_data[i] = words_dict[key]
                                break
                    test_data.append(c_test_data)
                    label_data.append(label)
    return [test_data,label_data]


if __name__ == '__main__':
    words = get_words()
    test_data, label_data = parse_data(words)
    
    neigh = KNeighborsClassifier(n_neighbors = 3)
    score = cross_val_score(neigh, test_data, label_data, cv=10)
    print score
    print "precision:",np.mean(score)*100

10輪交叉驗證效果如下: