表达式语言注入 (JEXL)¶
ID: java/jexl-expression-injection
Kind: path-problem
Security severity: 9.3
Severity: error
Precision: high
Tags:
- security
- external/cwe/cwe-094
Query suites:
- java-code-scanning.qls
- java-security-extended.qls
- java-security-and-quality.qls
Java EXpression Language (JEXL) 是 Apache Commons JEXL 库提供的简单表达式语言。其语法接近 ECMAScript 和 shell 脚本的混合。该语言允许调用 JVM 中可用的方法。如果使用攻击者控制的数据构建 JEXL 表达式,然后对其进行评估,则攻击者可能会运行任意代码。
建议¶
通常建议避免在 JEXL 表达式中使用不受信任的输入。如果无法做到这一点,则应在沙盒中运行 JEXL 表达式,该沙盒仅允许访问明确允许的类。
示例¶
以下示例使用不受信任的数据来构建和运行 JEXL 表达式。
public void evaluate(Socket socket) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
String input = reader.readLine();
JexlEngine jexl = new JexlBuilder().create();
JexlExpression expression = jexl.createExpression(input);
JexlContext context = new MapContext();
expression.evaluate(context);
}
}
下一个示例显示了如何在仅允许访问 java.lang.Math
类中的方法的沙盒中运行不受信任的 JEXL 表达式。该沙盒使用 Apache Commons JEXL 3 提供的 JexlSandbox
类实现。
public void evaluate(Socket socket) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
JexlSandbox onlyMath = new JexlSandbox(false);
onlyMath.white("java.lang.Math");
JexlEngine jexl = new JexlBuilder().sandbox(onlyMath).create();
String input = reader.readLine();
JexlExpression expression = jexl.createExpression(input);
JexlContext context = new MapContext();
expression.evaluate(context);
}
}
下一个示例显示了实现沙盒的另一种方法。它使用 JexlUberspect
的自定义实现,该实现检查被调用者是否是允许类的实例。
public void evaluate(Socket socket) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
JexlUberspect sandbox = new JexlUberspectSandbox();
JexlEngine jexl = new JexlBuilder().uberspect(sandbox).create();
String input = reader.readLine();
JexlExpression expression = jexl.createExpression(input);
JexlContext context = new MapContext();
expression.evaluate(context);
}
private static class JexlUberspectSandbox implements JexlUberspect {
private static final List<String> ALLOWED_CLASSES =
Arrays.asList("java.lang.Math", "java.util.Random");
private final JexlUberspect uberspect = new JexlBuilder().create().getUberspect();
private void checkAccess(Object obj) {
if (!ALLOWED_CLASSES.contains(obj.getClass().getCanonicalName())) {
throw new AccessControlException("Not allowed");
}
}
@Override
public JexlMethod getMethod(Object obj, String method, Object... args) {
checkAccess(obj);
return uberspect.getMethod(obj, method, args);
}
@Override
public List<PropertyResolver> getResolvers(JexlOperator op, Object obj) {
checkAccess(obj);
return uberspect.getResolvers(op, obj);
}
@Override
public void setClassLoader(ClassLoader loader) {
uberspect.setClassLoader(loader);
}
@Override
public int getVersion() {
return uberspect.getVersion();
}
@Override
public JexlMethod getConstructor(Object obj, Object... args) {
checkAccess(obj);
return uberspect.getConstructor(obj, args);
}
@Override
public JexlPropertyGet getPropertyGet(Object obj, Object identifier) {
checkAccess(obj);
return uberspect.getPropertyGet(obj, identifier);
}
@Override
public JexlPropertyGet getPropertyGet(List<PropertyResolver> resolvers, Object obj, Object identifier) {
checkAccess(obj);
return uberspect.getPropertyGet(resolvers, obj, identifier);
}
@Override
public JexlPropertySet getPropertySet(Object obj, Object identifier, Object arg) {
checkAccess(obj);
return uberspect.getPropertySet(obj, identifier, arg);
}
@Override
public JexlPropertySet getPropertySet(List<PropertyResolver> resolvers, Object obj, Object identifier, Object arg) {
checkAccess(obj);
return uberspect.getPropertySet(resolvers, obj, identifier, arg);
}
@Override
public Iterator<?> getIterator(Object obj) {
checkAccess(obj);
return uberspect.getIterator(obj);
}
@Override
public JexlArithmetic.Uberspect getArithmetic(JexlArithmetic arithmetic) {
return uberspect.getArithmetic(arithmetic);
}
}
}
参考¶
Apache Commons JEXL:项目页面。
Apache Commons JEXL 文档:JEXL 2.1.1 API。
Apache Commons JEXL 文档:JEXL 3.1 API。
OWASP:表达式语言注入。
通用弱点枚举:CWE-94。