谷桐羽 2026-05-16 17:40 采纳率: 98.7%
浏览 0
已采纳

`engine.eval(javascript)` 执行恶意脚本导致RCE或XSS漏洞

在基于 GraalVM、Nashorn 或某些 JS 引擎嵌入场景(如 Java 中 `ScriptEngine.eval()`)中,直接调用 `engine.eval(userInput)` 执行未经净化的用户可控 JavaScript 字符串,极易引发严重安全风险:一方面,若引擎具备 Java 互操作能力(如 GraalVM 的 `PolyglotContext` 或 Nashorn 的 `Java.type`),攻击者可构造 `engine.eval("Java.type('java.lang.Runtime').getRuntime().exec('calc')")` 实现远程代码执行(RCE);另一方面,若 eval 结果被直接注入 HTML(如 `document.innerHTML = result`),或脚本在浏览器上下文中执行,则可触发 DOM-based XSS。此类漏洞本质是信任边界失效——将不可信输入当作可信代码执行。常见误判包括“仅服务端执行就无 XSS”“禁用 `eval` 就安全”(实际 `Function constructor`、`setTimeout(string)` 等仍可绕过)。如何在保留动态脚本能力前提下实现安全沙箱与最小权限隔离?
  • 写回答

1条回答 默认 最新

  • 三月Moon 2026-05-16 17:40
    关注
    ```html

    一、认知层:理解沙箱失效的本质与攻击面全景

    动态脚本执行(ScriptEngine.eval())在规则引擎、低代码平台、报表公式计算等场景中广泛存在。但其本质是将字符串作为代码执行——这在安全模型中属于“最高特权操作”。GraalVM 的 PolyglotContext 默认启用 Java 互操作;Nashorn 的 Java.typeJavaImporter 可直接访问 JVM 类型系统;而浏览器端的 evalFunction('return '+userCode)setTimeout('alert(1)',0) 均构成完整执行通道。攻击者无需 XSS 上下文即可完成 RCE(如 Runtime.exec)、任意文件读写(Files.readAllBytes)、JNDI 注入(new javax.naming.InitialContext().lookup("ldap://..."))。

    二、架构层:沙箱设计的三大核心支柱

    • 执行隔离:进程级(独立 JVM 进程)、线程级(受限 ThreadGroup + SecurityManager)、上下文级(GraalVM Context.newBuilder().allowIO(false).allowHostAccess(HostAccess.NONE)
    • 能力裁剪:禁用危险全局对象(java, javax, com.sun, sun.*)、限制内置 API(eval, Function, setTimeout, setInterval)、重写 globalThis 属性
    • 输出约束:强制返回类型校验(仅允许 Number/String/Boolean/null/Object,禁止 Promise/Function/ArrayBuffer 等可逃逸类型)

    三、实现层:GraalVM 与 Nashorn 的差异化加固方案

    引擎推荐替代方案关键加固配置不可绕过检测项
    GraalVM JSContext.newBuilder("js").build().allowIO(false).allowHostAccess(HostAccess.NONE).allowExperimentalOptions(true).option("js.nashorn-compat", "false")拦截 context.eval("js", "Java.type('java.lang.Runtime')")
    Nashorn(已弃用)迁移至 GraalVM 或使用 SimpleScriptContext + 自定义 Bindingsengine.put("java", null); engine.put("javax", null); engine.setSecurityManager(new NoReflectionSM())覆盖 __noSuchProperty__ 钩子阻止 this.java 动态访问

    四、防御纵深:从语法解析到运行时监控的多层过滤

    单纯依赖引擎配置仍不足。需构建如下防御链:

    1. 词法预检:使用 Acorn 或 GraalVM 内置 parser 提取 AST,拒绝含 CallExpression.callee.name === 'Java'MemberExpression.object.name === 'java' 的节点
    2. 白名单函数注册:仅暴露 Math.abs, Date.now, JSON.parse(经严格 schema 校验)等无副作用函数
    3. 超时与内存熔断:设置 context.setLimits(ContextLimits.newBuilder().timeLimit(5, TimeUnit.SECONDS).heapSizeLimit(8 * 1024 * 1024).build())
    4. 执行后审计日志:记录所有 eval 调用的哈希指纹、调用栈、返回类型、耗时,接入 SIEM 实时告警异常模式

    五、验证层:构建可量化的沙箱有效性评估体系

    graph TD A[构造 23 类已知绕过 Payload] --> B{语法层拦截} B -->|通过| C[AST 分析层拦截] B -->|未通过| D[标记为高危] C -->|通过| E[运行时权限拦截] C -->|未通过| D E -->|通过| F[输出类型校验] E -->|未通过| D F -->|通过| G[✅ 沙箱有效] F -->|未通过| D

    六、演进层:面向未来的弹性沙箱架构

    随着 WASM、WebAssembly System Interface(WASI)成熟,建议采用分层执行模型:
    • 第一层:JS 引擎沙箱(处理轻量逻辑表达式)
    • 第二层:WASI 模块(执行需 I/O 的可信插件,如 CSV 解析)
    • 第三层:gRPC 边界服务(调用外部风控/规则服务,避免本地敏感操作)
    该架构天然支持跨语言、可审计、可热更新,并满足 SOC2 / ISO27001 对“最小权限+执行分离”的合规要求。

    ```
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 今天
  • 创建了问题 5月16日