胡哥给的任务是精简他给的扫描器字典。
我的思路是这样子的:
1.从一大堆文件中筛选出是扫描器构造的URL
2.对这些筛选出来的URL进行统计排序,和胡哥给的字典对比,留下吻合度高的字典。
3.从第三方web应用中获取URL作为字典的一部分,毕竟现在很多用户都在用第三方的web应用如织梦CMS,wordpress,一旦扫描起来,准确度特别高。
问题1:.如果胡哥给的文件的信息过少,导致筛选出来的字典吻合度都很低,那就坑爹了。(已解决)
这个问题问题好,不过肉眼目测有6w个数据,应该不会出现字典信息过少的情况。
问题2: 要怎么确定这个URL是扫描器而不是用户正常访问呢?(已解决)
这个思路有如下几点:
1)关键字如fuck,sql,webshell(当然还要很多)通通视为扫描器在扫描,因为正常用户都不会访问这些链接,记录这些IP,然后获取IP所访问的所有URL。
2)统计文件中请求IP的TOP10(根据需要可以设定这个TOP n),如果是则把这些IP所扫过的URL加入到字典中,毕竟正常用户的访问不可能特别频繁。
3)把扫描后台等敏感目录的IP视为恶意IP,并且把这个IP所扫过的URL记录为字典,如果这个IP是正常用户,那么他的访问必定数量很少,字典这点冗余可以接受,
如果这个IP是扫描器,那么我们就收集它的字典并加到我们的字典中。
问题3:如果扫描器也是个冗余字典,那怎么办?达不到我要精简字典的目的啊!(这个问题无法解决)
胡哥说,这个问题姑且留着。我个人认为这已经晁超出了自动化的范围了。
=======================================================================
读取keyword.txt,放到keywords[]中
线程1
判断文件Top n文件是否存在,若存在则停止线程
跑出Top 10 IP
线程 2
判断文件Top n文件是否存在,若不存在则等线程1完成wait()
读取in.txt 放到 TopN[]中
while Not EOF
如果匹配到TopN中的数据,则命中,加入到out.txt中
线程 3
读取in.txt,分析每一条数据。
while Not EOF
如果匹配到keywords中的数据,则命中
此record的IP是否在DirtyIP[]中,若是
pass
否则
DirtyIP.append(IP)
record的IP在DirtyIP中,则
写入到out.txt 中
否则
pass
如果所有线程都完成了
对out.txt去重(这个必须在最后才能的操作,没办法在读入的时候处理)
=======================================================================
flag = Top N文件是否存在的标志
线程2,3可以用同一个辅助函数:
bool isHitTarget(array[] , string record )
hit =fasle
for (element in array)
if element is the substring of record
hit = true
if hit == true
加入到 out.txt中
怎么对大数据去重呢?,我自己写的这个,不知道能不能承受大数据的冲击呢?效率高不高呢?谁用谁知道。。。
void getSingleRecord(filename)
while Not EOF
record = read from out.txt
if record in new_records
pass
else
new_records.append(record)
因为要写入到同一个out.txt文件中,所有要用互斥量,怎么写呢?
创建锁: g_mutex = threading.lock()
使用锁: g_mutex.acquire() ...
释放锁: g_mutex.release()
这三个线程分别用三个函数来解决:
def getTopN_IP(int n,string filename); 对应 th1 = threading.Thread(target = getTopN_IP, args =(n,filename) )
def getURLFromTopN_IP(topN[],filename) 对应 th2 = threading.Thread(target = getURLFromTopN_IP , args = (topN, filename))
def getURLFromDirty_IP(filename) 对应 th3 = threading.Thread(target = getURLFromDirty_IP,args = (filename))
等待线程完成:th1.join() th2.join() th3.join()
怎么从一条record中获取IP,获取关键的URL呢?
我首先就想到了正则表达式,以下是IP地址的正则表达式(我姑且相信它是对的):
((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d))))
但是我有更好的方法哦~~
因为胡哥给的数据都是IIS服务器的log,所以都是有特定格式的说。
我们可以根据这些特定格式来做文章,用split,然后数组的第i个和第j个就是我们要的IP地址和URL关键词了,这个方法不错吧,是吧?
==========================================================================================
import threading def getURLFromDirty_IP(filename): print "3" if __name__ == "__main__": infile = "in.txt" th3 = threading.Thread(target = getURLFromDirty_IP,args = (infile,)); //这里args中不加','会报错 th3.start() th3.join() print "Hello World";
mutex = threading.Lock() #创建线程锁,毕竟读文件存在竞争 mutex.acquire(100)#加个互斥锁 out.write(Path+"\r\n") mutex.release() #释放锁
import os os.path.isfile(infile) #返回False就不是文件,返回True就是了 os.path.exists(directory) #如果目录不存在就返回False
import os.path # To change this template, choose Tools | Templates # and open the template in the editor. __author__="Administrator" __date__ ="$2012-10-30 17:13:46$" import threading import os topN_IP = []; n = 10 #n是TOP N的n啊~~默认是10 threads = [] keywords = [] infile = "../infile/" outfile = "../outfile/" topNFile = "../topNFile/" dirtyFile = "../dirtyFile/dirtywords.txt" mutex = threading.Lock() #创建线程锁,毕竟读文件存在竞争 def getTopN_IP(n,infile,outfile): #IPs = "haha aa".split(" ") IPs = [] isRegetIP = False #如果文件已经存在,则默认我们曾经跑过了这个TopN_IP,pass if True == os.path.isfile(topNFile) : print topNFile +"已经存在,太好了~" f = file(topNFile,"r") while True: tmpLine = f.readline() if tmpLine == "": break topN_IP.append(tmpLine) f.close() if 0 == len(topN_IP): print "文件虽然存在,但是为空,请重新加入TOP_N_IP" isRegetIP = True if False == isRegetIP: f = file(infile,"r") while True: tmpLine = f.readline() if tmpLine == "": break tmpList = tmpLine.split(' ') #我们要解析的文件是IIS的日志如: #2012-03-17 07:21:50 192.168.100.20 GET / - 80 - 49.94.46.156 Mozilla/5.0+(Macintosh;+Intel+Mac+OS+X+10_7_3)+AppleWebKit/534.53.11+(KHTML,+like+Gecko)+Version/5.1.3+Safari/534.53.10 200 0 0 0 #很明显,这个结构很清晰,而且是通用的,不需要用正则去搞 #第九个是目标IP!print tmpList[8] IPs.append(tmpList[8]) f.close() #去重这句话好简单时尚啊~ singleIP = {}.fromkeys(IPs).keys() IPDict = {} for tmp in singleIP: IPDict[tmp] = 0; for tmp in IPs: IPDict[tmp] += 1 #对字典进行排序key=lambda e:e[1]表示对value排序。key=lambda e:e[0]对key排序 #IPDict.items()把字典搞成元祖集合的形式 #lambda就是匿名函数中,语句中冒号前是参数,可以有多个,用逗号隔开,冒号右边的返回值。 sortIP=sorted(IPDict.items(),key=lambda e:e[1],reverse=True) index = 0 for tmp in sortIP: index += 1 #因为元组(IP,个数),所以就是这么获取ip topN_IP.append(tmp[0]) #print tmp if index < 10: n = index def getURLFromTopN_IP(topN_IP,infile,outfile): #print topN_IP #print len(topN_IP) if 0 == len(topN_IP): print "top 名单为空" pass else: f = file(infile,"r") out = file(outfile,"w+") #还是根据IIS日志结构的来获取这个路径吧正则太困难了 #也就是tmpList[4] while True: tmpLine = f.readline() if tmpLine == "": break tmpList = tmpLine.split(' ') IP = tmpList[8] Path = tmpList[4] if IP in topN_IP: #加个互斥锁 mutex.acquire(100) out.write(Path+"\r\n") mutex.release() out.close() f.close() def getURLFromDirty_IP(infile,outfile,dirtyFile): f = file(infile,"r") out = file(outfile,"w+") dfile = file(dirtyFile,"r") #导入脏keywords dirtywords = [] while True: tmpLine = dfile.readline() if tmpLine == "" : break dirtywords.append(tmpLine) dfile.close() #字符串匹配 while True: flag = False tmpLine = f.readline() if tmpLine == "": break for word in dirtywords: if True == tmpLine.find(word): flag = True break if flag: tmpList = tmpLine.split(' ') #加个互斥锁 mutex.acquire(100) out.write(tmpList[4]+"\r\n") mutex.release() f.close() out.close() def getSingleRecord(outfile): f = file(outfile,"r") allList = [] while True: tmpLine = f.readline() if tmpLine == "" : break allList.append(tmpLine) singleList = {}.fromkeys(allList).keys() f.close() f2 = file(outfile,"w") for word in singleList: f2.write(word+"/r/n") f2.close() if __name__ == "__main__": while True: infile = "../infile/" outfile = "../outfile/" tmpfile = raw_input("请输入文件名(退出请输入:呵呵):") infile += tmpfile if infile == "呵呵": print "欢迎下次使用哦~~Ps:呵呵你妹!" break if False == os.path.isfile(infile): print "您输入的文件不存在哦~~" continue outfile += tmpfile[0:len(tmpfile)-4] outfile += "_out.txt" print "文件输出名为:"+outfile th1 = threading.Thread(target = getTopN_IP,args = (10,infile,outfile)); th2 = threading.Thread(target = getURLFromTopN_IP,args = (topN_IP,infile,outfile)); th3 = threading.Thread(target = getURLFromDirty_IP,args = (infile,outfile,dirtyFile)); threads.append(th1);threads.append(th2);threads.append(th3); th1.start() th1.join() th2.start() th3.start() th2.join() th3.join() #最终结果去重 getSingleRecord(outfile) print "处理完毕,请去文件夹目录查看处理结果:"+outfile;