本文目录导读:

Java表达式注入案例
什么是表达式注入?
表达式注入是一种安全漏洞,当应用程序将用户输入直接传递给表达式求值引擎(如SpEL、OGNL、MVEL等)进行解析执行时,攻击者可以注入恶意表达式导致远程代码执行。
常见案例
Spring Expression Language (SpEL) 注入
漏洞代码示例:
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class SpELInjectionExample {
public static void main(String[] args) {
String userInput = "T(java.lang.Runtime).getRuntime().exec('calc.exe')";
ExpressionParser parser = new SpelExpressionParser();
// 危险:直接解析用户输入
Object result = parser.parseExpression(userInput).getValue();
System.out.println(result);
}
}
修复方案:
public class SpELFixExample {
public static void main(String[] args) {
String userInput = "T(java.lang.Runtime).getRuntime().exec('calc.exe')";
ExpressionParser parser = new SpelExpressionParser();
// 使用SimpleEvaluationContext限制可访问的类和对象
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// 或者直接在表达式中限制可访问的变量
try {
// 设置白名单,只允许访问特定对象
StandardEvaluationContext safeContext = new StandardEvaluationContext();
safeContext.setRootObject(new SafeObject());
Object result = parser.parseExpression(userInput).getValue(safeContext);
} catch (Exception e) {
// 安全的错误处理
System.err.println("非法表达式: " + e.getMessage());
}
}
static class SafeObject {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
OGNL (Object-Graph Navigation Language) 注入
常见于Struts2框架
漏洞代码示例:
import ognl.Ognl;
import ognl.OgnlContext;
public class OGNLInjectionExample {
public static void main(String[] args) {
String userInput = "#a=(new java.lang.ProcessBuilder(new java.lang.String[]{'cmd','/c','calc'})).start()";
OgnlContext context = new OgnlContext();
try {
// 危险:直接解析用户输入
Object expression = Ognl.parseExpression(userInput);
Ognl.getValue(expression, context, new Object());
} catch (Exception e) {
e.printStackTrace();
}
}
}
修复方案:
import ognl.ASTProperty;
import ognl.Node;
import ognl.Ognl;
import ognl.OgnlContext;
public class OGNLFixExample {
private static final String[] ALLOWED_PROPERTIES = {"name", "age", "email"};
public static boolean validateExpression(String expression) {
try {
Node node = Ognl.parseExpression(expression);
return validateNode(node);
} catch (Exception e) {
return false;
}
}
private static boolean validateNode(Node node) {
if (node instanceof ASTProperty) {
String property = ((ASTProperty) node).getProperty(null).toString();
return Arrays.asList(ALLOWED_PROPERTIES).contains(property);
}
// 递归验证子节点
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
if (!validateNode(node.jjtGetChild(i))) {
return false;
}
}
return true;
}
public static Object safeGetValue(String expression, Object root) {
if (!validateExpression(expression)) {
throw new SecurityException("非法表达式: " + expression);
}
OgnlContext context = new OgnlContext();
try {
Node node = Ognl.compileExpression(context, root, expression);
return Ognl.getValue(node, context, root);
} catch (Exception e) {
throw new RuntimeException("表达式执行失败", e);
}
}
}
MVEL (MVFLEX Expression Language) 注入
漏洞代码示例:
import org.mvel2.MVEL;
public class MVELInjectionExample {
public static void main(String[] args) {
String userInput = "Runtime.getRuntime().exec('calc')";
// 危险:直接执行用户输入
Object result = MVEL.eval(userInput);
System.out.println(result);
}
}
修复方案:
import org.mvel2.MVEL;
import org.mvel2.ParserContext;
public class MVELFixExample {
public static void main(String[] args) {
String userInput = "Runtime.getRuntime().exec('calc')";
// 创建安全的解析器上下文
ParserContext context = new ParserContext();
// 禁用危险的函数和类
context.addImport("Math", Math.class);
context.setAllowNakedMaptrixAccess(false);
context.setStrictTypeEnforcement(true);
// 定义白名单类
Set<String> allowedClasses = new HashSet<>();
allowedClasses.add("java.lang.Math");
allowedClasses.add("java.lang.String");
context.addClassImport("String", String.class);
// 使用白名单验证
if (isValidExpression(userInput, allowedClasses)) {
try {
Object result = MVEL.eval(userInput, context);
System.out.println("结果: " + result);
} catch (Exception e) {
System.err.println("表达式执行错误: " + e.getMessage());
}
} else {
System.err.println("包含不允许的类或方法");
}
}
private static boolean isValidExpression(String expression, Set<String> allowedClasses) {
// 检查是否包含危险的方法调用
String[] dangerousPatterns = {
"Runtime", "ProcessBuilder", "exec", "invoke",
"ClassLoader", "getClass", "forName"
};
for (String pattern : dangerousPatterns) {
if (expression.contains(pattern)) {
return false;
}
}
return true;
}
}
自定义表达式引擎注入
import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
public class ScriptEngineInjectionExample {
public static void main(String[] args) {
String userInput = "var proc = new java.lang.ProcessBuilder('calc').start()";
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
try {
// 危险:直接执行用户输入的脚本
engine.eval(userInput);
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
修复方案(使用沙箱环境):
import javax.script.*;
import java.util.*;
public class SecureScriptEngineExample {
public static void main(String[] args) {
String userInput = "var proc = new java.lang.ProcessBuilder('calc').start()";
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
// 创建安全上下文
Bindings bindings = engine.createBindings();
bindings.put("safeMath", new MathHelper());
// 使用简单的数学运算白名单
SimpleScriptContext context = new SimpleScriptContext();
context.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
// 设置写入限制
StringWriter writer = new StringWriter();
context.setWriter(writer);
try {
// 使用预编译和验证
if (isMathExpression(userInput)) {
Object result = engine.eval(userInput, context);
System.out.println("结果: " + result);
} else {
System.err.println("只允许数学表达式");
}
} catch (ScriptException e) {
System.err.println("脚本执行错误: " + e.getMessage());
}
}
private static boolean isMathExpression(String input) {
// 只允许基本的数学运算
return input.matches("[0-9+\\-*/()\\s.]+");
}
// 提供安全的方法
static class MathHelper {
public double add(double a, double b) { return a + b; }
public double subtract(double a, double b) { return a - b; }
public double multiply(double a, double b) { return a * b; }
public double divide(double a, double b) {
if (b == 0) throw new ArithmeticException("除数不能为0");
return a / b;
}
}
}
- 输入验证:严格验证和过滤用户输入
- 使用安全上下文:使用限制性的求值上下文
- 白名单机制:只允许访问特定的类和方法
- 禁用动态执行:尽可能避免使用表达式引擎
- 最小权限原则:应用程序只拥有必要的权限
- 使用安全库:选择有安全特性支持的表达式引擎版本
- 代码审查:定期进行安全代码审查
- 日志记录:记录所有表达式执行操作
检测工具
- FindSecBugs:用于检测Java安全漏洞
- Snyk:开源组件安全扫描
- OWASP Dependency Check:检查依赖项漏洞
- 静态代码分析工具:如SonarQube、Checkmarx等
避免表达式注入的最佳实践是在设计阶段就考虑安全性,避免将用户输入直接用于表达式求值,如果必须使用,要实施严格的输入验证和执行环境限制。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播