在 Chrome 扩展中绕过 X-Frame-Options DENY?

IT技术 javascript iframe google-chrome-extension x-frame-options
2021-01-31 17:28:25

我是Intab的作者,是一个 Chrome 扩展程序,可让您查看内联链接而不是新选项卡。幕后没有太多花哨的东西,它只是一个加载用户点击的 URL 的 iframe。

除了将 X-Frame-Options 标头设置为 DENY 或 SAMEORIGIN 的站点外,它的效果很好。一些非常大的网站,如谷歌和 Facebook 都使用它,这会产生轻微的卡顿体验。

有什么办法可以解决这个问题吗?由于我使用的是 Chrome 扩展程序,是否有任何我可以访问的浏览器级别的内容可能有帮助?寻找任何想法或帮助!

2个回答

Chrome 提供webRequestAPI 来拦截和修改 HTTP 请求。您可以删除X-Frame-Options标题以允许在 iframe 中内联页面。

chrome.webRequest.onHeadersReceived.addListener(
    function(info) {
        var headers = info.responseHeaders;
        for (var i=headers.length-1; i>=0; --i) {
            var header = headers[i].name.toLowerCase();
            if (header == 'x-frame-options' || header == 'frame-options') {
                headers.splice(i, 1); // Remove header
            }
        }
        return {responseHeaders: headers};
    }, {
        urls: [
            '*://*/*', // Pattern to match all http(s) pages
            // '*://*.example.org/*', // Pattern to match one http(s) site
        ], 
        types: [ 'sub_frame' ]
    }, [
        'blocking',
        'responseHeaders',
        // Modern Chrome needs 'extraHeaders' to see and change this header,
        // so the following code evaluates to 'extraHeaders' only in modern Chrome.
        chrome.webRequest.OnHeadersReceivedOptions.EXTRA_HEADERS,
    ].filter(Boolean)
);

在清单中,您需要指定webRequestwebRequestBlocking权限,以及您打算拦截URL 模式,即"*://*/*""*://www.example.org/*"上面的示例。

@GuyKorland 我明白了。Chrome 扩展程序无法修改响应正文,因此您很不走运。
2021-03-15 17:28:25
@TaiwanGrapefruitTea 扩展名的标题修改不会显示在 devtools 中。如果想查看header修改是否成功,可以查看chrome://net-internals/#events。
2021-03-26 17:28:25
结果发现 webRequest 在内容脚本上是不可访问的。我得把它移到背景上。
2021-04-04 17:28:25
@IanMcIntyreSilber 你好,我只是想知道你是否曾经使用过它,如果你做到了,你是否可以教我。
2021-04-04 17:28:25
@RobW X-Frame-Options 可以设置为 HTML 元元素,请参阅:javascript.info/tutorial/clickjacking
2021-04-04 17:28:25

使用 declarativeNetRequest 的 ManifestV3 示例

让我们使用新的declarativeNetRequest API 仅在 iframe 嵌入到我们的扩展程序的页面中时剥离标头。

清单.json

  "permissions": ["declarativeNetRequest"],
  "host_permissions": ["*://*.example.com/"],
  "background": {"service_worker": "bg.js"},

bg.js:

const iframeHosts = [
  'example.com',
];
chrome.runtime.onInstalled.addListener(() => {
  chrome.declarativeNetRequest.updateDynamicRules({
    removeRuleIds: iframeHosts.map((h, i) => i + 1),
    addRules: iframeHosts.map((h, i) => ({
      id: i + 1,
      condition: {
        domains: [chrome.runtime.id],
        urlFilter: `||${h}/`,
        resourceTypes: ['sub_frame'],
      },
      action: {
        type: 'modifyHeaders',
        responseHeaders: [
          {header: 'X-Frame-Options', operation: 'remove'},
          {header: 'Frame-Options', operation: 'remove'},
        ],
      },
    })),
  });
});