PratikKaran23/aem-hunter
GitHub: PratikKaran23/aem-hunter
一款针对 Adobe Experience Manager 的单文件未授权安全审计扫描器,覆盖 Dispatcher 绕过、暴露控制台、CVE 检测等数十类漏洞,通过功能验证有效降低误报率。
Stars: 0 | Forks: 1
# AEM Hunter — 未授权 AEM 安全扫描器
单文件 Adobe Experience Manager (AEM) 审计扫描器。只需指定一个 URL,
它就会深入运行所有已知的 AEM 漏洞检测 —— 无需身份验证,无需
cookie,也没有角色概念。输出结果为控制台 + HTML + JSON 报告。
## 安装说明
```
git clone https://github.com/PratikKaran23/aem-hunter.git
cd aem-hunter
pip install -r requirements.txt
```
单一依赖:`requests`。`httpx[http2]` 是可选的(用于仅支持 HTTP/2 的
目标 —— 见下文)。
## 使用方法
```
python3 aem_hunter.py # prompts for URL
python3 aem_hunter.py https://aem.example.com
python3 aem_hunter.py -u https://aem.example.com
python3 aem_hunter.py -u TARGET --proxy http://127.0.0.1:8080
python3 aem_hunter.py -u TARGET --aggressive # bigger dispatcher fuzz
python3 aem_hunter.py -u TARGET --http2 # HTTP/2-only targets
python3 aem_hunter.py -u TARGET --exploit # end-to-end JSP-RCE PoC
```
每次运行都会将 `report--unauthenticated-.{json,html}` 写入
当前目录(使用 `-o` 可覆盖此设置)。
### 仅支持 HTTP/2 的目标
许多企业级 AEM 部署位于 **仅支持
HTTP/2** 的 CDN/WAF/LB 之后。Python `requests` 仅支持 HTTP/1.1,因此直接扫描会因
`UnknownProtocol('HTTP/2')` 而终止,导致所有请求失败。有两个选项:
- **通过 Burp/mitmproxy** (`--proxy ...`) —— 代理会将 HTTP/2 降级为
HTTP/1.1,因此默认后端可以直接工作。
- **原生 HTTP/2** —— 无需代理:
pip install 'httpx[http2]'
python3 aem_hunter.py -u https://aem.example.com --http2
该工具会在预检时检测到 HTTP/2 错误,并提示您该使用哪种修复方法。
### 所有标志参数
| 标志 | 用途 |
| -------------------------- | ------------------------------------------------------------------------ |
| `target` / `-u` | 目标 URL(位置参数或 `-u`;如果不存在则提示输入) |
| `--proxy` | 通过代理路由(例如 Burp) |
| `--http2` | 原生 HTTP/2 后端(需要 `httpx[http2]`) |
| `-o, --output-dir` | 报告输出位置(默认:当前目录) |
| `--aggressive` | 扩展的 dispatcher-bypass / Sling-selector payload 集(请求数约增加 10 倍) |
| `--exploit` | 端到端 JSP RCE PoC + 反序列化探测(部署并移除金丝雀文件) |
| `--collaborator DOMAIN` | 通过 Burp Collaborator 实现的带外 SSRF |
| `--ssrf-callback HOST:PORT`| 自建 OOB SSRF 监听器(需要测试人员可访问的 IP) |
| `-v, --verbose` | 详细的请求日志记录 |
TLS 验证始终关闭(渗透测试默认设置)。
## 测试内容
以下每一项检测均在 **未授权** 状态下运行:
| 类别 | 覆盖范围 |
| ---------------------- | ------------------------------------------------------------------------------------------------- |
| 指纹识别 | 实例类型(Author 与 Publish)、版本提示、Sling / Day / CQ headers |
| 默认凭据 | `admin`、`author`、`anonymous`、`replication-receiver`、Geometrixx 演示用户、`vgnadmin`、`audit`、`grios` 等 |
| 暴露的控制台 | Felix `/system/console/*`(bundles、components、services、configMgr、scr、JMX、threads、memoryusage、profiler、logs、healthcheck、events、slingauth、jcrresolver、depfinder、status-*)、CRX DE、CRX Package Manager、CRX Explorer、Groovy Console、WebDAV、miscadmin、BulkEditor、Granite operations 控制台(maintenance、healthreports、replicationqueue、systemoverview、diagnosistools) |
| QueryBuilder | `/bin/querybuilder.json` 暴露、feed.xml、selector bypass、**`p.hits=selective&p.properties=rep:password` 哈希转储**、跨类型 rep:User 枚举 |
| Dispatcher bypass | `.css`/`.js`/`.png`/`.html` selector 技巧、`;` 分号滥用、`..;/` Jetty 规范化、`%2f`/`%00`/`%0a` 特性、双斜杠、URL 编码技巧、traversal+suffix 组合(通过 `--aggressive` 获取完整集合) |
| Sling 信息转储 | 在 `/`、`/content`、`/etc`、`/apps`、`/libs`、`/var`、`/home`、`/tmp`、`/conf` 以及许多子路径上的 `.json`、`.1.json`、`.tidy.json`、`.infinity.json`、`.harray.4.json`、`.children.json`、`.feed.xml` |
| JCR 枚举 | `users.1.json`、`groups.1.json`、`currentuser.json`、infinity 转储、authorizables servlet |
| 云服务泄露 | `/etc/cloudservices.infinity.json` — AWS / Salesforce / 第三方凭据泄露 |
| Crypto key 泄露 | `/etc/key.infinity.json` 主密钥(允许您离线解密 `{...}` 加密的机密) |
| 匿名用户创建 | `:operation=createUser` POST 到 `/libs/granite/security/post/authorizables` |
| SSRF(URL 确认) | linkchecker、SalesforceSecretServlet (CVE-2018-5006)、ReportingServicesServlet (CVE-2018-12809)、DAM cloud proxy、OpenSocial proxy、SiteCatalyst、AutoProvisioning、Google OAuth fetcher |
| SSRF(带外) | 通过 Burp Collaborator (`--collaborator`) 或自建监听器 (`--ssrf-callback`) 的相同集合 |
| **2025 CVEs** | CVE-2025-54253 (OGNL RCE Forms JEE)、CVE-2025-54254 (XXE)、CVE-2025-49533 (反序列化) |
| **2024 CVEs** | CVE-2024-43712、CVE-2024-43711、CVE-2024-32813、CVE-2024-32812、CVE-2024-32811、CVE-2024-26031、CVE-2024-26030、CVE-2024-20767 (Forms 文件读取)、CVE-2024-20736 |
| **2023 CVEs** | CVE-2023-22368、CVE-2023-22366、CVE-2023-22365 |
| **2022 CVEs** | CVE-2022-30679、CVE-2022-30680、CVE-2022-23710 (SOAP XXE) |
| **2021 CVEs** | CVE-2021-44519 (Forms 上传 XXE 基线)、CVE-2021-43762 (路径遍历) |
| **2019 CVEs** | CVE-2019-8088、CVE-2019-8087、CVE-2019-8086 (Forms XSS) |
| **2018 CVEs** | CVE-2018-5006、CVE-2018-12809、CVE-2018-19298、CVE-2018-19297 |
| **2017 / 2016 CVEs** | CVE-2017-3104 (SSTI)、CVE-2016-7882 (WCMDebugFilter 反射型 XSS)、CVE-2016-1027 |
| Sling POST 滥用 | 在 `/content/usergenerated`、`/var/dam` 创建任意节点、匿名用户创建 |
| 复制 | `/etc/replication.infinity.json` 中的传输凭据 — 直接的横向移动原语 |
| 源码泄露 | 在基于 JSP 的路径上的 `.source` / `.servlet` selector 技巧 |
| 额外的 servlet 暴露 | GQLServlet、LoginStatusServlet(+ 默认凭据检查)、AuditLogServlet、CRXDE logs、Disk Usage、BackgroundServlet、MergeMetadata、dumplibs、nodetypes、ContentFinder suggestions |
| 反射型 XSS | ChildrenList selector、CRXDE setPreferences、WCMDebugFilter、WCMSuggestionsServlet、CQ UI widgets、designs/default `0.gif`、标记为 CVE 的 XSS sinks、**暴露的 SWF 反射型 XSS** |
| 开放重定向 | `resource=`、`redirect=`、`return=`、`next=`、登录 `resource=`、WCM 页面重定向(HTTP 30x + HTML/JS sinks) |
| GraphQL | Endpoint 枚举 + introspection (`{__schema{types{...}}}`) |
| WebDAV 方法 | `OPTIONS` 发现可写方法(PUT/DELETE/MKCOL/MOVE)、PROPFIND XXE |
| ACS AEM Tools | AEM Fiddle JSP-eval RCE、ACS Tools 是否存在 |
| 反序列化 | ExternalJobServlet Java 不受信任的反序列化探测 (`--exploit`) |
| Nuclei 路径集 | 从 projectdiscovery/nuclei-templates AEM 集移植的约 45 项检测 + Cappricio aem-xss |
servlet/XSS/SSRF 的大部分覆盖范围移植自
[0ang3el/aem-hacker](https://github.com/0ang3el/aem-hacker),并使用此工具的
身份验证绕过和报告功能重新实现。
### 带外 SSRF — Burp Collaborator (`--collaborator`)
AEM 连接器 servlet 中的盲 SSRF 通过带外方式进行确认。
推荐的方法是 **Burp Collaborator**:
```
python3 aem_hunter.py -u TARGET --proxy http://127.0.0.1:8080 --collaborator abc123.oastify.com
```
它为每个 servlet(Salesforce / Reporting / SiteCatalyst /
AutoProvisioning / Opensocial / linkchecker)触发一个子域。在
Collaborator 选项卡中如果出现对
`salesforcesecret.abc123.oastify.com` 的 DNS/HTTP 命中,
即可确认是通过 SalesforceSecretServlet (CVE-2018-5006) 等实现的 SSRF
等。(该工具无法替您轮询
Collaborator,因此它会报告已触发的探测以及用于归因的子域到 servlet 的
映射关系。)
或者,如果您有一个测试人员可访问的 IP(VPS/隧道,而不是通过 Burp),
请使用自建的自动确认监听器:
```
python3 aem_hunter.py -u TARGET --ssrf-callback 1.2.3.4:8000
```
### `--exploit` — 端到端 RCE PoC
默认情况下,提权模块会安全地确认原语(创建然后
立即删除一次性的测试制品)。使用 `--exploit`,它还会尝试
端到端的 JSP RCE PoC(通过 Sling POST
servlet / package install / `sling:resourceType` 链部署并移除一个金丝雀 JSP)。该金丝雀仅会打印
`System.getProperty("user.name")` — 证明执行了 Java 代码而无需运行
OS 命令。仅在您被授权进行积极利用的系统上使用 `--exploit`。
## 准确性 — 杜绝“shell 已加载 = 严重”的误报
AEM author 实例会将诸如 CRXDE、
Package Manager 和 Felix console 等控制台的 **HTML/JSP shell** 提供给*任何人*(HTTP 200),而实际的
功能仍处于登录状态。简单的扫描器会将该 200 标记为 CRITICAL —
这是一个误报。本工具不会这样做:
- **登录/身份验证墙的响应会被抑制。** 一个实际上是登录
页面的 200 响应(`j_security_check`、`granite.shell.login`、`QUICKSTART`、登录表单、
身份验证重定向、401/403)永远不会被报告为可访问。
- **控制台是通过功能验证的,而不是通过其 shell。** CRITICAL 仅在
特权操作实际成功时才会触发 —— `bundles.json` 返回
实时的 OSGi 清单,package service 返回真实的 package 列表,
或者受保护的 JCR 节点返回真实的 `jcr:primaryType` JSON。如果仅渲染了
shell,您只会得到一条 **INFO** 提示,而不是 critical。
- **数据 Endpoint 必须返回真实的 JCR/JSON**,而不是空的 `{}` 或 HTML
页面,并且只有在响应体实际包含
类似机密的内容时,严重程度才会被提升。
因此,在一个被锁定的 author 实例上,您将主要看到 INFO —— 这是
最真实客观的结果。
## 报告
每次运行都会生成:
- 带有严重性标签的实时控制台输出
- `report--unauthenticated-.json` — 机器可读的发现
- `report--unauthenticated-.html` — 带有证据的样式化报告、
请求/响应片段、参考和 CVE 章
HTML 使用内联 CSS,因此它可以在没有
互联网访问的物理隔离机器上完美渲染。报告被 git-ignored 忽略,因此检测结果永远不会被提交。
## 参考
基于以下公开研究构建:
- 0ang3el/aem-hacker
- Assetnote / hopgoblin
- HackTricks AEM section
- Mikhail Egorov, "Hacking AEM" (adaptTo 2018)
- Adobe APSB advisories, CISA KEV (CVE-2025-54253)
- Various HackerOne disclosures (#1247163, #436555, #698991, …)
- projectdiscovery/nuclei-templates (http/misconfiguration/aem set)
- Cappricio-Securities/aem-xss
## 许可证
MIT。请负责任地使用。
标签:AEM, CISA项目, Python, 无后门, 运行时操纵, 逆向工具