在基于 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.type、JavaImporter可直接访问 JVM 类型系统;而浏览器端的eval、Function('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 JS Context.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动态访问四、防御纵深:从语法解析到运行时监控的多层过滤
单纯依赖引擎配置仍不足。需构建如下防御链:
- 词法预检:使用 Acorn 或 GraalVM 内置 parser 提取 AST,拒绝含
CallExpression.callee.name === 'Java'或MemberExpression.object.name === 'java'的节点 - 白名单函数注册:仅暴露
Math.abs,Date.now,JSON.parse(经严格 schema 校验)等无副作用函数 - 超时与内存熔断:设置
context.setLimits(ContextLimits.newBuilder().timeLimit(5, TimeUnit.SECONDS).heapSizeLimit(8 * 1024 * 1024).build()) - 执行后审计日志:记录所有
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 对“最小权限+执行分离”的合规要求。本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报- 执行隔离:进程级(独立 JVM 进程)、线程级(受限 ThreadGroup + SecurityManager)、上下文级(GraalVM