[当人工智能遇上安全] 6.基于机器学习的入侵检测和攻击识别——以KDD CUP99数据集为例
您或許知道,作者后續分享網絡安全的文章會越來越少。但如果您想學習人工智能和安全結合的應用,您就有福利了,作者將重新打造一個《當人工智能遇上安全》系列博客,詳細介紹人工智能與安全相關的論文、實踐,并分享各種案例,涉及惡意代碼檢測、惡意請求識別、入侵檢測、對抗樣本等等。只想更好地幫助初學者,更加成體系的分享新知識。該系列文章會更加聚焦,更加學術,更加深入,也是作者的慢慢成長史。換專業確實挺難的,系統安全也是塊硬骨頭,但我也試試,看看自己未來四年究竟能將它學到什么程度,漫漫長征路,偏向虎山行。享受過程,一起加油~
首先,祝大家1024程序員節快樂,祝CSDN越來越好,感謝大家十年的陪伴。
隨著互聯網的繁榮,現階段的惡意代碼也呈現出快速發展的趨勢,主要表現為變種數量多、傳播速度快、影響范圍廣。在這樣的形勢下,傳統的惡意代碼檢測方法已經無法滿足人們對惡意代碼檢測的要求。比如基于簽名特征碼的惡意代碼檢測,這種方法收集已知的惡意代碼,以一種固定的方式生成特定的簽名,維護這樣的簽名庫,當有新的檢測任務時,通過在簽名庫中檢索匹配的方法進行檢測。暫且不說更新、維護簽名庫的過程需要耗費大量的人力物力,惡意代碼編寫者僅僅通過混淆、壓縮、加殼等簡單的變種方式便可繞過這樣的檢測機制。
為了應對上面的問題,基于機器學習的惡意代碼檢測方法一直是學界研究的熱點。由于機器學習算法可以挖掘輸入特征之間更深層次的聯系,更加充分地利用惡意代碼的信息,因此基于機器學習的惡意代碼檢測往往表現出較高的準確率,并且一定程度上可以對未知的惡意代碼實現自動化的分析。下面讓我們開始進行系統的介紹吧~
文章目錄
- 一.KDD CUP背景知識
- 二.數據特征描述
- 1.TCP連接基本特征(共9種,序號1~9)
- 2.TCP連接的內容特征(共13種,序號10~22)
- 3.基于時間的網絡流量統計特征 (共9種,序號23~31)
- 4.基于主機的網絡流量統計特征 (共10種,序號32~41)
- 5.樣本分析
- 三.Python數據處理
- 1.KDD 99數據集評價
- 2.字符型轉換為數值型
- 四.KNN實現入侵檢測
- 1.KNN
- 2.算法實現
- 五.入侵檢測算法優化
- 1.數值標準化
- 2.數值歸一化
- 3.KNN檢測及評估
- 4.Github代碼分享
- 六.總結
作者作為網絡安全的小白,分享一些自學基礎教程給大家,主要是在線筆記,希望您們喜歡。同時,更希望您能與我一起操作和進步,后續將深入學習AI安全和系統安全知識并分享相關實驗??傊?#xff0c;希望該系列文章對博友有所幫助,寫文不易,大神們不喜勿噴,謝謝!如果文章對您有幫助,將是我創作的最大動力,點贊、評論、私聊均可,一起加油喔!
前文推薦:
- [當人工智能遇上安全] 1.人工智能真的安全嗎?浙大團隊外灘大會分享AI對抗樣本技術
- [當人工智能遇上安全] 2.清華張超老師 - GreyOne: Discover Vulnerabilities with Data Flow Sensitive Fuzzing
- [當人工智能遇上安全] 3.安全領域中的機器學習及機器學習惡意請求識別案例分享
- [當人工智能遇上安全] 4.基于機器學習的惡意代碼檢測技術詳解
- [當人工智能遇上安全] 5.基于機器學習算法的主機惡意代碼識別研究
- [當人工智能遇上安全] 6.基于機器學習的入侵檢測和攻擊識別——以KDD CUP99數據集為例
作者的github資源:
- https://github.com/eastmountyxz/AI-Security-Paper
本文將分享機器學習在安全領域的應用,并復現一個基于機器學習的入侵檢測和攻擊識別。嚴格意義上來說,這篇文章是數據分析,它有幾個亮點:
- (1) 詳細介紹了數據分析預處理中字符特征轉換為數值特征、數據標準化、數據歸一化,這都是非?;A的工作。
- (2) 結合入侵檢測應用KNN實現分類。
- (3) 繪制散點圖采用序號、最小歐式距離、類標,ROC曲線繪制都是之前沒分享的。
文章中也有很多不足之處,惡意代碼或入侵檢測作者還會繼續深入,包括源代碼、二進制分析。作者作為網絡安全的小白,分享一些自學基礎教程給大家,希望你們喜歡。同時,更希望你能與我一起操作進步,爭取能入門,后續也將深入學習網絡安全和系統安全知識并分享相關實驗。總之,希望該系列文章對博友有所幫助,寫文不容易,大神請飄過,不喜勿噴,謝謝!
一.KDD CUP背景知識
KDD是數據挖掘與知識發現(Data Mining and Knowledge Discovery)的簡稱,”KDD CUP 99 dataset”是KDD競賽在1999年舉行時采用的數據集。從官網下載KDD99數據集,如下圖所示:
http://kdd.ics.uci.edu/databases/kddcup99/kddcup99.html
This is the data set used for The Third International Knowledge Discovery and Data Mining Tools Competition, which was held in conjunction with KDD-99 The Fifth International Conference on Knowledge Discovery and Data Mining. The competition task was to build a network intrusion detector, a predictive model capable of distinguishing between bad connections, called intrusions or attacks, and good normal connections. This database contains a standard set of data to be audited, which includes a wide variety of intrusions simulated in a military network environment.
KDD Cup 1999數據集: 是KDD知識發現和數據挖掘會議的比賽數據集,主要為軍事網絡環境中模擬的多種入侵,是入侵檢測應用的常用數據集,后續衍生出NSL-KDD。建議讀者結合論文和官網數據集進行分析:
- https://www.unb.ca/cic/datasets/nsl.html
數據文件包括:
kddcup.names 功能列表。 kddcup.data.gz 完整數據集(18M; 743M未壓縮) kddcup.data_10_percent.gz 10%的數據集(2.1M; 75M未壓縮) kddcup.newtestdata_10_percent_unlabeled.gz(1.4M; 45M未壓縮) kddcup.testdata.unlabeled.gz (11.2M; 430M未壓縮) kddcup.testdata.unlabeled_10_percent.gz (1.4M; 45M未壓縮) corrected.gz 正確標簽的測試數據 training_attack_types 入侵類型列表 typo-correction.txt 關于數據集中的簡要說明1998年美國國防部高級規劃署(DARPA)在MIT林肯實驗室進行了一項入侵檢測評估項目。林肯實驗室建立了模擬美國空軍局域網的一個網絡環境,收集了9周時間的TCPdump()網絡連接和系統審計數據,仿真各種用戶類型、各種不同的網絡流量和攻擊手段,使它就像一個真實的網絡環境。這些TCPdump采集的原始數據被分為兩個部分:7周時間的訓練數據,大概包含5,000,000多個網絡連接記錄,剩下的2周時間的測試數據大概包含2,000,000個網絡連接記錄。
4種異常類型分別是:
- DOS(denial-of-service)
拒絕服務攻擊,例如ping-of-death, syn flood, smurf等 - R2L(unauthorized access from a remote machine to a local machine)
來自遠程主機的未授權訪問,例如guessing password - U2R(unauthorized access to local superuser privileges by a local unpivileged user)
未授權的本地超級用戶特權訪問,例如buffer overflow attacks。 - PROBING(surveillance and probing)
端口監視或掃描,例如port-scan, ping-sweep等
隨后來自哥倫比亞大學的Sal Stolfo 教授和來自北卡羅萊納州立大學的 Wenke Lee 教授采用數據挖掘等技術對以上的數據集進行特征分析和數據預處理,形成了一個新的數據集。該數據集用于1999年舉行的KDD CUP競賽中,成為著名的KDD99數據集。雖然年代有些久遠,但KDD99數據集仍然是網絡入侵檢測領域的事實Benckmark,為基于計算智能的網絡入侵檢測研究奠定基礎。
數據分布如下圖所示(作者自己論文截圖):每個網絡連接被標記為正常(normal)或異常(attack),異常類型被細分為4大類共39種攻擊類型,其中22種攻擊類型出現在訓練集中,另有17種未知攻擊類型出現在測試集中。
二.數據特征描述
下載的數據集如下圖所示,這里以10%的數據集來進行實驗。
- kddcup.data_10_percent_corrected
- kddcup.testdata.unlabeled_10_percent
下面展現了其中3條記錄,總共有42項特征,最后一列是標記特征(Label),其他前41項特征共分為四大類。
- TCP連接基本特征(共9種,序號1~9)
- TCP連接的內容特征(共13種,序號10~22)
- 基于時間的網絡流量統計特征 (共9種,序號23~31)
- 基于主機的網絡流量統計特征 (共10種,序號32~41)
0,tcp,http,SF,239,486,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,8,8,0.00,0.00,0.00,0.00,1.00,0.00,0.00,19,19,1.00,0.00,0.05,0.00,0.00,0.00,0.00,0.00,normal.
0,icmp,ecr_i,SF,1032,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,511,511,0.00,0.00,0.00,0.00,1.00,0.00,0.00,255,255,1.00,0.00,1.00,0.00,0.00,0.00,0.00,0.00,smurf.
0,tcp,private,S0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,52,13,1.00,1.00,0.00,0.00,0.25,0.10,0.00,255,13,0.05,0.07,0.00,0.00,1.00,1.00,0.00,0.00,neptune.
數據集特征如下表所示:
接下來按順序解釋各個特征的具體含義,這是進行數據分析之前非常必要的一個環節。
1.TCP連接基本特征(共9種,序號1~9)
基本連接特征包含了一些連接的基本屬性,如連續時間,協議類型,傳送的字節數等。
- (1) duration - 連接持續時間,以秒為單位,連續類型。范圍是 [0, 58329] 。它的定義是從TCP連接以3次握手建立算起,到FIN/ACK連接結束為止的時間;若為UDP協議類型,則將每個UDP數據包作為一條連接。數據集中出現大量的duration = 0 的情況,是因為該條連接的持續時間不足1秒。
- (2) protocol_type - 協議類型,離散類型,共有3種:TCP, UDP, ICMP。
- (3) service - 目標主機的網絡服務類型,離散類型,共有70種?!痑ol’, ‘auth’, ‘bgp’, ‘courier’, ‘csnet_ns’, ‘ctf’, ‘daytime’, ‘discard’, ‘domain’, ‘domain_u’, ‘echo’, ‘eco_i’, ‘ecr_i’, ‘efs’, ‘exec’, ‘finger’, ‘ftp’, ‘ftp_data’, ‘gopher’, ‘harvest’, ‘hostnames’, ‘http’, ‘http_2784′, ‘http_443′, ‘http_8001′, ‘imap4′, ‘IRC’, ‘iso_tsap’, ‘klogin’, ‘kshell’, ‘ldap’, ‘link’, ‘login’, ‘mtp’, ‘name’, ‘netbios_dgm’, ‘netbios_ns’, ‘netbios_ssn’, ‘netstat’, ‘nnsp’, ‘nntp’, ‘ntp_u’, ‘other’, ‘pm_dump’, ‘pop_2′, ‘pop_3′, ‘printer’, ‘private’, ‘red_i’, ‘remote_job’, ‘rje’, ‘shell’, ‘smtp’, ‘sql_net’, ‘ssh’, ‘sunrpc’, ‘supdup’, ‘systat’, ‘telnet’, ‘tftp_u’, ‘tim_i’, ‘time’, ‘urh_i’, ‘urp_i’, ‘uucp’, ‘uucp_path’, ‘vmnet’, ‘whois’, ‘X11′, ‘Z39_50′。
- (4) flag - 連接正?;蝈e誤的狀態,離散類型,共11種?!疧TH’, ‘REJ’, ‘RSTO’, ‘RSTOS0′, ‘RSTR’, ‘S0′, ‘S1′, ‘S2′, ‘S3′, ‘SF’, ‘SH’。它表示該連接是否按照協議要求開始或完成。例如SF表示連接正常建立并終止;S0表示只接到了SYN請求數據包,而沒有后面的SYN/ACK。其中SF表示正常,其他10種都是error。
- (5) src_bytes - 從源主機到目標主機的數據的字節數,連續類型,范圍是 [0, 1379963888]。
- (6) dst_bytes - 從目標主機到源主機的數據的字節數,連續類型,范圍是 [0. 1309937401]。
- (7) land - 若連接來自/送達同一個主機/端口則為1,否則為0,離散類型,0或1。
- (8) wrong_fragment - 錯誤分段的數量,連續類型,范圍是 [0, 3]。
- (9) urgent - 加急包的個數,連續類型,范圍是[0, 14]。
2.TCP連接的內容特征(共13種,序號10~22)
第二部分特征是TCP連接的內容特征,共13種。對于U2R和R2L之類的攻擊,由于它們不像DoS攻擊那樣在數據記錄中具有頻繁序列模式,而一般都是嵌入在數據包的數據負載里面,單一的數據包和正常連接沒有什么區別。為了檢測這類攻擊,Wenke Lee等從數據內容里面抽取了部分可能反映入侵行為的內容特征,如登錄失敗的次數等。
- (10) hot - 訪問系統敏感文件和目錄的次數,連續,范圍是 [0, 101]。例如訪問系統目錄,建立或執行程序等。
- (11) num_failed_logins - 登錄嘗試失敗的次數。連續,[0, 5]。
- (12) logged_in - 成功登錄則為1,否則為0,離散,0或1。
- (13) num_compromised - compromised條件出現的次數,連續,[0, 7479]。
- (14) root_shell - 若獲得root shell 則為1,否則為0,離散,0或1。root_shell是指獲得超級用戶權限。
- (15) su_attempted - 若出現”su root” 命令則為1,否則為0,離散,0或1。
- (16) num_root - root用戶訪問次數,連續,[0, 7468]。
- (17) num_file_creations - 文件創建操作的次數,連續,[0, 100]。
- (18) num_shells - 使用shell命令的次數,連續,[0, 5]。
- (19) num_access_files - 訪問控制文件的次數,連續,[0, 9]。例如對 /etc/passwd 或 .rhosts 文件的訪問。
- (20) num_outbound_cmds - 一個FTP會話中出站連接的次數,連續,0。數據集中這一特征出現次數為0。
- (21) is_hot_login - 登錄是否屬于“hot”列表,是為1,否則為0,離散,0或1。例如超級用戶或管理員登錄。
- (22) is_guest_login - 若是guest 登錄則為1,否則為0,離散,0或1。
3.基于時間的網絡流量統計特征 (共9種,序號23~31)
第三類特征是基于時間的網絡流量統計特征。包括相同目標主機和相同服務。
由于網絡攻擊事件在時間上有很強的關聯性,因此統計出當前連接記錄與之前一段時間內的連接記錄之間存在的某些聯系,可以更好的反映連接之間的關系。這類特征又分為兩種集合:
- 一個是 “same host”特征,只觀察在過去兩秒內與當前連接有 相同目標主機 的連接,例如相同的連接數,在這些相同連接與當前連接有相同的服務的連接等等;
- 另一個是 “same service”特征,只觀察過去兩秒內與當前連接有 相同服務 的連接,例如這樣的連接有多少個,其中有多少出現SYN錯誤或者REJ錯誤。
具體翻譯內容如下:
- (23) count - 過去兩秒內,與當前連接具有相同的目標主機的連接數,連續,[0, 511]。
- (24) srv_count - 過去兩秒內,與當前連接具有相同服務的連接數,連續,[0, 511]。
- (25) serror_rate - 過去兩秒內,在與當前連接具有相同目標主機的連接中,出現“SYN” 錯誤的連接的百分比,連續,[0.00, 1.00]。
- (26) srv_serror_rate - 過去兩秒內,在與當前連接具有相同服務的連接中,出現“SYN” 錯誤的連接的百分比,連續,[0.00, 1.00]。
- (27) rerror_rate - 過去兩秒內,在與當前連接具有相同目標主機的連接中,出現“REJ” 錯誤的連接的百分比,連續,[0.00, 1.00]。
- (28) srv_rerror_rate - 過去兩秒內,在與當前連接具有相同服務的連接中,出現“REJ” 錯誤的連接的百分比,連續,[0.00, 1.00]。
- (29) same_srv_rate - 過去兩秒內,在與當前連接具有相同目標主機的連接中,與當前連接具有相同服務的連接的百分比,連續,[0.00, 1.00]。
- (30) diff_srv_rate - 過去兩秒內,在與當前連接具有相同目標主機的連接中,與當前連接具有不同服務的連接的百分比,連續,[0.00, 1.00]。
- (31) srv_diff_host_rate - 過去兩秒內,在與當前連接具有相同服務的連接中,與當前連接具有不同目標主機的連接的百分比,連續,[0.00, 1.00]。
注意:這一大類特征中,23、25、27、29、30這5個特征是 “same host” 特征,前提都是與當前連接具有相同目標主機的連接;24、26、28、31這4個特征是 “same service” 特征,前提都是與當前連接具有相同服務的連接。
4.基于主機的網絡流量統計特征 (共10種,序號32~41)
基于時間的流量統計只是在過去兩秒的范圍內統計與當前連接之間的關系,而在實際入侵中,有些 Probing攻擊使用慢速攻擊模式來掃描主機或端口,當它們掃描的頻率大于2秒的時候,基于時間的統計方法就無法從數據中找到關聯。所以Wenke Lee等按照目標主機進行分類,使用一個具有100個連接的時間窗,統計當前連接之前100個連接記錄中與當前連接具有 相同目標主機 的統計信息。
- (32) dst_host_count - 前100個連接中,與當前連接具有相同目標主機的連接數,連續,[0, 255]。
- (33) dst_host_srv_count - 前100個連接中,與當前連接具有相同目標主機相同服務的連接數,連續,[0, 255]。
- (34) dst_host_same_srv_rate - 前100個連接中,與當前連接具有相同目標主機相同服務的連接所占的百分比,連續,[0.00, 1.00]。
- (35) dst_host_diff_srv_rate - 前100個連接中,與當前連接具有相同目標主機不同服務的連接所占的百分比,連續,[0.00, 1.00]。
- (36) dst_host_same_src_port_rate - 前100個連接中,與當前連接具有相同目標主機相同源端口的連接所占的百分比,連續,[0.00, 1.00]。
- (37) dst_host_srv_diff_host_rate - 前100個連接中,與當前連接具有相同目標主機相同服務的連接中,與當前連接具有不同源主機的連接所占的百分比,連續,[0.00, 1.00]。
- (38) dst_host_serror_rate - 前100個連接中,與當前連接具有相同目標主機的連接中,出現SYN錯誤的連接所占的百分比,連續,[0.00, 1.00]。
- (39) dst_host_srv_serror_rate - 前100個連接中,與當前連接具有相同目標主機相同服務的連接中,出現SYN錯誤的連接所占的百分比,連續,[0.00, 1.00]。
- (40) dst_host_rerror_rate - 前100個連接中,與當前連接具有相同目標主機的連接中,出現REJ錯誤的連接所占的百分比,連續,[0.00, 1.00]。
- (41) dst_host_srv_rerror_rate - 前100個連接中,與當前連接具有相同目標主機相同服務的連接中,出現REJ錯誤的連接所占的百分比,連續,[0.00, 1.00]。
5.樣本分析
KDD99數據集總共由500萬條記錄構成,它還提供一個10%的訓練子集和測試子集,它的樣本類別分布如下:
- NORMAL:正常訪問,訓練集(10%)有97278個樣本,測試集(Corrected)有60593個樣本。
- PROBE: 端口監視或掃描,訓練集(10%)有4107個樣本,測試集(Corrected)有4166個樣本。攻擊包括: ipsweep、 mscan、nmap、portsweep、saint、satan。
- DOS:拒絕服務攻擊,訓練集(10%)有391458個樣本,測試集(Corrected)有229853個樣本。攻擊包括: apache2、back、land、mailbomb、neptune、pod、processtable、smurf、teardrop、udpstorm。
- U2R:未授權的本地超級用戶特權訪問,訓練集(10%)有52個樣本,測試集(Corrected)有228個樣本。攻擊包括:buffer_overflow、httptunnel、loadmodule、perl、ps、rootkit、sqlattack、 xterm。
- R2L:來自遠程主機的未授權訪問,訓練集(10%)有1126個樣本,測試集(Corrected)有16189個樣本。攻擊包括:ftp_write、guess_passwd、imap、multihop、named、phf、sendmail、snmpgetattack、snmpguess、spy、warezclient、warezmaster、worm、xlock、xsnoop。
具體的數據描述如下:
三.Python數據處理
1.KDD 99數據集評價
入侵檢測
入侵檢測的方法從根本上講就是設計一個分類器,能將數據流中的正常與異常數據區分出來,從而實現對攻擊行為的報警。本文KDD99數據集的目的就是為入侵檢測系統提供統一的性能評價基準,常用來在學術圈檢驗入侵檢測算法的好壞。本文將數據集中的10%訓練集來訓練分類器,然后用corrected測試集測試分類器性能,這個分類器可以是基于貝葉斯的、決策樹的、神經網絡的或者是支持向量機的。
特征選擇
特征選擇是KDD99數據集的另一個主要應用。KDD99數據集中,每個連接有41個特征,對于一個分類器來說,要從這么多特征中提取規則是費時且不精確的,這體現在一些無關或冗余的特征往往會降低分類器模型的檢測精度和速度。而且對于從原始的tcpdump數據中提取特征這一過程,也將是困難和費時的,這對于在線入侵檢測系統是致命的。因此去除冗余特征或不重要特征,對于提高分類器訓練速度和檢測精度來說,是必要的。要說明的是對于不同的分類器來說,最優的特征子集可以是不同的。
數據集評價
KDD 99數據集是入侵檢測領域的Benchmark(基準),為基于計算智能的網絡入侵檢測研究奠定了基礎,從那以后很多學者開始研究入侵檢測算法,當然不能不提到眾所周知的“功夫網”,實際上它就是一個大規模的入侵檢測系統。KDD99從1999年創建已經過去多年,當年的實驗條件和攻擊手段放到今天早已過時,而且從原來的網絡層攻擊進化為針對應用層的攻擊,例如跨站腳本、數據庫注入等等(當然,針對應用層攻擊自有新的解決方案)。你可以說,要解決這個問題,重新做一遍98年那個實驗,用新的設備新的攻擊手段,產生新的數據集不就行了嗎?事實是據我所知還沒有學術組織公開新的且質量較高的數據集,安全軟件公司里肯定有足夠的數據庫,當然,人家是不會共享出來的,就靠這個賺錢。另一個解決辦法是你自己搭建網絡環境,自己做實驗,就是累點,當然可行。
所以,希望這篇基礎性文章對您有所幫助。
2.字符型轉換為數值型
在數據挖掘的過程中,數據的預處理一直都是非常重要的一個環節,只有把數據轉化為分類器認可的形式才可以對其進行訓練。下面這段代碼參考CSDN asialee_bird大神的文章及Github代碼,非常厲害的一位博主,推薦大家閱讀他的文章(https://blog.csdn.net/asialee_bird)。
個人認為這段代碼最大的亮點是:
(1) 有效地將數據集中字符型轉換為數值型,這是數據集預處理常見的方法。
(2) 訓練集和測試集的類標不同,通過全局變量動態增加新類標,對未知類型的檢測是評價算法的重要指標。
處理后的結果如下圖所示:
0,2,12,9,520,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,457,457,0.00,0.00,0.00,0.00,1.00,0.00,0.00,255,255,1.00,0.00,1.00,0.00,0.00,0.00,0.00,0.00,5
0,0,21,9,428,7512,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,7,18,0.00,0.00,0.00,0.00,1.00,0.00,0.11,255,255,1.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0
四.KNN實現入侵檢測
這里通過KNN算法實現一個最簡單的入侵檢測。
1.KNN
K最近鄰(K-Nearest Neighbor,簡稱KNN)分類算法是數據挖掘分類技術中最簡單常用的方法之一。所謂K最近鄰,就是尋找K個最近的鄰居的意思,每個樣本都可以用它最接近的K個鄰居來代表。本小節主要講解KNN分類算法的基礎知識及分析實例。
KNN分類算法是最近鄰算法,字面意思就是尋找最近鄰居,由Cover和Hart在1968年提出,簡單直觀易于實現。下面通過一個經典的例子來講解如何尋找鄰居,選取多少個鄰居。下圖是非常經典的KNN案例,需要判斷右邊這個動物是鴨子、雞還是鵝?它涉及到了KNN算法的核心思想,判斷與這個樣本點相似的類別,再預測其所屬類別。由于它走路和叫聲像一只鴨子,所以右邊的動物很可能是一只鴨子。
所以,KNN分類算法的核心思想是從訓練樣本中尋找所有訓練樣本X中與測試樣本距離(歐氏距離)最近的前K個樣本(作為相似度),再選擇與待分類樣本距離最小的K個樣本作為X的K個最鄰近,并檢測這K個樣本大部分屬于哪一類樣本,則認為這個測試樣本類別屬于這一類樣本。假設現在需要判斷下圖中的圓形圖案屬于三角形還是正方形類別,采用KNN算法分析如下:
1.當K=3時,圖中第一個圈包含了三個圖形,其中三角形2個,正方形一個,該圓的則分類結果為三角形。
2.當K=5時,第二個圈中包含了5個圖形,三角形2個,正方形3個,則以3:2的投票結果預測圓為正方形類標。
總之,設置不同的K值,可能預測得到不同的結果。
KNeighborsClassifier可以設置3種算法:brute、kd_tree、ball_tree,設置K值參數為n_neighbors=3。
調用方法如下:
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=3, algorithm=“ball_tree”)
它也包括兩個方法:
- 訓練:nbrs.fit(data, target)
- 預測:pre = clf.predict(data)
2.算法實現
接下來開始進行KNN算法分類分析,其中KNN核心算法主要步驟包括五步:
- 加載數據集
- 劃分數據集
- KNN訓練
- 評價算法
- 降維可視化
上面代碼非常簡單,其輸出結果如下圖所示。但也存在幾個缺點:
- 數據集 kddcup.data_10_percent_corrected.csv 隨機劃分為訓練集和測試集,而真實的是用某個數據集訓練,另一個數據集預測,并且測試集中存在未知的攻擊。
- 該代碼沒有考慮數據歸一化、數據標準化處理,而該數據集數值集中分布幾個值,這會影響最終實驗結果。
- 該實驗的評價應該計算ROC、AUC曲線,推薦這篇文章:機器學習分類算法常用評價指標
數據高度重疊,所以接下來我們對KNN算法進行優化。
五.入侵檢測算法優化
1.數值標準化
數據標準化是機器學習、數據挖掘中常用的一種方法。
數據標準化主要是應對特征向量中數據很分散的情況,防止小數據被大數據(絕對值)吞并的情況。另外,數據標準化也有加速訓練,防止梯度爆炸的作用。下面是從李宏毅教授視頻中截下來的兩張圖,左圖表示未經過數據標準化處理的loss更新函數,右圖表示經過數據標準化后的loss更新圖。可見經過標準化后的數據更容易迭代到最優點,而且收斂更快。
在聚類\分類算法中,使用計算距離的方法對數據進行聚類\分類,而連接記錄的固定特征屬性中有兩種類型的數值——離散型和連續型。對于連續型特征屬性,各屬性的度量方法不一樣。一般而言,所用的度量單位越小,變量可能的值域就越大,這樣對聚類結果的影響也越大,即在計算數據間距離時對聚類的影響越大,甚至會出現“大數”吃“小數”的現象。
因此為了避免對度量單位選擇的依賴,消除由于屬性度量的差異對聚類\分類產生的影響,需要對屬性值進行標準化。對于離散型特征屬性本文中并不作標準化處理,而是放在聚類算法中計算距離時處理。所以數據標準化是針對連續型特征屬性的。
設訓練數據集有n條網絡連接記錄,每個記錄中有22個連續型屬性向量記作 Xij(1≤i≤n,11≤j≤41) 。對 Xij 數據預處理分為兩步:數值標準化和數值歸一化。
Z-score標準化:
基于數據均值和方差的標準化化方法。標準化后的數據是均值為0,方差為1的正態分布。這種方法要求原始數據的分布可以近似為高斯分布,否則效果會很差。標準化公式如下,
x′=x?meanstdx' = \frac{x-mean}{std} x′=stdx?mean?
核心代碼為:
#Z-score normaliaztion def ZscoreNormalization(x):x = (x - np.mean(x)) / np.std(x)return x針對該數據集,通過標注化處理連續型特征,具體公式如下:
xij′=xij?AVGjSTDjx'_{ij} = \frac{x_{ij}-AVG_j}{STD_j} xij′?=STDj?xij??AVGj??
AVGi=1n(X1j+X2j+...+Xnj)AVG_i = \frac{1}{n}(X_{1j}+X_{2j}+...+X_{nj}) AVGi?=n1?(X1j?+X2j?+...+Xnj?)
STDi=1n(∣X1j?AVGj∣+∣X2j?AVGj∣+...+∣Xnj?AVGj∣)STD_i = \frac{1}{n}(|X_{1j}-AVG_j|+|X_{2j}-AVG_j|+...+|X_{nj}-AVG_j|) STDi?=n1?(∣X1j??AVGj?∣+∣X2j??AVGj?∣+...+∣Xnj??AVGj?∣)
其中,AVG為平均值,STAD為平均絕對偏差,如果AVG等于0,則X’=0;如果STD等于0,則X’=0。
核心代碼如下所示,這里建議讀者直接使用我的數據集或測試數據集測試,否則花費巨大時間。
注意:將np.mean和np.std以及后面的np.max、np.min計算提出來賦值變量,否則會非常耗時。之前速度慢的原因就是這個細節沒有注意,大家寫代碼一定要避免不必要的運算,尤其是多層循環計算過程中,盡量寫優美的代碼!
#coding:utf-8 import numpy as np import pandas as pd import csv#全局變量 global x_mat#數據標準化 def ZscoreNormalization(x, n):meanValue = np.mean(x)stdValue = np.std(x)print(len(x))i = 0while i<len(x):x_mat[i][n] = (x[i] - meanValue) / stdValueif x_mat[i][n]>0:print(x_mat[i][n])i = i + 1print("The ", n , "feature is normal.")#-------------------------------------讀取文件劃分數據集----------------------------------------- fr = open("test-normal.csv") data_file = open("test-normal-result.csv",'wb+',newline='') lines = fr.readlines() line_nums = len(lines) print(line_nums)#創建line_nums行 para_num列的矩陣 x_mat = np.zeros((line_nums, 42))#劃分數據集 for i in range(line_nums):line = lines[i].strip()item_mat = line.split(',')x_mat[i, :] = item_mat[0:42] #獲取42個特征 fr.close() print(x_mat.shape)#--------------------------------獲取某列特征并依次標準化并賦值----------------------------- print(len(x_mat[:, 0])) #獲取某列數據 494021 print(len(x_mat[0, :])) #獲取某行數據 42#標準化處理 ZscoreNormalization(x_mat[:, 0], 0) #duration ZscoreNormalization(x_mat[:, 4], 4) #src_bytes ZscoreNormalization(x_mat[:, 5], 5) #dst_bytes ZscoreNormalization(x_mat[:, 7], 7) #wrong_fragment ZscoreNormalization(x_mat[:, 8], 8) #urgentZscoreNormalization(x_mat[:, 9], 9) #hot ZscoreNormalization(x_mat[:, 10], 10) #num_failed_logins ZscoreNormalization(x_mat[:, 12], 12) #num_compromised ZscoreNormalization(x_mat[:, 14], 14) #su_attempte ZscoreNormalization(x_mat[:, 15], 15) #num_root ZscoreNormalization(x_mat[:, 16], 16) #num_file_creations ZscoreNormalization(x_mat[:, 17], 17) #num_shells ZscoreNormalization(x_mat[:, 18], 18) #num_access_files ZscoreNormalization(x_mat[:, 19], 19) #num_outbound_cmdsZscoreNormalization(x_mat[:, 22], 22) #count ZscoreNormalization(x_mat[:, 23], 23) #srv_count ZscoreNormalization(x_mat[:, 24], 24) #serror_rate ZscoreNormalization(x_mat[:, 25], 25) #srv_serror_rate ZscoreNormalization(x_mat[:, 26], 26) #rerror_rate ZscoreNormalization(x_mat[:, 27], 27) #srv_rerror_rate ZscoreNormalization(x_mat[:, 28], 28) #same_srv_rate ZscoreNormalization(x_mat[:, 29], 29) #diff_srv_rate ZscoreNormalization(x_mat[:, 30], 30) #srv_diff_host_rateZscoreNormalization(x_mat[:, 31], 31) #dst_host_count ZscoreNormalization(x_mat[:, 32], 32) #dst_host_srv_count ZscoreNormalization(x_mat[:, 33], 33) #dst_host_same_srv_rate ZscoreNormalization(x_mat[:, 34], 34) #dst_host_diff_srv_rate ZscoreNormalization(x_mat[:, 35], 35) #dst_host_same_src_port_rate ZscoreNormalization(x_mat[:, 36], 36) #dst_host_srv_diff_host_rate ZscoreNormalization(x_mat[:, 37], 37) #dst_host_serror_rate ZscoreNormalization(x_mat[:, 38], 38) #dst_host_srv_serror_rate ZscoreNormalization(x_mat[:, 39], 39) #dst_host_rerror_rate ZscoreNormalization(x_mat[:, 40], 40) #dst_host_srv_rerror_rate#文件寫入操作 csv_writer = csv.writer(data_file) i = 0 while i<len(x_mat[:, 0]):csv_writer.writerow(x_mat[i, :])i = i + 1 data_file.close()標準化之前的數據顯示如下圖所示:
0,1,47,9,105,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0.00,0.00,0.00,0.00,1.00,0.00,0.00,255,254,1.00,0.01,0.00,0.00,0.00,0.00,0.00,0.00,0
經常處理后的數據如下所示:
-0.024411893497851576,1.0,47.0,9.0,-0.030455897580918892,-0.030455897580918892,0.0,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,0.0,-0.030455897580918892,0.0,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,0.0,0.0,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,-0.030455897580918892,0
2.數值歸一化
數據標準化(歸一化)處理是數據挖掘的一項基礎工作,不同評價指標往往具有不同的量綱和量綱單位,這樣的情況會影響到數據分析的結果,為了消除指標之間的量綱影響,需要進行數據標準化處理,以解決數據指標之間的可比性。原始數據經過數據標準化處理后,各指標處于同一數量級,適合進行綜合對比評價。以下是常用的歸一化方法:
min-max標準化(Min-Max Normalization)
也稱為離差標準化,是對原始數據的線性變換,使結果值映射到[0 , 1]之間。轉換函數如下:
x′=x?minmax?minx' = \frac{x-min}{max-min} x′=max?minx?min?
其中max為樣本數據的最大值,min為樣本數據的最小值。這種方法有個缺陷就是當有新數據加入時,可能導致max和min的變化,需要重新定義。min-max標準化python代碼如下:
import numpy as nparr = np.asarray([0, 10, 50, 80, 100]) for x in arr:x = float(x - np.min(arr))/(np.max(arr)- np.min(arr))print x # output # 0.0 # 0.1 # 0.5 # 0.8 # 1.0歸一化核心代碼如下所示:
#coding:utf-8 import numpy as np import pandas as pd import csv#全局變量 global x_mat#數據歸一化 def MinmaxNormalization(x, n):minValue = np.min(x)maxValue = np.max(x)print(minValue, maxValue)print(len(x))i = 0while i<len(x):x_mat[i][n] = (x[i] - minValue) / (maxValue - minValue)#if x_mat[i][n]>0:# print(x_mat[i][n])i = i + 1print("The ", n , "feature is normal.")#-------------------------------------讀取文件劃分數據集----------------------------------------- fr = open("test-normal-result.csv") data_file = open("test-normal-result-minmax.csv",'wb+',newline='') lines = fr.readlines() line_nums = len(lines) print(line_nums)#創建line_nums行 para_num列的矩陣 x_mat = np.zeros((line_nums, 42))#劃分數據集 for i in range(line_nums):line = lines[i].strip()item_mat = line.split(',')x_mat[i, :] = item_mat[0:42] #獲取42個特征 fr.close() print(x_mat.shape)#--------------------------------獲取某列特征并依次標準化并賦值----------------------------- print(len(x_mat[:, 0])) #獲取某列數據 494021 print(len(x_mat[0, :])) #獲取某行數據 42#歸一化處理 MinmaxNormalization(x_mat[:, 0], 0) #duration MinmaxNormalization(x_mat[:, 4], 4) #src_bytes MinmaxNormalization(x_mat[:, 5], 5) #dst_bytes MinmaxNormalization(x_mat[:, 7], 7) #wrong_fragment MinmaxNormalization(x_mat[:, 8], 8) #urgentMinmaxNormalization(x_mat[:, 9], 9) #hot MinmaxNormalization(x_mat[:, 10], 10) #num_failed_logins MinmaxNormalization(x_mat[:, 12], 12) #num_compromised MinmaxNormalization(x_mat[:, 14], 14) #su_attempte MinmaxNormalization(x_mat[:, 15], 15) #num_root MinmaxNormalization(x_mat[:, 16], 16) #num_file_creations MinmaxNormalization(x_mat[:, 17], 17) #num_shells MinmaxNormalization(x_mat[:, 18], 18) #num_access_files MinmaxNormalization(x_mat[:, 19], 19) #num_outbound_cmdsMinmaxNormalization(x_mat[:, 22], 22) #count MinmaxNormalization(x_mat[:, 23], 23) #srv_count MinmaxNormalization(x_mat[:, 24], 24) #serror_rate MinmaxNormalization(x_mat[:, 25], 25) #srv_serror_rate MinmaxNormalization(x_mat[:, 26], 26) #rerror_rate MinmaxNormalization(x_mat[:, 27], 27) #srv_rerror_rate MinmaxNormalization(x_mat[:, 28], 28) #same_srv_rate MinmaxNormalization(x_mat[:, 29], 29) #diff_srv_rate MinmaxNormalization(x_mat[:, 30], 30) #srv_diff_host_rateMinmaxNormalization(x_mat[:, 31], 31) #dst_host_count MinmaxNormalization(x_mat[:, 32], 32) #dst_host_srv_count MinmaxNormalization(x_mat[:, 33], 33) #dst_host_same_srv_rate MinmaxNormalization(x_mat[:, 34], 34) #dst_host_diff_srv_rate MinmaxNormalization(x_mat[:, 35], 35) #dst_host_same_src_port_rate MinmaxNormalization(x_mat[:, 36], 36) #dst_host_srv_diff_host_rate MinmaxNormalization(x_mat[:, 37], 37) #dst_host_serror_rate MinmaxNormalization(x_mat[:, 38], 38) #dst_host_srv_serror_rate MinmaxNormalization(x_mat[:, 39], 39) #dst_host_rerror_rate MinmaxNormalization(x_mat[:, 40], 40) #dst_host_srv_rerror_rate#文件寫入操作 csv_writer = csv.writer(data_file) i = 0 while i<len(x_mat[:, 0]):csv_writer.writerow(x_mat[i, :])i = i + 1 data_file.close()輸出結果如下圖所示:
5.1346198410647435e-05,1.0,47.0,9.0,5.1346198410647435e-05,5.1346198410647435e-05,0.0,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,0.0,5.1346198410647435e-05,0.0,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,0.0,0.0,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,5.1346198410647435e-05,0
3.KNN檢測及評估
最后代碼如下所示,主要包括以下功能:
- 針對上面標準化和歸一化處理后的數據集,進行KNN算法分類
- 采用歐式距離計算,并繪制散點分布圖(序列號、最小歐式距離、類標)
- ROC曲線評估
但實驗效果非常不理想,不知道什么具體原因,哎,心累~博友們使用的時候幫忙檢測下前面的標準化和歸一化代碼是否正確。
# -*- coding: utf-8 -*- import os import csv import numpy as np from sklearn.svm import SVC from sklearn import metrics import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap from sklearn.model_selection import train_test_split from sklearn.decomposition import PCA from sklearn import neighbors#-----------------------------------------第一步 加載數據集----------------------------------------- fr= open("kddcup.data_10_yxz-result-minmax.csv") lines = fr.readlines() line_nums = len(lines) print(line_nums)#創建line_nums行 para_num列的矩陣 x_mat = np.zeros((line_nums, 31)) y_label = []#劃分數據集 for i in range(line_nums):line = lines[i].strip()item_mat = line.split(',')x_mat[i, :] = item_mat[0:31] #前41個特征y_label.append(item_mat[-1]) #類標 fr.close() print(x_mat.shape) print(len(y_label))#-----------------------------------------第二步 劃分數據集----------------------------------------- y = [] for n in y_label: y.append(int(float(n))) y = np.array(y, dtype = int) #list轉換數組#劃分數據集 測試集40% train_data, test_data, train_target, test_target = train_test_split(x_mat, y, test_size=0.4, random_state=42) print(train_data.shape, train_target.shape) print(test_data.shape, test_target.shape)#-----------------------------------------第三步 KNN訓練----------------------------------------- def classify(input_vct, data_set):data_set_size = data_set.shape[0]#擴充input_vct到與data_set同型并相減diff_mat = np.tile(input_vct, (data_set_size, 1)) - data_set sq_diff_mat = diff_mat**2 #矩陣中每個元素都平方distance = sq_diff_mat.sum(axis=1)**0.5 #每行相加求和并開平方根return distance.min(axis=0) #返回最小距離test_size = len(test_target) result = np.zeros((test_size, 3)) for i in range(test_size):#序號 最小歐氏距離 測試集數據類別result[i] = i + 1, classify(test_data[i], train_data), test_target[i] #矩陣轉置 result = np.transpose(result) #-----------------------------------------第四步 評價及可視化----------------------------------------- def roc(data_set):normal = 0data_set_size = data_set.shape[1]roc_rate = np.zeros((2, data_set_size)) #輸出ROC曲線 二維矩陣#計算正常請求數量for i in range(data_set_size):if data_set[2][i] == 1:normal += 1abnormal = data_set_size - normalmax_dis = data_set[1].max() #歐式距離最大值for j in range(1000):threshold = max_dis / 1000 * jnormal1 = 0abnormal1 = 0for k in range(data_set_size):if data_set[1][k] > threshold and data_set[2][k] == 1:normal1 += 1if data_set[1][k] > threshold and data_set[2][k] != 1:abnormal1 += 1roc_rate[0][j] = normal1 / normal # 閾值以上正常點/全體正常的點roc_rate[1][j] = abnormal1 / abnormal # 閾值以上異常點/全體異常點return roc_rate#圖1 散點圖 #橫軸為序號 縱軸為最小歐氏距離 #點中心顏色根據測試集數據類別而定 點外圍無顏色 點大小為最小1 灰度為最大1 plt.figure(1) plt.scatter(result[0], result[1], c=result[2], edgecolors='None', s=2, alpha=1)#圖2 ROC曲線 #橫軸誤報率:即閾值以上正常點/全體正常的點 #縱軸檢測率:即閾值以上異常點/全體異常點 roc_rate = roc(result) plt.figure(2) plt.scatter(roc_rate[0], roc_rate[1], edgecolors='None', s=1, alpha=1) plt.show()4.Github代碼分享
最后提供Github的代碼,希望對讀者有所幫助,參考龔炎大神的文章和代碼。
https://blog.gongyan.me/2017/04/kdd-cup99/
https://github.com/gongyanc/kddcup99
運行結果如下圖所示,本篇文章所有資源參考我的Github。
橫坐標序號,縱坐標最小歐式距離,散點顏色類標(正常、攻擊)。
ROC曲線:
六.總結
寫到這里,這篇基于機器學習的入侵檢測和攻擊識別分享完畢。嚴格意義上來說,這篇文章是數據分析,它有幾個亮點:
- (1) 詳細介紹了數據分析預處理中字符特征轉換為數值特征、數據標準化、數據歸一化,這都是非?;A的工作。
- (2) 結合入侵檢測應用KNN實現分類。
- (3) 繪制散點圖采用序號、最小歐式距離、類標,ROC曲線繪制都是之前沒分享的。
- (4) 惡意代碼或入侵檢測,后續作者還會深入,包括源代碼、二進制分析。
這篇文章中也有幾個不足之處:
- (1) 最后的實驗效果非常不理想,但本文的整體思路是值得學習的,推薦各位從我的Github下載學習。
- (2) 后續作者嘗試結合深度學習、圖像識別來進行惡意代碼分析。
- (3) 作者剛剛學習安全領域,還非常菜,還有太多要學習的知識,但會一直努力的。
總之,希望基礎性文章對您有所幫助,如果文章中有錯誤或不足之處,還請提出和海涵,希望與您共同進步。天行健,君子以自強不息。地勢坤,君子以厚德載物。祝大家1024程序員節快樂,祝CSDN越來越好。
(By:Eastmount 2021-10-24 周末寫于武大 早上11點 http://blog.csdn.net/eastmount/ )
該篇文章參考了以下文獻,非常推薦大家閱讀這些大牛的文章:
- [1] 機器學習在安全攻防場景的應用與分析 - 騰訊云FreeBuf官方
- [2] 用機器學習玩轉惡意URL檢測 - 騰訊云FreeBuf官方
- [3] https://github.com/exp-db/AI-Driven-WAF
- [4] https://github.com/eastmountyxz
- [5] 張思思, 左信, 劉建偉. 深度學習中的對抗樣本問題[J]. 計算機學報,2019(8).
- [6] KDD CUP 99數據集
- [7] KDD CUP99數據集預處理(Python實現) CSDN Asia-Lee大神
- [8] The 1998 Lincoln Laboratory IDS Evaluation A Critique. by John McHugh
- [9] Testing Intrusion Detection Systems: A Critique of the 1998 and 1999 DARPA Intrusion Detection System Evaluations as Performed by Lincoln Laboratory. by John McHugh
- [10] The Comparison of IP Networks. by ST Brugger
- [11] KDD Cup ’99 dataset (Network Intrusion) considered harmful. by ST Brugger
- [12] https://github.com/gongyanc/kddcup99
- [13] https://blog.gongyan.me/2017/04/kdd-cup99/
- [14] Python3實現常用數據標準化方法 - z小白
總結
以上是生活随笔為你收集整理的[当人工智能遇上安全] 6.基于机器学习的入侵检测和攻击识别——以KDD CUP99数据集为例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Python图像识别] 四十六.图像预
- 下一篇: [论文阅读] (11)ACE算法和暗通道