d3xm0s/Reaper
GitHub: d3xm0s/Reaper
Reaper 是一个零依赖的纯 Ruby Web 漏洞扫描器,通过差异比对确认注入漏洞,覆盖十余种检测类别,并内置带外监听与认证扫描支持。
Stars: 0 | Forks: 0
# REAPER
自动化 Web 漏洞扫描器。
只需提供一个 URL。它会爬取目标,提取所有可访问的查询参数、表单字段和请求头,然后对每一个进行污染(注入),并确认实际触发了什么——包括 SSTI、SQL 注入(基于报错和时间)、反射型 XSS、LFI/路径遍历、OS 命令注入和开放重定向。每一个判断都是通过与参数自身的基准进行差异比对得出的,因此原本就存在的数据库错误,或者经过 HTML 编码后返回的标记,都不会被误判为漏洞命中。纯 Ruby stdlib 实现,只要有 Ruby 环境就能运行。
## 检测项目
| 类别 | 确认方式 |
|-------|---------------------|
| SSTI | `{{111*111}}` 及类似表达式计算出 `12321`,随后对引擎进行指纹识别并尝试 RCE |
| SQLi | 数据库报错(或两次 5 秒延迟)确认漏洞,随后对 DBMS 进行指纹识别并提取版本信息 |
| NoSQLi | 通过运算符或损坏的引号触发 MongoDB/driver 报错 |
| XSS | 原始 `<>` 标记在未经编码的情况下被反射回显 |
| LFI / 路径遍历 | 返回了 `/etc/passwd` 的内容(`root:...:0:0:`) |
| 命令注入 | `sleep 5` payload 导致响应延迟,并经过两次确认 |
| SSRF | `file://` URL 被引用,其内容以带内方式泄露回来 |
| Blind SSRF | URL 形式的参数触发了向内置 OOB 监听器的回调 |
| XXE | 外部实体在带内读取 `/etc/passwd`,或进行带外回调 |
| 批量赋值 | 意外的特权 JSON 字段(如 `is_admin`, `role` 等)被绑定并回显 |
| CRLF | 参数中的 CR/LF 在响应中拆分出攻击者控制的 header |
| 开放重定向 | 被污染的 `Location:` 指向攻击者控制的主机 |
## WAF 与速率限制
所有请求都通过同一个客户端传输,因此请求的节奏控制和重试机制在全局(爬取、检测、登录)均适用。遇到 429/503 错误时会进行重试,并采用指数退避策略(遵循 `Retry-After` 头),最大重试次数默认为 `--retry` 2 次。`--rate` 限制所有 worker 的每秒请求数,`--delay` 为每个 worker 的请求间隔设置时间,而 `--jitter` 会对该延迟进行随机化处理,使得请求节奏不至于成为死板的固定模式。当目标进行拦截时,reaper 会对 WAF(Cloudflare、Imperva、Akamai、ModSecurity 等)进行指纹识别,并在运行结束时提示您已受到限流。
```
bin/reaper http://target/ --rate 10 --delay 0.2 --jitter 0.4 # gentle
bin/reaper http://target/ --retry 5 # ride out 429s
```
## 授权扫描
只需为 reaper 提供一个登录流程,它就会优先执行该流程,保持 session,随后的所有请求——包括爬取和全部四种攻击面——都会继承该 session。
```
# 来自 form login 的 cookie session
bin/reaper http://target/dashboard \
--login http://target/login --login-data 'user=admin&pass=pw'
# 从 JSON login response 中提取的 bearer token
bin/reaper http://api/v1/me --data '{"q":"x"}' \
--login http://api/v1/auth --login-data '{"user":"a","pass":"b"}' --login-token token
# 由 synchroniser CSRF token (Django, Rails, ASP.NET, Laravel) 保护的登录
bin/reaper http://target/app \
--login http://target/login --login-data 'user=admin&pass=pw' --csrf
```
凭据会以 JSON 或表单编码的格式被自动检测(`@file` 表示从磁盘读取)。配合 `--csrf` 使用时,reaper 会先 GET 获取表单页面,抓取隐藏的 anti-CSRF token,并将表单页面的 cookie 带入到 POST 请求中。捕获到的 session cookie 以及任何 `--login-token` 指定的 bearer token 会被合并到请求头中,因此它们可以与 `-H` 叠加使用,并应用于查询参数、表单、请求头以及 JSON body 注入。
## 带外检测 (Blind SSRF / XXE)
盲注漏洞不会在响应中体现——唯一的证据是目标服务器的反向连接请求。Reaper 自带了监听器:它会为每个 payload 生成一个唯一的 token,将其嵌入到回调 URL 中,并将任何命中结果与导致该命中的注入行为关联起来。在本地运行时,无需任何设置,它会分发 `http://127.0.0.1:8899/` 形式的 URL。如果是真实的测试任务,请将其指向目标服务器可访问到的主机地址:
```
# 监听所有 interfaces,callback url 为目标实际解析的地址
bin/reaper https://target/ --oob-bind 0.0.0.0:80 --oob-url http://oob.your-domain.com
# 同时捕获仅 DNS 的 egress(需要将该 zone 委托给此 box)
bin/reaper https://target/ --oob-bind 0.0.0.0:53 --oob-domain oob.your-domain.com --oob-ip
bin/reaper https://target/ --no-oob # turn the listener off
```
基于时间的检测会先发送一个控制请求,然后要求在两次独立的试探中都能复现延迟现象才会上报漏洞,这能有效消除由网络抖动引起的误报。
当确认存在 SSTI 时,reaper 会进行漏洞利用升级:它会读取成功的定界符,对引擎(Jinja2、Twig、Nunjucks、Smarty、ERB、Freemarker、Spring EL、Ruby)进行指纹识别,并发送特定于该引擎的 payload 来执行 `id` 命令。如果返回了 `uid=...` 输出结果,它会作为单独的严重级别 `SSTI RCE` 漏洞进行报告,并注明引擎名称及命令输出内容。
SQL 注入也以同样的方式进行升级:对 DBMS 进行指纹识别(通过错误特征,或对盲注有效的休眠语法),对于基于错误的漏洞,会使用带标记包裹的 payload(`SQLi (data extraction)`)提取版本信息。在 MySQL 上,它还会进一步进行 UNION dump——找到列数、确定可见的列,然后直接从 `information_schema` 中读取表名、最相关表中的列名以及部分数据行(`SQLi (UNION dump)`)。可以通过传递 `--no-exploit` 参数让所有检测在确认漏洞存在后即停止。
## 环境要求
Ruby >= 3.0。无需额外安装任何 gems 即可运行。
## 安装
```
git clone reaper
cd reaper
chmod +x bin/reaper
ln -s "$PWD/bin/reaper" ~/.local/bin/reaper # optional, puts it on PATH
```
## 使用说明
```
bin/reaper http://target/search?q=x # scan a single parameterised url
bin/reaper target.com -d 2 # crawl two levels deep first
bin/reaper http://target/ --only sqli,ssti # run a subset of checks
bin/reaper http://target/ -t 16 # more workers
bin/reaper http://target/ -o report.json # write a JSON report
bin/reaper http://target/ -H "Cookie: sid=..." # authenticated scan
bin/reaper http://target/ --proxy http://127.0.0.1:8080 # through Burp
bin/reaper http://api/v1/search --data '{"q":"x"}' # JSON API endpoint
```
## API 目标 (JSON bodies)
爬虫只能解析 HTML,因此 JSON API 需要手动驱动:通过 `--data`(直接输入或 `@file`)传入一个示例 body,reaper 会将其展平到叶子节点路径,每次污染其中一个字段——包括嵌套对象和数组元素——并在每次请求时重建文档结构。所有的检测都会针对这些字段运行,并且 JSON 响应中反射回来的 `<>` 不会被判定为 XSS。批量赋值检测还会额外添加原本 body 中不存在的特权字段,并报告那些被 API 绑定并回显的字段。
```
bin/reaper http://api/v1/search --data '{"q":"x","filter":{"id":1}}'
bin/reaper http://api/v1/item --data @body.json --method patch
```
## 参数标志
```
-u, --url URL target url (also accepted as a positional arg)
-d, --depth N crawl depth (default 1)
--data DATA JSON body to inject into (or @file); switches to API mode
--method M http method for --data: post (default), put, patch, delete
--no-headers skip injecting into request headers
-t, --threads N concurrent workers (default 8)
-T, --timeout SEC per-request timeout (default 12)
--delay SEC delay before each request per worker (default 0)
--jitter FRAC randomise --delay by +/- this fraction, e.g. 0.3
--rate N cap total requests per second across all workers
--retry N retry 429/503 up to N times with backoff (default 2)
--only a,b,c run only these checks: ssti, sqli, nosqli, xss, lfi, cmdi, ssrf, blind-ssrf, xxe, mass-assign, crlf, redirect
-H, --header 'K: V' extra request header, repeatable
-A, --user-agent UA custom user agent
--proxy URL route requests through an http proxy
--secure verify TLS certificates (off by default)
--no-exploit confirm SSTI only, skip the engine fingerprint + RCE step
--login URL log in (POST) before scanning and hold the session
--login-data DATA credentials for --login: JSON or form-encoded (or @file)
--login-token PATH pull a bearer token from this JSON field of the response
--csrf scrape the anti-CSRF token from the login form first
--csrf-url URL page to scrape the token from (default: the --login url)
--csrf-field NAME exact hidden field name of the token (default: auto-detect)
--oob-bind H:PORT OOB listener bind (default 127.0.0.1:8899)
--oob-url URL callback base url the target reaches (default http://)
--oob-domain DOM enable subdomain tokens + DNS catcher (needs the zone delegated)
--oob-ip IP A record the DNS catcher answers with
--no-oob disable the out-of-band listener (blind checks off)
-o, --output FILE write a JSON report
--no-banner suppress the banner
```
## 针对内置实验环境进行测试
在 `lab/` 目录下提供了一个故意包含漏洞的测试目标,您无需接触任何非自身资产即可看到真实的漏洞报告。它仅绑定到 localhost。
```
ruby lab/vulnserver.rb # terminal 1: http://127.0.0.1:8000
bin/reaper http://127.0.0.1:8000 # terminal 2: scan it
```
实验环境会通过 localhost 回连到 OOB 监听器,因此在本地运行时,blind SSRF 和 blind XXE 漏洞检测可以端到端地触发——无需公共主机。
实验环境中的命令注入 endpoint 是模拟的——它通过识别 shell 元字符来执行休眠操作,而不是真正去执行系统命令,因此运行该实验环境绝对不会执行被注入的输入内容。
## 开发说明
无需运行时 gems;测试基于 Ruby 自带的 minitest 和 rake 运行。
```
rake test # boots the lab and drives the real engine against it
```
测试套件会在回环端口上启动 `lab/vulnserver.rb`,对其进行爬取,并验证所有的检测类别——无论是带内还是带外检测——是否依然能成功确认漏洞。CI 会在每次代码提交时执行相同的测试。
## 适用范围
主动扫描器:它会发送攻击性流量。请仅对您已获得授权测试的系统运行此工具。
## 检测项目
| 类别 | 确认方式 |
|-------|---------------------|
| SSTI | `{{111*111}}` 及类似表达式计算出 `12321`,随后对引擎进行指纹识别并尝试 RCE |
| SQLi | 数据库报错(或两次 5 秒延迟)确认漏洞,随后对 DBMS 进行指纹识别并提取版本信息 |
| NoSQLi | 通过运算符或损坏的引号触发 MongoDB/driver 报错 |
| XSS | 原始 `<>` 标记在未经编码的情况下被反射回显 |
| LFI / 路径遍历 | 返回了 `/etc/passwd` 的内容(`root:...:0:0:`) |
| 命令注入 | `sleep 5` payload 导致响应延迟,并经过两次确认 |
| SSRF | `file://` URL 被引用,其内容以带内方式泄露回来 |
| Blind SSRF | URL 形式的参数触发了向内置 OOB 监听器的回调 |
| XXE | 外部实体在带内读取 `/etc/passwd`,或进行带外回调 |
| 批量赋值 | 意外的特权 JSON 字段(如 `is_admin`, `role` 等)被绑定并回显 |
| CRLF | 参数中的 CR/LF 在响应中拆分出攻击者控制的 header |
| 开放重定向 | 被污染的 `Location:` 指向攻击者控制的主机 |
## WAF 与速率限制
所有请求都通过同一个客户端传输,因此请求的节奏控制和重试机制在全局(爬取、检测、登录)均适用。遇到 429/503 错误时会进行重试,并采用指数退避策略(遵循 `Retry-After` 头),最大重试次数默认为 `--retry` 2 次。`--rate` 限制所有 worker 的每秒请求数,`--delay` 为每个 worker 的请求间隔设置时间,而 `--jitter` 会对该延迟进行随机化处理,使得请求节奏不至于成为死板的固定模式。当目标进行拦截时,reaper 会对 WAF(Cloudflare、Imperva、Akamai、ModSecurity 等)进行指纹识别,并在运行结束时提示您已受到限流。
```
bin/reaper http://target/ --rate 10 --delay 0.2 --jitter 0.4 # gentle
bin/reaper http://target/ --retry 5 # ride out 429s
```
## 授权扫描
只需为 reaper 提供一个登录流程,它就会优先执行该流程,保持 session,随后的所有请求——包括爬取和全部四种攻击面——都会继承该 session。
```
# 来自 form login 的 cookie session
bin/reaper http://target/dashboard \
--login http://target/login --login-data 'user=admin&pass=pw'
# 从 JSON login response 中提取的 bearer token
bin/reaper http://api/v1/me --data '{"q":"x"}' \
--login http://api/v1/auth --login-data '{"user":"a","pass":"b"}' --login-token token
# 由 synchroniser CSRF token (Django, Rails, ASP.NET, Laravel) 保护的登录
bin/reaper http://target/app \
--login http://target/login --login-data 'user=admin&pass=pw' --csrf
```
凭据会以 JSON 或表单编码的格式被自动检测(`@file` 表示从磁盘读取)。配合 `--csrf` 使用时,reaper 会先 GET 获取表单页面,抓取隐藏的 anti-CSRF token,并将表单页面的 cookie 带入到 POST 请求中。捕获到的 session cookie 以及任何 `--login-token` 指定的 bearer token 会被合并到请求头中,因此它们可以与 `-H` 叠加使用,并应用于查询参数、表单、请求头以及 JSON body 注入。
## 带外检测 (Blind SSRF / XXE)
盲注漏洞不会在响应中体现——唯一的证据是目标服务器的反向连接请求。Reaper 自带了监听器:它会为每个 payload 生成一个唯一的 token,将其嵌入到回调 URL 中,并将任何命中结果与导致该命中的注入行为关联起来。在本地运行时,无需任何设置,它会分发 `http://127.0.0.1:8899/标签:CISA项目, Ruby, Web安全, 加密, 漏洞扫描器, 知识库, 蓝队分析