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

使用PHP代理脚本加载iframe的实现方案是否存在安全隐患?

问题背景

我们网站使用某可信第三方提供的工具,原有流程如下:

  • 用户点击链接
  • 打开模态窗口(modal window),其中包含指向第三方域名的iframe
  • 用户与工具交互完成后,iframe向我方发送消息(iframe message)
  • 我方接收消息后关闭模态窗口并执行后续操作

这套流程运行正常,但第三方录屏服务常因iframe跨域无法录制其中的交互内容,导致录屏里的iframe区域显示空白。虽然部分录屏服务商支持跨域iframe录制,但我们不想受限于此类服务商。

因此计划部署自有域名下的PHP代理脚本作为中转,让iframe指向自有域名以解决录屏问题。我们信任第三方来源,不担心其恶意行为,重点关注黑客利用代理脚本实施攻击的风险,现询问以下代码是否存在需修复的安全漏洞?


相关代码片段

1. 创建iframe的JavaScript代码

window.openProxiedIframe = href => {
    let url = new URL('https:' + href);
    let queryString = "?";
    for (const [key, value] of url.searchParams) {
        queryString = `${queryString}${key}=${value}&`;
    }
    let proxyURL = "https://www.example.com/proxy.php" + queryString;
    if ( jQuery("#designTool").length && jQuery("#designTool").hasClass("ui-dialog-content") ) {
        jQuery("#designTool").dialog("destroy");
        jQuery("#designTool").remove();
    }
    jQuery(`<div id='designTool'><iframe style='height: 100%; width: 100%; margin: 0px; border: none;' src='${proxyURL}' /></div>`).appendTo("body").dialog({
        modal: true,
        title:"Design Your Item"
    });
};

2. PHP代理脚本(proxy.php)

// it's not important what a and b are, what matters is that they are required, so
// any legit request will have them. Also note that example.com here is really
// a third-party domain, not us. Again, the third-party is trusted, and
// I hardcoded their domain to prevent anyone from trying to force this
// script to open some other page on the internet
if ( isset( $_REQUEST["a"] ) && isset( $_REQUEST["b"] ) ) {
    $url = "https://www.example.com/designTool?a=" . urlencode($_REQUEST["a"]) . "&b=" . urlencode($_REQUEST["b"]);
    $contents = file_get_contents( $url );
    echo $contents;
}

3. 监听iframe消息的JavaScript代码

// usingProxy is defined elsewhere as true if we are using the proxy.php script.
// In case we are NOT using the proxy, I check that the origin is
// the third-party domain. Otherwise, I check that the origin is our domain
window.addEventListener("message", function(event){
    if (
        event.origin === "https://www.example.com" ||
        (
            usingProxy &&
            (window.location.protocol + '//' + window.location.host).indexOf(event.origin) === 0
        )
    ) {
        // ok then, this is our message, go ahead and do stuff with it, close the modal, and stop listening for more messages
    }
});

安全漏洞分析与修复建议

一、PHP代理脚本的风险

  1. SSRF(服务器端请求伪造)风险
    虽然硬编码了第三方域名,但file_get_contents默认会跟随重定向。如果第三方的designTool接口存在跳转逻辑,黑客可构造a/b参数,诱导请求跳转到服务器本地IP或内网服务,进而探测、攻击内部系统。

  2. DoS攻击隐患
    未对请求的资源大小、响应时长做限制。黑客可反复请求大体积资源耗尽服务器带宽,或请求耗时极长的接口占用服务器进程,拖慢整体服务。

  3. 参数校验缺失
    仅检查a/b参数是否存在,未验证参数格式。即使urlencode避免了URL注入,恶意参数仍可能导致第三方返回异常内容,引发前端潜在风险。

二、前端代码的风险

  1. XSS注入风险
    直接用模板字符串拼接proxyURL到iframe的src属性中,若proxyURL包含单引号等特殊字符,会导致属性闭合,触发XSS攻击(比如构造proxyURL为https://example.com/proxy.php?a=' onload='alert(1))。

  2. 消息监听逻辑漏洞
    使用indexOf判断origin的写法存在缺陷:若攻击者构造类似https://www.example.com.attacker.com的域名,indexOf会返回0,误判为可信来源,导致恶意消息被接收,触发后续逻辑操作。

三、修复建议

PHP代理脚本修复

  1. 限制重定向与超时
    配置file_get_contents禁止跟随重定向,并设置超时时间,阻断SSRF路径:
$context = stream_context_create([
    'http' => [
        'follow_location' => false,
        'timeout' => 5
    ]
]);
$contents = file_get_contents($url, false, $context);
  1. 添加资源大小限制
    返回内容前检查大小,超过阈值则拒绝响应:
$maxSize = 10 * 1024 * 1024; // 限制为10MB
if(strlen($contents) > $maxSize) {
    http_response_code(413);
    exit("Request entity too large");
}
  1. 严格校验参数格式
    根据第三方接口要求,对a/b做格式校验(比如字符范围、长度限制):
if(!preg_match('/^[a-zA-Z0-9]{1,32}$/', $_REQUEST['a']) || !preg_match('/^[a-zA-Z0-9]{1,32}$/', $_REQUEST['b'])) {
    http_response_code(400);
    exit("Invalid parameters");
}

前端代码修复

  1. 安全设置iframe的src属性
    改用jQuery的attr方法设置src,避免字符串拼接带来的注入风险:
let $iframe = jQuery('<iframe style="height: 100%; width: 100%; margin: 0; border: none;">');
$iframe.attr('src', proxyURL);
jQuery('<div id="designTool"></div>').append($iframe).appendTo('body').dialog({
    modal: true,
    title: "Design Your Item"
});
  1. 修复origin判断逻辑
    使用全等匹配替代indexOf,确保origin完全一致:
window.addEventListener("message", function(event){
    const ourOrigin = window.location.protocol + '//' + window.location.host;
    if (
        event.origin === "https://www.example.com" ||
        (usingProxy && event.origin === ourOrigin)
    ) {
        // 执行后续操作
    }
});

内容的提问来源于stack exchange,提问作者Mike Willis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 23:25:17