java审计-表达式注入

文章探讨了SpringExpressionLanguage(SpEL)的表达式注入可能导致的任意命令执行风险,通过对比安全代码示例展示了如何使用SimpleEvaluationContext限制权限,以提高安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

  • SpEL(Spring Expression Language)表达式注入, 是一种功能强大的表达式语言、用于在运行时查询和操作对象图,由于未对参数做过滤可造成任意命令执行。

漏洞代码

// PoC: T(java.lang.Runtime).getRuntime().exec(%22open%20-a%20Calculator%22)

public String vul(String ex) {
    ExpressionParser parser = new SpelExpressionParser();

    // StandardEvaluationContext权限过大,可以执行任意代码,默认使用
    EvaluationContext evaluationContext = new StandardEvaluationContext();

    Expression exp = parser.parseExpression(ex);
    String result = exp.getValue(evaluationContext).toString();
    return result;
}

安全代码

// SimpleEvaluationContext 旨在仅支持 SpEL 语言语法的一个子集。它不包括 Java 类型引用,构造函数和 bean 引用

public String spelSafe(String ex) {
    ExpressionParser parser = new SpelExpressionParser();

    EvaluationContext simpleContext = SimpleEvaluationContext.forReadOnlyDataBinding().build();

    Expression exp = parser.parseExpression(ex);
    String result = exp.getValue(simpleContext).toString();
    return result;
}
                 
<think>好的,我现在需要处理用户关于Fel表达式注入的问题,用户想了解防御机制或安全解析的方法。首先,我得回顾一下Fel表达式的基本知识,以及它可能存在的安全风险。 根据引用[1],Fel表达式注入是因为未对用户输入进行验证,导致攻击者可以执行恶意表达式。所以防御的核心应该是输入验证和限制执行环境。引用[3]和[4]提到Fel引擎的使用,比如设置上下文和自定义函数,这可能是控制执行环境的方法。 用户可能需要具体的防御步骤,比如如何过滤表达式中的危险字符,或者如何安全配置Fel引擎。例如,引用[2]中的自定义上下文可以控制变量访问,这可能限制攻击者能使用的变量。引用[3]中的例子展示了如何从JSON中获取数据并设置到上下文中,这可能涉及如何安全地处理外部输入。 另外,引用[4]提到Fel允许替换函数和扩展模块,这可能意味着可以禁用危险函数或运算符。例如,限制对系统函数的调用,或者禁用反射相关的方法。 需要整理出具体的防御措施,比如白名单验证、沙箱环境、禁用危险功能等。同时,要确保回答结构清晰,分点说明,并引用相关文献支持。可能还需要生成相关问题,比如如何实现白名单,或者Fel的安全配置步骤。</think>### Fel表达式注入防御机制及安全解析方法 #### 一、Fel表达式注入攻击原理 Fel表达式注入攻击通过构造恶意表达式执行未授权操作(如文件读写、反射调用、系统命令执行),其根本原因是未对用户输入的表达式进行有效过滤和权限控制[^1]。例如攻击者可构造表达式`System.exit(0)`导致服务中断。 #### 二、核心防御策略 1. **输入白名单验证** - 定义允许的运算符和函数白名单(如仅允许`+`, `-`, `*`, `/`和数学函数) - 使用正则表达式过滤特殊字符 ```java String safePattern = "^[a-zA-Z0-9_+\\-*/() ]+$"; if (!expression.matches(safePattern)) throw new SecurityException(); ``` 2. **上下文隔离控制** - 通过自定义`FelContext`限制可访问变量[^2] ```java FelContext ctx = new AbstractContext() { @Override public Object get(String key) { if (!allowedKeys.contains(key)) return null; // 仅开放白名单变量 return super.get(key); } }; ``` 3. **禁用危险功能** - 移除默认函数库中的高危函数(如反射相关方法) ```java FelEngine fel = new FelEngineImpl(); fel.getFunMgr().remove("exec"); // 删除系统命令执行函数 ``` 4. **沙箱环境执行** - 使用`SecurityManager`限制权限 - 通过Java安全管理器禁止敏感操作 ```java System.setSecurityManager(new SecurityManager() { @Override public void checkExec(String cmd) { throw new SecurityException("禁止执行系统命令"); } }); ``` #### 三、安全解析最佳实践 1. **预编译表达式检测** ```java FelEngine fel = new FelEngineImpl(); Expression compiled = fel.compile(expression); // 检查AST节点类型 compiled.getAst().accept(new DefaultTraversalVisitor() { @Override public void visit(FunctionNode node) { if (node.getName().equals("exec")) throw new SecurityException("检测到危险函数"); } }); ``` 2. **启用编译模式提升安全性** Fel的编译模式(生成Java字节码)相比解释模式更易进行静态分析[^4] ```java FelEngine fel = new FelEngineImpl(); fel.setCompile(true); // 启用编译模式 ``` 3. **日志监控与审计** - 记录所有表达式执行日志 - 设置异常表达式报警阈值 #### 四、企业级防护方案示例 ```java public class SafeFelEvaluator { private static final Set<String> ALLOWED_VARS = Set.of("price","quantity"); private static final Pattern SAFE_PATTERN = Pattern.compile("^[\\w+\\-*/() ]+$"); public static Object safeEval(String expr) { // 输入验证 if (!SAFE_PATTERN.matcher(expr).matches()) { throw new SecurityException("非法字符"); } // 创建受限上下文 FelContext ctx = new MapContext(); ctx.set("price", 0); ctx.set("quantity", 0); // 配置安全引擎 FelEngine fel = new FelEngineImpl(ctx); fel.getFunMgr().clear(); // 移除所有内置函数 fel.getFunMgr().register(CommonFunctions.class); // 仅注册数学函数 return fel.eval(expr); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值