You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通过预解析传入表达式能否让JS的eval()函数变得安全?

能否通过预解析限制eval()的安全性?

结论:通过预解析传入eval()的代码来保证执行安全,本质上是不可行的,以下是具体原因:

1. JavaScript语法的隐式特性与歧义性,导致静态预解析无法完全覆盖

即使你禁止了for/while等显式流程控制语句,攻击者仍可通过隐式方式实现无限阻塞或恶意操作:

  • 利用数组方法触发大量计算:eval("Array(1e9).forEach(() => {})"),无显式循环但会直接耗尽浏览器资源
  • 立即执行函数绕过流程控制检查:eval("(() => { /* 恶意代码,比如窃取Cookie */ })()"),静态分析若仅检查流程控制关键字,会忽略这类匿名函数的即时执行
  • 通过Function构造函数动态生成代码:eval("Function('alert(document.cookie)')()"),若你的白名单未明确禁止Function全局对象,这类调用会直接绕过检查

2. 动态代码生成可轻松绕过静态预解析

攻击者可通过字符串拼接、变量替换等方式生成恶意代码,静态预解析无法识别动态组合后的危险内容:

  • 拼接函数名绕过白名单:eval("('al' + 'ert')(document.cookie)"),静态检查时仅能看到字符串字面量,无法预判拼接后的结果是alert调用
  • 利用字符编码转换:eval(String.fromCharCode(97,108,101,114,116,40,39,104,97,99,107,101,100,39,41)),静态解析无法直接识别编码后的恶意函数

3. 原型链与作用域逃逸可绕过变量/函数白名单限制

即使你严格限制了白名单内的变量和函数,攻击者仍可通过原型链或作用域特性访问全局对象的敏感API:

  • 原型链间接获取全局构造函数:eval("Object.prototype.constructor('alert(1)')()"),通过Object原型拿到Function构造函数,进而执行任意代码
  • 利用this指向全局对象:eval("this['document']['cookie']"),若白名单未限制this的属性访问,可直接获取DOM敏感数据
  • 闭包作用域泄露:若eval()在当前作用域执行,攻击者可通过eval("sensitiveVariable")直接读取当前作用域内未加入黑名单的敏感变量,而你无法提前预知所有作用域内的变量

4. 浏览器环境的隐式API暴露无法完全封堵

浏览器环境中存在大量可被间接调用的内置API,即使你禁用了常见的document/window,仍有隐蔽路径:

  • 通过匿名函数获取全局上下文:eval("(function(){return this;})().navigator.userAgent"),利用匿名函数的this指向全局对象,进而访问敏感信息
  • 利用错误栈探测环境:eval("new Error().stack.split('at ')[1].split('(')[0]"),可用于收集环境信息为后续攻击做准备

总结

eval()的原生性能和语言一致性确实有优势,但JavaScript的动态特性、语法复杂性以及浏览器环境的隐式暴露,导致任何预解析规则都存在被绕过的可能——你无法覆盖所有潜在的恶意代码编写方式,只要有一个遗漏点,就会导致安全风险。

内容的提问来源于stack exchange,提问作者Erik Hermansen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 22:20:41