原文:Machine Learning based Password Strength Classification
地址:http://web.archive.org/web/20170606022743/http://fsecurify.com/machine-learning-based-password-strength-checking/
近期,我想做一些機遇機器學習和網絡安全的項目。這是另一個與信息安全和機器學習有關的項目。
各公司的密碼強度檢測都不近相同。但所有的這些檢測都是基於規則的。一個密碼在Google這邊可能是強密碼但在Dropbox就變成了弱密碼。我在想我們能否讓機器學習算法來決定一個密碼是弱密碼還是強密碼。於是,這個帖子誕生了。讓我們開始吧。
數據收集此次分析所使用的密碼數據來自於000webhost洩漏,此數據可在網上下載。那麼我們是如何決定哪些密碼是高強度的哪些密碼是低強度的呢?Well,Georgia Tech university開發了一款名叫PARS的工具,這款工具集成了各大公司所使用的密碼強度檢測規則。這些文件有兩行數據,密碼和強度。
我在此使用的密碼強度檢測算法來自於Twitter,微軟和暴雪。這個算法與其他檢測儀有什麼區別呢?首先,它是純粹基於機器學習而不是密碼規則的。其次,我只保留了那些三種檢測儀都認為強度是弱、中等、強的密碼。這意味著所有用來訓練的密碼的強度都確實是弱、中等、強的。
下面是一些用來訓練模型的密碼樣本:
0 for weak, 1 for medium and 2 for strong
lamborghin1,1
AVYq1lDE4MgAZfNt,2
u6c8vhow,1
v1118714,1
universe2908,1
as326159,1
asv5o9yu,1
intel1,0
612035180tok,1
jytifok873,1
WUt9IZzE0OQ7PkNE,2
lsdlsd1,0
我原本有300萬條密碼數據,但是過濾出滿足三個密碼強度檢測儀後只剩下70萬條密碼數據了,我將這些數據分為了80%的訓練集和20%的測試集。其中過濾掉了許多數據是因為我只用了那些被三個分類算法都認為是相同強度的密碼。
數據分析我將使用Tf-idf分數而不是整條密碼,我將使用每個字符作為一個token。其他我沒用到的指標有密碼長度,特殊字符的數量,包含數字的數量等。這是一個自定義的令牌解析器(tokenizer)。
def getTokens(inputString):
tokens = []
for i in inputString:
tokens.append(i)
return tokens
加載數據。
filepath = 'your_file_path_containing_passwords_and_labels'
data = pd.read_csv(filepath,',',error_bad_lines=False)
data = pd.DataFrame(data)
passwords = np.array(data)
現在打亂數據集,然後獲取y和X向量。
random.shuffle(passwords)
y = [d[1] for d in passwords]
allpasswords= [d[0] for d in passwords]
現在在我們的密碼語料庫(corpus)上使用Tfidvectorizer分割數據。
vectorizer = TfidfVectorizer(tokenizer=getTokens)
X = vectorizer.fit_transform(allpasswords)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)
That's it. 現在我們需要做的就是應用機器學習算法然後我門就擁有了一個基於機器學習的密碼強度檢測器。開工!由於我想讓算法運行更快一些,在此我使用了多分類的邏輯回歸算法。
lgs = LogisticRegression(penalty='l2',multi_class='ovr')
lgs.fit(X_train, y_train)
print(lgs.score(X_test, y_test))
我們的準確率(accuracy)大概有81%,這可能是由於我們沒有使用大量的數據。這代表80%的情況下,我們算法能夠將密碼正確分類(與三個商業的密碼檢測器分類結果相同)。讓我們來看看這個算法是如何將我們的密碼分類的。
X_predict = ['faizanahmad','faizanahmad123','faizanahmad##','ajd1348#28t**','ffffffffff','kuiqwasdi','uiquiuiiuiuiuiuiuiuiuiuiui','mynameisfaizan','mynameis123faizan#','faizan','123456','abcdef']
X_predict = vectorizer.transform(X_predict)
y_Predict = lgs.predict(X_predict)
print y_Predict
來看看結果。
faizanahmad [medium]
faizanahmad123 [medium]
faizanahmad
ajd1348
ffffffffff [easy]
kuiqwasdi [medium]
uiquiuiiuiuiuiuiuiuiuiuiui [easy]
mynameis123faizan
faizan [easy]
abcdef [easy]
看起來我們的算法知道字母、數字和特殊符號的組合是一個好的密碼。很好,結果看起來很好,不是嗎?
有一些需要注意的地方,由於此模型是從已經存在的檢測算法中的規則訓練的,但我組合了三種不同的檢測方法來使他更可靠(robust)。它不只是基於算法模仿了一個規則。它綜合了廣泛使用的許多密碼強度檢查算法。
這個項目是我在閒暇時間做的,它肯定是不完全的。這只是實現我心中的一個想法,然後分享與你們大家。我相信這個項目可以進一步擴展為更強大,更有意義的密碼檢測器/分類器。
代碼和數據可以在此找到:
https://github.com/faizann24/Machine-Learning-based-Password-Strength-Classification