本小节的内容虽然放到智能扫描器中,但是自动识别登录界面实际上是让通过让机器通过学习20News Groups Dataset数据样本,挖掘登录与注册页面常见关键字,如输入参数为password,即求与password接近的单词;而输入参数为email,即求与email相近的但此处。看到这里,相信非初学者应该已经了解本小节的本质是什么了,那就是通过Word2Vec来分析语义相似度。
一、自动登录
在研究如何使用机器自动识别注册和登录界面之前,我们先回顾一下人工是如何识别的。这里附作者给的示例图
以注册页面为例,常见的注册页面都会要求填写用户名、密码、邮箱等信息,并且一定会要求你重新输入密码进行确认。一个典型的注册页面如图12-9所示,会包含以下关键字:
Sign Up
Name
Email
Password
Password confirmation
同样,以登录页面为例,常见的登录页面都会要求填写用户名/邮箱、密码、验证码。
一个典型的登录页面如图12-10所示,会包含以下关键字:
Sign in
Email
Password
code
我们可以把机器识别注册和登录页面的过程简化成机器识别页面中包含指定关键字的过程。如何不依赖人工,而是依靠机器自动生成这些关键字呢?答案是Word2Vec。Word2Vec是Google在2013年开源的一款将词表征为实数值向量的高效工具,采用的模型有连续的词袋(Continuous Bag-Of-Words,CBOW)模型和Skip-Gram模型两种。
Word2Vec通过训练,可以把对文本内容的处理简化为K维向量空间中的向量运算,而向量空间上的相似度可以用来表示文本语义上的相似度。可以通过Word2Vec自动挖掘登录与注册页面常见关键字。关于Word2Vec的详细介绍请参考第7章相关内容。
我的理解这个应用其实可以很简单的描述,但是作者也是给了此应用在web安全中如何使用,所以说了这么多内容来描述自动登录这个问题。
二、数据集
本节的数据集使用大名鼎鼎的20News Groups Dataset。20News Groups Dataset包含20000个新闻报道,分别来自20个新闻组,它已经成为机器学习在文本分类和文本聚类领域非常流行的一个数据集。Scikit-Learn中默认包含了该数据集,可以很方便地使用:
newsgroups_train = fetch_20newsgroups(subset='train')
其中,可以通过指定categories访问不同领域的新闻
cats = ['alt.atheism', 'sci.space']
newsgroups_train = fetch_20newsgroups(subset='train', categories=cats)
三、数据清理
Word2Vec需要在语料库上进行训练,我们使用20News Groups Dataset。20News Groups Dataset包含大量的非字符符号,所以需要进行数据清洗,仅提取单词:
newsgroups_train = fetch_20newsgroups(subset='train')
sentences=[re.findall("[a-z\-]+",s.lower()) for s in newsgroups_train.data]
四、模型构建
作者在这里使用20News Groups Dataset提取全部单词,然后使用gensim进行Word2Vec训练,完整流程如图12-11所示
而源码部分处理是这样的
def get_login_pages(keywords):
from sklearn.datasets import fetch_20newsgroups
import gensim
import re
newsgroups_train = fetch_20newsgroups(subset='train')
sentences=[re.findall("[a-z]+",s.lower()) for s in newsgroups_train.data]
model = gensim.models.Word2Vec(sentences, size=200, window=5, min_count=1, workers=4)
results=model.most_similar(positive=[keywords], topn=10)
for i in results:
print (i)
五、运行结果
以password为例,调用如下
get_login_pages("password")
运行结果如下
[password] most_similar:
('username', 0.6823453903198242)
('login', 0.6291040182113647)
('nodis', 0.580697774887085)
('passwd', 0.565298318862915)
('alias', 0.5318878889083862)
('plaintext', 0.5194739103317261)
('trap-door', 0.51244056224823)
('authentication', 0.5074070692062378)
('passphrase', 0.5054489970207214)
('cipher', 0.5029815435409546)
六、改进函数
将输入变为字符串列表,这样可以一次性输出多个相似度,优化后代码如下
def get_login_pages(keywords):
from sklearn.datasets import fetch_20newsgroups
import gensim
import re
newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
newsgroups=[]
newsgroups.append(newsgroups_train.data)
newsgroups.append(newsgroups_test.data)
sentences=[re.findall("[a-z\-]+",s.lower()) for s in newsgroups_train.data]
model = gensim.models.Word2Vec(sentences, size=200, window=5, min_count=1, workers=4,iter=20)
for key in keywords:
print ("[%s] most_similar:" % key)
results=model.most_similar(positive=[key], topn=10)
for i in results:
print (i)
此时调用如下
get_login_pages(["user","password","email","name"])
运行结果如下所示
[user] most_similar:
results=model.most_similar(positive=[key], topn=10)
('interface', 0.5456673502922058)
('client', 0.5338382720947266)
('users', 0.5327937602996826)
('resource', 0.517593264579773)
('extension', 0.5087355971336365)
('application', 0.4957618713378906)
('builder', 0.4955199956893921)
('server', 0.492167592048645)
('toolkit', 0.48378533124923706)
('protocol', 0.47578126192092896)
[password] most_similar:
('username', 0.6823453903198242)
('login', 0.6291040182113647)
('nodis', 0.580697774887085)
('passwd', 0.565298318862915)
('alias', 0.5318878889083862)
('plaintext', 0.5194739103317261)
('trap-door', 0.51244056224823)
('authentication', 0.5074070692062378)
('passphrase', 0.5054489970207214)
('cipher', 0.5029815435409546)
[email] most_similar:
('e-mail', 0.8045320510864258)
('mail', 0.6995552778244019)
('compuserve', 0.5921804308891296)
('replies', 0.5792131423950195)
('reply', 0.5595848560333252)
('snail-mail', 0.5508401393890381)
('inquiries', 0.5456984043121338)
('wchutt', 0.5267196893692017)
('listserv', 0.5228370428085327)
('send', 0.5143170356750488)
[name] most_similar:
('printf', 0.41633301973342896)
('d-l', 0.40300360321998596)
('initials', 0.396043598651886)
('word', 0.3865213990211487)
('definition', 0.37389007210731506)
('names', 0.36851173639297485)
('parent', 0.36721381545066833)
('feyruzovich', 0.36647385358810425)
('address', 0.36511367559432983)
('title', 0.3628310263156891)
Process finished with exit code 0