自动化Web渗透Payload提取技术(2)

一个Web访问记录的成分是比较固定的,每个部分(方法、路径、参数、HTTP头、Cookie等)都有比较好的结构化特点。因此可以把Web攻击识别任务抽象为文本分类任务,而且这种思路应用在了安全领域,如有监督的攻击识别[1]、 XSS识别[2] 等。文本分类任务中常用的向量化手段有词袋模型(Bag of Word,BOW)、TF-IDF模型、词向量化(word2vec)等,兜哥的文章[3]已经做了详细的讲解。

经过对Web日志特点的分析,本文认为使用TF-IDF来对样本进行向量化效果更好。一是经过标准化后请求参数的值仍会有非常多的可能性,这种情况下词袋模型生成的特征向量长度会非常大,而且没法收缩;二是每个请求中参数个数有大有小,绝大多数不超过10个,这个时候词向量能表达的信息非常有限,并不能反映出参数value的异常性;三是TF-IDF可以表达出不同请求同一参数的值是否更有特异性,尤其是IDF项。

举个例子, ?ipAddr=8.8.8.8 是一个查询IP详细信息的页面(真实存在),在某一段时间内收到了10000个请求,其中9990个请求中ipAddr参数值是符合xx.xx.xx.xx这个IP的格式的,通过0×2中提到的标准化之后,也就是9990个请求的ipAddr参数为n+.n+.n+.n+ (当然这里做了简化,数字不一定为多位)。此外有10个请求的ipAddr是形如alert('XSS')、'or '1' = '1之类的不同的攻击Payload。

经过TF-IDF向量化后,那9900个请求ipAddr=n+.n+.n+.n+这一项的TF-IDF值:

TF-IDF normal = TF * IDF = 1 * log(10000/(9990+1)) = 0.001

而出现ipAddr=alert('XSS')的请求的TF-IDF值:

TF-IDF abnormal = TF * IDF = 1 * log(10000/(1+1)) = 8.517

可以看出异常请求参数value的TF-IDF是远大于正常请求的,因此TF-IDF可以很好地反映出参数value的异常程度。

熟悉TF-IDF的同学一定有疑问了,你这TF-IDF的字典也会很大呀,如果样本量很大而且有各式各样的参数value,你的特征向量岂不是稀疏得不行了?对于这个问题,我有一个解决方案,也就是将所有的TF-IDF进一步加以处理,对参数key相同的TF-IDF项进行求和。设参数key集合为K={k1, k2, …, kn},TF-IDF字典为集合x={x1, x2, …, xm}。则每个参数key的特征值为:

vn = ∑TF-IDFxn   xn∈{x | x startswith ‘kn=’}

具体代码在vectorize/vectorizer.py中:

    for path, strs in path_buckets.items():         if not strs:             continue         vectorizer = TfidfVectorizer(analyzer='word', token_pattern=r"(?u)\b\S\S+\b")         try:             tfidf = vectorizer.fit_transform(strs)             #putting same key's indices together             paramindex = {}             for kv, index in vectorizer.vocabulary.items():                 k = kv.split('=')[0]                 if k in param_index.keys():                     param_index[k].append(index)                 else:                     param_index[k] = [index]             #shrinking tfidf vectors             tfidf_vectors = []             for vector in tfidf.toarray():                 v = []                 for param, index in param_index.items():                     v.append(np.sum(vector[index]))                 tfidf_vectors.append(v)             #other features             other_vectors = []             for str in strs:                 ov = []                 kvs = str.split(' ')[:-1]                 lengths = np.array(list(map(lambda x: len(x), kvs)))                 #param count                 ov.append(len(kvs))                 #mean kv length                 ov.append(np.mean(lengths))                 #max kv length                 ov.append(np.max(lengths))                 #min kv length                 ov.append(np.min(lengths))                 #kv length std                 ov.append(np.std(lengths))                 other_vectors.append(ov)             tfidf_vectors = np.array(tfidf_vectors)             other_vectors = np.array(other_vectors)             vectors = np.concatenate((tfidf_vectors, other_vectors), axis=1)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/64f0d605e09440d8cad668ef12921d47.html