[當人工智能遇上安全] 6.基于機器學習的入侵檢測和攻擊識別——以KDD CUP99數據集為例(人工智能的安全問題不容忽視)
隨著互聯網的繁榮,現階段的惡意代碼也呈現出快速發展的趨勢,主要表現為變種數量多、傳播速度快、影響范圍廣。在這樣的形勢下,傳統的惡意代碼檢測方法已經無法滿足人們對惡意代碼檢測的要求。比如基于簽名特征碼的惡意代碼檢測,這種方法收集已知的惡意代碼,以一種固定的方式生成特定的簽名,維護這樣的簽名庫,當有新的檢測任務時,通過在簽名庫中檢索匹配的方法進行檢測。暫且不說更新、維護簽名庫的過程需要耗費大量的人力物力,惡意代碼編寫者僅僅通過混淆、壓縮、加殼等簡單的變種方式便可繞過這樣的檢測機制。
為了應對上面的問題,基于機器學習的惡意代碼檢測方法一直是學界研究的熱點。由于機器學習算法可以挖掘輸入特征之間更深層次的聯系,更加充分地利用惡意代碼的信息,因此基于機器學習的惡意代碼檢測往往表現出較高的準確率,并且一定程度上可以對未知的惡意代碼實現自動化的分析。下面讓我們開始進行系統的介紹吧~
文章目錄
一.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代碼分享
六.總結
前文推薦(華為云):
[當人工智能遇上安全] 1.人工智能真的安全嗎?浙大團隊外灘大會分享AI對抗樣本技術
[當人工智能遇上安全] 2.清華張超老師 - GreyOne: Discover Vulnerabilities with Data Flow Sensitive Fuzzing
[當人工智能遇上安全] 3.安全領域中的機器學習及機器學習惡意請求識別案例分享
[當人工智能遇上安全] 4.基于機器學習的惡意代碼檢測技術詳解
[當人工智能遇上安全] 5.基于機器學習算法的主機惡意代碼識別研究
[當人工智能遇上安全] 6.基于機器學習的入侵檢測和攻擊識別——以KDD CUP99數據集為例
https://github.com/eastmountyxz/AI-Security-Paper
本文將分享機器學習在安全領域的應用,并復現一個基于機器學習的入侵檢測和攻擊識別。嚴格意義上來說,這篇文章是數據分析,它有幾個亮點:
(1) 詳細介紹了數據分析預處理中字符特征轉換為數值特征、數據標準化、數據歸一化,這都是非常基礎的工作。
(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,為基于計算智能的網絡入侵檢測研究奠定基礎。
二.數據特征描述
下載的數據集如下圖所示,這里以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種。’aol’, ‘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?- 連接正常或錯誤的狀態,離散類型,共11種。’OTH’, ‘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) 訓練集和測試集的類標不同,通過全局變量動態增加新類標,對未知類型的檢測是評價算法的重要指標。
#coding:utf-8 import numpy as np import pandas as pd import csv """ 功能:數據預處理 將KDD99數據集中字符型轉換為數值型 原文:https://blog.csdn.net/asialee_bird/article/details/80491256 強烈推薦博友們閱讀asialee_bird大神的文章及Github代碼,非常厲害的一位博主。 修訂:Eastmount 2019-11-22 """ #label_list為全局變量 global label_list #文件名 source_file='kddcup.data_10_percent_corrected' handled_file='kddcup.data_10_percent_corrected.csv' #文件寫入操作 data_file = open(handled_file,'w',newline='') #將相應的非數字類型轉換為數字標識即符號型數據轉化為數值型數據 def find_index(x,y): return [i for i in range(len(y)) if y[i]==x] #定義將源文件行中3種協議類型轉換成數字標識的函數 def handleProtocol(inputs): protocol_list=['tcp','udp','icmp'] if inputs[1] in protocol_list: return find_index(inputs[1], protocol_list)[0] #定義將源文件行中70種網絡服務類型轉換成數字標識的函數 def handleService(inputs): service_list=['aol','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'] if inputs[2] in service_list: return find_index(inputs[2],service_list)[0] #定義將源文件行中11種網絡連接狀態轉換成數字標識的函數 def handleFlag(inputs): flag_list=['OTH','REJ','RSTO','RSTOS0','RSTR','S0','S1','S2','S3','SF','SH'] if inputs[3] in flag_list: return find_index(inputs[3],flag_list)[0] #定義將源文件行中攻擊類型轉換成數字標識的函數(訓練集中共出現了22個攻擊類型,而剩下的17種只在測試集中出現) def handleLabel(inputs): label_list=['normal.', 'buffer_overflow.', 'loadmodule.', 'perl.', 'neptune.', 'smurf.', 'guess_passwd.', 'pod.', 'teardrop.', 'portsweep.', 'ipsweep.', 'land.', 'ftp_write.', 'back.', 'imap.', 'satan.', 'phf.', 'nmap.', 'multihop.', 'warezmaster.', 'warezclient.', 'spy.', 'rootkit.'] #在函數內部使用全局變量并修改它 global label_list if inputs[41] in label_list: return find_index(inputs[41],label_list)[0] else: label_list.append(inputs[41]) return find_index(inputs[41],label_list)[0] #主函數 if __name__=='__main__': #循環讀取文件數據 with open(source_file,'r') as data_source: csv_reader = csv.reader(data_source) csv_writer = csv.writer(data_file) count = 0 #行數 for row in csv_reader: temp_line=np.array(row) temp_line[1] = handleProtocol(row) #將源文件行中3種協議類型轉換成數字標識 temp_line[2] = handleService(row) #將源文件行中70種網絡服務類型轉換成數字標識 temp_line[3] = handleFlag(row) #將源文件行中11種網絡連接狀態轉換成數字標識 temp_line[41] = handleLabel(row) #將源文件行中23種攻擊類型轉換成數字標識 csv_writer.writerow(temp_line) count += 1 #輸出每行數據中所修改后的狀態 #print(count,'status:',temp_line[1],temp_line[2],temp_line[3],temp_line[41]) data_file.close()
處理后的結果如下圖所示:
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訓練
評價算法
降維可視化
# -*- coding: utf-8 -*- import os import csv import numpy as np import pandas as pd 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_percent_corrected.csv") lines = fr.readlines() line_nums = len(lines) print(line_nums) #創建line_nums行 para_num列的矩陣 x_mat = np.zeros((line_nums, 41)) y_label = [] #劃分數據集 for i in range(line_nums): line = lines[i].strip() item_mat = line.split(',') x_mat[i, :] = item_mat[0:41] #前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(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訓練----------------------------------------- clf = neighbors.KNeighborsClassifier() clf.fit(train_data, train_target) print clf result = clf.predict(test_data) print result print test_target #-----------------------------------------第四步 評價算法----------------------------------------- print sum(result==test_target) #預測結果與真實結果比對 print(metrics.classification_report(test_target, result)) #準確率 召回率 F值 #----------------------------------------第五步 降維可視化--------------------------------------- pca = PCA(n_components=2) newData = pca.fit_transform(test_data) plt.figure() plt.scatter(newData[:,0], newData[:,1], c=test_target, s=50) plt.show()
上面代碼非常簡單,其輸出結果如下圖所示。但也存在幾個缺點:
數據集 kddcup.data_10_percent_corrected.csv 隨機劃分為訓練集和測試集,而真實的是用某個數據集訓練,另一個數據集預測,并且測試集中存在未知的攻擊。
該代碼沒有考慮數據歸一化、數據標準化處理,而該數據集數值集中分布幾個值,這會影響最終實驗結果。
該實驗的評價應該計算ROC、AUC曲線,推薦這篇文章:機器學習分類算法常用評價指標
494021 (494021L, 41L) 494021 (296412L, 41L) (296412L,) (197609L, 41L) (197609L,) KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski', metric_params=None, n_jobs=None, n_neighbors=5, p=2, weights='uniform') [5 5 5 ... 5 4 5] [5 5 5 ... 5 4 5] 197299 precision recall f1-score support 0 1.00 1.00 1.00 38977 1 0.88 0.50 0.64 14 2 0.00 0.00 0.00 2 3 0.00 0.00 0.00 2 4 1.00 1.00 1.00 42797 5 1.00 1.00 1.00 112364 6 0.92 0.96 0.94 23 7 0.94 1.00 0.97 93 8 0.98 1.00 0.99 398 9 0.94 0.87 0.91 434 10 0.91 0.97 0.94 497 11 1.00 0.75 0.86 8 12 0.00 0.00 0.00 2 13 1.00 0.99 1.00 879 14 1.00 0.50 0.67 4 15 0.98 0.89 0.93 602 16 1.00 1.00 1.00 1 17 0.75 0.49 0.60 85 18 0.00 0.00 0.00 2 19 0.86 0.86 0.86 7 20 0.96 0.98 0.97 415 22 0.00 0.00 0.00 3 micro avg 1.00 1.00 1.00 197609 macro avg 0.73 0.67 0.69 197609 weighted avg 1.00 1.00 1.00 197609
數據高度重疊,所以接下來我們對KNN算法進行優化。
五.入侵檢測算法優化
1.數值標準化
數據標準化是機器學習、數據挖掘中常用的一種方法。
數據標準化主要是應對特征向量中數據很分散的情況,防止小數據被大數據(絕對值)吞并的情況。另外,數據標準化也有加速訓練,防止梯度爆炸的作用。下面是從李宏毅教授視頻中截下來的兩張圖,左圖表示未經過數據標準化處理的loss更新函數,右圖表示經過數據標準化后的loss更新圖。可見經過標準化后的數據更容易迭代到最優點,而且收斂更快。
在聚類\分類算法中,使用計算距離的方法對數據進行聚類\分類,而連接記錄的固定特征屬性中有兩種類型的數值——離散型和連續型。對于連續型特征屬性,各屬性的度量方法不一樣。一般而言,所用的度量單位越小,變量可能的值域就越大,這樣對聚類結果的影響也越大,即在計算數據間距離時對聚類的影響越大,甚至會出現“大數”吃“小數”的現象。
因此為了避免對度量單位選擇的依賴,消除由于屬性度量的差異對聚類\分類產生的影響,需要對屬性值進行標準化。對于離散型特征屬性本文中并不作標準化處理,而是放在聚類算法中計算距離時處理。所以數據標準化是針對連續型特征屬性的。
設訓練數據集有n條網絡連接記錄,每個記錄中有22個連續型屬性向量記作 Xij(1≤i≤n,11≤j≤41) 。對 Xij 數據預處理分為兩步:數值標準化和數值歸一化。
Z-score標準化:
基于數據均值和方差的標準化化方法。標準化后的數據是均值為0,方差為1的正態分布。這種方法要求原始數據的分布可以近似為高斯分布,否則效果會很差。標準化公式如下,
核心代碼為:
#Z-score normaliaztion def ZscoreNormalization(x): x = (x - np.mean(x)) / np.std(x) return x
針對該數據集,通過標注化處理連續型特征,具體公式如下:
其中,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 = 0 while i 標準化之前的數據顯示如下圖所示: 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]之間。轉換函數如下: 其中max為樣本數據的最大值,min為樣本數據的最小值。這種方法有個缺陷就是當有新數據加入時,可能導致max和min的變化,需要重新定義。min-max標準化python代碼如下: import numpy as np arr = 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 = 0 while i 輸出結果如下圖所示: 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 = 0 data_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 += 1 abnormal = data_set_size - normal max_dis = data_set[1].max() #歐式距離最大值 for j in range(1000): threshold = max_dis / 1000 * j normal1 = 0 abnormal1 = 0 for k in range(data_set_size): if data_set[1][k] > threshold and data_set[2][k] == 1: normal1 += 1 if data_set[1][k] > threshold and data_set[2][k] != 1: abnormal1 += 1 roc_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曲線: # coding=utf-8 from __future__ import division import numpy as np import matplotlib.pyplot as plt def classify(input_vct, data_set): data_set_size = data_set.shape[0] diff_mat = np.tile(input_vct, (data_set_size, 1)) - data_set #擴充input_vct到與data_set同型并相減 sq_diff_mat = diff_mat**2 #矩陣中每個元素都平方 distance = sq_diff_mat.sum(axis=1)**0.5 #每行相加求和并開平方根 return distance.min(axis=0) #返回最小距離 def file2mat(test_filename, para_num): """ 將表格存入矩陣,test_filename為表格路徑,para_num為存入矩陣的列數 返回目標矩陣,和矩陣每一行數據的類別 """ fr = open(test_filename) lines = fr.readlines() line_nums = len(lines) result_mat = np.zeros((line_nums, para_num)) #創建line_nums行 para_num列的矩陣 class_label = [] for i in range(line_nums): line = lines[i].strip() item_mat = line.split(',') result_mat[i, :] = item_mat[0: para_num] class_label.append(item_mat[-1]) #表格中最后一列正常1異常2的分類存入class_label fr.close() return result_mat, class_label def roc(data_set): normal = 0 data_set_size = data_set.shape[1] roc_rate = np.zeros((2, data_set_size)) for i in range(data_set_size): if data_set[2][i] == 1: normal += 1 abnormal = data_set_size - normal max_dis = data_set[1].max() for j in range(1000): threshold = max_dis / 1000 * j normal1 = 0 abnormal1 = 0 for k in range(data_set_size): if data_set[1][k] > threshold and data_set[2][k] == 1: normal1 += 1 if data_set[1][k] > threshold and data_set[2][k] == 2: abnormal1 += 1 roc_rate[0][j] = normal1 / normal #閾值以上正常點/全體正常的點 roc_rate[1][j] = abnormal1 / abnormal #閾值以上異常點/全體異常點 return roc_rate def test(training_filename, test_filename): training_mat, training_label = file2mat(training_filename, 32) test_mat, test_label = file2mat(test_filename, 32) test_size = test_mat.shape[0] result = np.zeros((test_size, 3)) for i in range(test_size): result[i] = i + 1, classify(test_mat[i], training_mat), test_label[i] # 序號 最小歐氏距離 測試集數據類別 result = np.transpose(result) #矩陣轉置 plt.figure(1) plt.scatter(result[0], result[1], c=result[2], edgecolors='None', s=1, alpha=1) # 圖1 散點圖:橫軸為序號,縱軸為最小歐氏距離,點中心顏色根據測試集數據類別而定, 點外圍無顏色,點大小為最小1,灰度為最大1 roc_rate = roc(result) plt.figure(2) plt.scatter(roc_rate[0], roc_rate[1], edgecolors='None', s=1, alpha=1) # 圖2 ROC曲線:橫軸誤報率,即閾值以上正常點/全體正常的點;縱軸檢測率,即閾值以上異常點/全體異常點 plt.show() if __name__ == "__main__": test('training.csv', 'test.csv') 六.總結 寫到這里,這篇基于機器學習的入侵檢測和攻擊識別分享完畢。嚴格意義上來說,這篇文章是數據分析,它有幾個亮點: (1) 詳細介紹了數據分析預處理中字符特征轉換為數值特征、數據標準化、數據歸一化,這都是非常基礎的工作。 (2) 結合入侵檢測應用KNN實現分類。 (3) 繪制散點圖采用序號、最小歐式距離、類標,ROC曲線繪制都是之前沒分享的。 這篇文章中也有幾個不足之處: (1) 最后的實驗效果非常不理想,但本文的整體思路是值得學習的,推薦各位從我的Github下載學習。 總之,希望基礎性文章對您有所幫助,如果文章中有錯誤或不足之處,還請提出和海涵,希望與您共同進步。天行健,君子以自強不息。地勢坤,君子以厚德載物。祝華為云越來越好~ 2022年加油,感恩能與大家在華為云遇見! 希望能與大家一起在華為云社區共同成長。原文地址:https://blog.csdn.net/Eastmount/article/details/120514813 (By:娜璋之家 Eastmount 2022-02-22 夜于貴陽) 該篇文章參考了以下文獻,非常推薦大家閱讀這些大牛的文章: [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小白 企業主機安全 機器學習 網絡
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。