黑客在攻擊過程中或者對目標網(wǎng)絡(luò)實施控制時經(jīng)常使用域名。我們在做流量分析時不僅要通過流量的指紋特征識別威脅,也可以通過檢測是否解析了惡意域名來判斷網(wǎng)絡(luò)中是否存在肉雞。
不直接用威脅情報的原因
公司購買了一批威脅情報數(shù)據(jù),其中一項重要的數(shù)據(jù)就是就是惡意域名列表。
因此可以在客戶流量里面導(dǎo)出DNS解析日志,去跟威脅情報的惡意域名情報直接匹配來找出惡意外鏈。但威脅情報往往有以下的缺陷:
誤報多。威脅情報誤報較多。從我手上的這份數(shù)據(jù)來看,不少正規(guī)中小網(wǎng)站、過期的域名、甚至Alexa排名一千以內(nèi)的都被列為惡意域名。猜測有可能是網(wǎng)站被掛過黑頁,或者論壇上被傳過帶毒附件,導(dǎo)致整個域名被列入黑名單。而后期維護沒有跟上,導(dǎo)致沒有及時刪除誤報信息。
漏報更多。從威脅情報的性質(zhì)上來看,越是大范圍/長時間的攻擊的行為、大面積傳播的病毒,越容易被威脅情報所捕獲。反之,針對性的APT特征攻擊則不容易被收錄,造成漏報。而我們公司的客戶主要是政企類,信息更為敏感,更容易被境外黑客盯上并發(fā)起針對性攻擊。
不可控。我允許安全系統(tǒng)的誤報和漏報,這畢竟是不可避免的,但我無法接受的是誤報和漏報的不可控。可控的安全系統(tǒng)你知道什么條件下會產(chǎn)生誤報,所以你可以用其它策略去降低誤報;你會知道什么樣的攻擊會被系統(tǒng)遺漏掉,所以可以用其它的安全方案來彌補這部分缺失。而威脅情報雖然內(nèi)容可讀,但采集過程就是個“黑盒子”,你不知道里面的數(shù)據(jù)是怎么來的,告警出來的東西也不知道如何降低誤報,更不知道它會遺漏哪些信息。
因此我決定用這批威脅情報作為AI訓(xùn)練集,學(xué)習(xí)威脅情報背后的數(shù)據(jù)特征,通過AI強大的泛化能力,可以減少漏報,并讓安全系統(tǒng)變得可控。
選擇AI維度
選擇維度是很重要一項工作,你做的是人工智能還是人工智障,是神經(jīng)網(wǎng)絡(luò)還是神經(jīng)病網(wǎng)絡(luò),很大程度上取決于選擇的維度。
Alexa排名
一般情況下,惡意域名不會是流量非常高的網(wǎng)站域名。因此抓取Alexa排名作為維度。
通過接口抓取Alexa排名,如果域名沒有Alexa排名數(shù)據(jù),則認為它的排名非常靠后,設(shè)置一個非常大的數(shù)值:99999999。
如果是多級域名的話,除了抓取多級域名的Alexa,還要抓取主域名的Alexa。這樣便共享了兩個維度。
搜狗rank
搜狗rank和Alexa排名一樣,反應(yīng)的是網(wǎng)站的規(guī)模和流量的大小。不同的是Alexa是越小站越大,搜狗rank是值越大站越大。對于沒有搜狗rank的站點,認為rank為0。
搜狗與百度的收錄數(shù)量
一般情況下,惡意域名要多低調(diào)就有多低調(diào),不會專門去做SEO的,也不會希望搜索引擎搜到到。
通過某個SEO接口爬取百度和搜狗收錄頁面的數(shù)量,對于搜不到的域名,認為收錄數(shù)量為0。
必應(yīng)收錄數(shù)量
與“百度和搜狗收錄數(shù)量”形成互補,因為必應(yīng)對于境外域名收錄的更全一些,而百度搜狗對國內(nèi)收錄的更好一些。本來想用Google的,但是Google太頻繁的抓取會有驗證碼,沒必要把精力花費在破解驗證碼上面。
必應(yīng)的收錄數(shù)量并沒有查詢接口,因此直接用site:domain.com的方式直接抓取收錄數(shù)量,相比SEO查詢接口,這樣直接抓取也更準確一些。
網(wǎng)站首頁完整度
很多域名會解析到web服務(wù)器,一般情況下,正規(guī)域名解析到正常的網(wǎng)站,而惡意域名的解析ip要么沒有web服務(wù),要么是沒有內(nèi)容的首頁。例如404頁面、Apache默認頁面、空白頁面等等。
那么怎么判斷首頁是不是正常的、完整的呢。最好的方法就是用head less瀏覽器(如phantomjs)去訪問,檢查首頁(包括多媒體資源)的大小,以及媒體資源是否成功加載。這是后續(xù)可以優(yōu)化的一個點。
奈何懶癌晚期,我用了一個取巧的辦法,直接判斷首頁各個媒體標簽的數(shù)量。精心設(shè)計的首頁肯定有img link script等標簽,滿足的越多,完整度level遍越高。如下圖所示,取level值作為完整度。如果沒開放web服務(wù),則level為0。
圖1 通過標簽給網(wǎng)頁完整度評分
是否是主流域名后綴
一般情況下,普通域名大多數(shù)常用.com、.net.、.cn等主流后綴,而惡意域名往往會喜歡注冊小國家域名,如.io、.ru等。
Cn域名一般都要求實名備案,惡意域名很少有cn域名。
地理位置
國內(nèi)對主機審查比較嚴,除了被黑的肉雞,很少有專門申請國內(nèi)主機用于黑客行為的。
另外公司客戶主要是政府國企類,向境外的反連本來就是可疑行為,因此把域名的地理位置作為一個維度。
A記錄與CNAME
正規(guī)公司如果有注冊企業(yè)郵箱的,企業(yè)域名一般都會注冊A記錄和CNAME。而惡意域名可能只會注冊A記錄。
如果一個域名既沒有A也沒有CNAME,維度值為0。
待加入維度
WHOIS匿名:惡意域名的whois信息一般都選擇匿名,因此whois信息是否匿名應(yīng)當作為一個判斷維度。在實際測試過程中,發(fā)現(xiàn)很多匿名域名的注冊人、聯(lián)系方式等字段,不是為空,而是nameserver或者域名注冊商的聯(lián)系方式,因此要建立一個域名商匿名信息的黑名單來判斷是否匿名。維護成本有些高,在第一個版本中暫不加入該維度。
域名更新的頻繁程度:使用域名的ttl值或者歷史解析記錄。一般認為惡意域名的解析更換的比較頻繁。做壞事嘛,總是喜歡打一槍換一個地方。
是否使用CDN:檢測域名是否使用了CDN。CDN一般用于流量比較大的站點進行加速,木馬或shell的C&C域名一般是不會用的。
清洗數(shù)據(jù)
本文定義的惡意域名為黑客實施攻擊時用的域名,包括但不限于:木馬回連、病毒通訊、反彈shell、SSRF、XSS、DDoS、掛馬、礦機、DNS隧道木馬等等。總之都是黑客攻擊所用。
威脅情報里的域名中有不少我們不需要的,這些信息要人工剔除。例如博彩網(wǎng)站、色情站、垃圾郵件域名。用AI也可以識別:抓取網(wǎng)站內(nèi)容后直接上樸素貝葉斯,或者走NLP情感分析的套路即可,這不在本文的討論范圍內(nèi)。還有釣魚站也要剔除,識別釣魚站是另一個話題了。由于擔心誤報影響樣本質(zhì)量,只取置信度較高的那部分域名。
惡意域名作為正樣本,正常域名作為負樣本,正負樣本比例大約為1:1。
取威脅情報中9月10日的全量惡意域名作為訓(xùn)練集,另取9月11-17日的增量部分作為測試集。
圖2 整理后的惡意域名樣本
建立模型
筆者訓(xùn)練了兩種模型,一個是機器學(xué)習(xí)的代表算法支持向量機SVM,另一個是卷積神經(jīng)網(wǎng)絡(luò)CNN。最后通過多方面對比絕對線上業(yè)務(wù)使用哪個。
支持向量機
在神經(jīng)網(wǎng)絡(luò)沒火之前,SVM是應(yīng)用最廣泛的機器學(xué)習(xí)算法之一,對于線性可分的樣本集識別率很高,那也就注定了本次我們用SVM的效果不會差。
#載入訓(xùn)練集數(shù)據(jù)
x_data, y_label = data.load_tran_data()
#數(shù)據(jù)歸一化。由于有些維度值特別高,如百度收錄量和Alexa值,有些維度則特別低,只有1或者0。因此等比縮小是不可取的,否則收斂特別慢。這里將數(shù)據(jù)縮小至方差為1均值0的數(shù)組
x_data = preprocessing.scale(x_data)
svc = svm.SVC()
parameters = [
{
'C': [0.5, 0.8, 0.9, 1, 1.1, 1.2,1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 3, 5, 7, 9, 11, 13, 15, 17, 19, 30, 50],
'gamma': [0.1, 0.5, 0.6, 0.7, 0.8,0.9, 1, 1.2, 1.3, 1.5, 2, 2.5, 3, 4, 5, 6, 7, 8, 9, 10, 11],
'kernel': ['rbf']
},
{
'C': [0.5, 0.8, 0.9, 1, 2, 3, 4,4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 5, 5.5, 6, 7, 9, 11, 13, 15, 17, 19, 30, 50],
'kernel': ['linear']
}
]
# 使用rbf和linear兩種核函數(shù)進行對比,同時使用“爆破”的方式尋找最優(yōu)參數(shù)組合
clf = GridSearchCV(svc, parameters, cv=5,n_jobs=8)
clf.fit(x_data,y_label)
# 打印最優(yōu)參數(shù)組合
print(clf.best_params_)
best_model= clf.best_estimator_
joblib.dump(best_model,"svm2.2.m")
最終確定的最優(yōu)參數(shù)組合是核函數(shù)linear和C參數(shù)4.2,證明樣本是線性可分的。
在測試集上進行測試,結(jié)果準確率97.2% 、召回率97.3%,翻譯成我們熟悉的指標,誤報率為2.8%、漏報率都為2.7%。
卷積神經(jīng)網(wǎng)絡(luò)
卷積神經(jīng)網(wǎng)絡(luò)CNN可以說憑一己之力掀起了近幾年AI熱潮。CNN的特點是強調(diào)顯細節(jié)的特征,大家熟悉的是CNN在圖像方面的應(yīng)用,其實一維的文本、二維的圖像、三維的空間、四維的宇宙、五維度的量子態(tài)……都可以卷,頗有“大餅卷一切”的趨勢,連三體人的智子都望塵莫及。
好吧,今天有點喝多了。吹牛x的習(xí)慣又犯了。
總之,理論上CNN可以擬合任意函數(shù),自然包括線性函數(shù)了。
x_data, y_label = data.load_test_data() #載入訓(xùn)練集并歸一化
x_data = preprocessing.scale(x_data)
x_data = np.expand_dims(x_data, axis=2)
dim = len(x_data[0])
y_len = len(y_label)
model = Sequential()
# 輸入層、卷基層
model.add(Conv1D(4, 3, input_shape=(dim, 1), padding='same', activation='relu', use_bias=True))
# BN算法,使輸出信號規(guī)范為“均值0,方差1”,目的是加速收斂
model.add(BatchNormalization())
# 最大池化層
model.add(MaxPooling1D(3))
# 放棄層,防止過擬合
model.add(Dropout(0.5))
# 再來一次卷積,經(jīng)過BN算法規(guī)范化后,進行平均池化
model.add(Conv1D(8, 3, padding='same', activation='relu'))
model.add(BatchNormalization())
model.add(GlobalAveragePooling1D())
model.add(Dropout(0.5))
# 兩層全連接
model.add(Dense(4, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
# 訓(xùn)練模型
model.compile(loss='binary_crossentropy',
optimizer='sgd',
metrics=['accuracy'])
model.fit(x_data, y_label, batch_size=20, epochs=600)
model.save("cnn1.22.h5")
該模型在測試集上準確率為97.5%,召回率96.7%。
線上應(yīng)用
SVM和CNN模型對比數(shù)據(jù)如下:
模型名稱
準確率
召回率
SVM
97.2% (誤報率2.8%)
97.3% (漏報率2.7%)
CNN
97.5% (誤報率2.5%)
96.7% (漏報率3.3%)
兩種模型相對而言,SVM誤報略高漏報低,而CNN誤報低漏報高。整體而言兩個模型指標相近,SVM略好于CNN,最終線上決定使用SVM作為檢測算法。
SVM的2.8%的誤報率反映在出口流量上有點多,需要配合其他策略如黑白名單降低誤報。后來在實際線上應(yīng)用中,發(fā)現(xiàn)誤報的一部分來自于程序所用的API的域名,這類域名在訓(xùn)練集中沒有包含。修正過程本文不再贅述。
|