HTTP_ORIGIN 的安全性如何?

Posted

技术标签:

【中文标题】HTTP_ORIGIN 的安全性如何?【英文标题】:How secure is HTTP_ORIGIN? 【发布时间】:2011-06-01 18:28:56 【问题描述】:

我想查明来自第三方网站的传入 HTTP_REQUEST 调用是否来自我定义的域列表。

我知道可以使用 HTTP_REFERER 找出第三方域在哪里,但它不够安全。人们可以欺骗它或使用 Telnet 来伪造它。

那么,HTTP_ORIGIN 怎么样?它是从所有浏览器发送的吗?安全吗?

另外,人们可以在 HTTP_REQUEST 调用中伪造 REMOTE_ADDR 吗?

【问题讨论】:

@RichardW11 我在哪里可以找到有关 $_SERVER['ORIGIN'] 的信息?你确定它是正确的? @GianpaoloDiNino 嗨,我删除了我的评论,因为我想澄清一下。那天很忙,评论也不是很准确。这是我所知道的。当我创建一个 javascript api 时,通过一个 php 应用程序连接。 Mozilla 浏览器不接受我的请求。研究时。原来我在寻找 HTTP_ORIGIN,但是浏览器正在发送 $_SERVER[ORIGIN]。为了解决这个问题,我刚刚创建了脚本来查找任一版本。您可以最终验证这一点。它也可能是 Mozilla 的版本。让我知道这是否有帮助。 @RichardW11 我没有找到任何相关信息。我们使用 http_origin + http_host 作为后备。 @GianpaoloDiNino 是的,很奇怪。这是来自 Mozilla 的屏幕截图。 i.imgur.com/9YEvpfj.png 奇怪的是,站点上的其他 javascript 请求没有发送该标头。哪些浏览器会发送 http_host? @GianpaoloDiNino 刚刚加倍检查。在 Mozilla 的网络视图中,它显示 Origin,但事实证明他们只是清理标题以仅显示 Origin。然而,实际上它正在发送 http_origin。感谢挑战。感谢您的帮助。+1 【参考方案1】:

HTTP_ORIGIN 是一种防止 CSRF(跨站请求伪造)请求的方法。目前它仅由 Chrome 实现(截至 2011 年 11 月)。我测试了 Firefox 和 Opera,但都失败了。

它在请求头中的名字是Origin。在我的 PHP 脚本的服务器上,我在 $_SERVER 数组中将其视为 HTTP_ORIGIN。此标头仅在某些情况下发送,当需要针对 CSRF 进行保护时(仅 POST 就足够了)。以下是所有请求的列表,无论是否设置:

https://wiki.mozilla.org/Security/Origin

锚标记 - 否 窗口导航 - 否 IMG - 否 iframe、嵌入、小程序 - 是 表单(GET 和 POST)- 是 脚本 - 是的 样式表 - 否 样式表的依赖加载 - 否 重定向 - 是 XHR - 是的

不幸的是,Origin 标头仅在 Chrome 中实现。它于 2010 年 1 月在 Google Chrome 的博客上首次公布:

http://blog.chromium.org/2010/01/security-in-depth-new-security-features.html

通过 Origin Header 进行 CSRF 保护

Origin 标头是一项新的 HTML5 功能,可帮助您保护您的网站免受跨站请求伪造 (CSRF) 攻击。在 CSRF 攻击中,恶意网站(如攻击者.com)指示用户的浏览器向目标服务器(如 example.com)发送 HTTP 请求,从而使 example.com 服务器迷惑执行某些操作。例如,如果 example.com 是一个网络邮件提供商,那么 CSRF 攻击可能会欺骗 example.com 将电子邮件消息转发给攻击者。

Origin 标头通过识别生成请求的网站来帮助网站防御 CSRF 攻击。在上面的示例中,example.com 可以看到请求来自恶意网站,因为 Origin 标头包含值 http://attacker.com。要将 Origin 标头用作 CSRF 防御,站点应仅在响应以下请求时修改状态:(1) 缺少 Origin 标头或 (2) 具有带有白名单值的 Origin 标头。

我只是在我的PHP脚本中实现CSRF保护,我个人使用Chrome,所以对我来说已经足够了,我希望其他浏览器能尽快赶上Chrome。

有趣的是,Mozilla 发明了该安全功能,您可以在其网站上阅读大量关于 Origin 标头的文档,但他们仍然没有时间实施它;-)

HTTP_ORIGIN 似乎只包含protocoldomain,末尾没有斜线: “http://www.example.com” - 即使您从“http://www.example.com/myform/”提交表单。

PHP 脚本中针对 CSRF 的简单保护:

if ($_SERVER['REQUEST_METHOD'] == 'POST') 
    if (isset($_SERVER['HTTP_ORIGIN'])) 
        $address = 'http://'.$_SERVER['SERVER_NAME'];
        if (strpos($address, $_SERVER['HTTP_ORIGIN']) !== 0) 
            exit('CSRF protection in POST request: detected invalid Origin header: '.$_SERVER['HTTP_ORIGIN']);
        
    

此脚本仍可升级以支持 80 以外的端口(Origin 包含与 80 不同的端口)、HTTPS 连接以及从不同子域提交表单(例如 sub.example.com => 将请求发送到www.example.com)。

【讨论】:

请注意,我的 Mac Chrome 18.0 在标头中显示“Origin”而不是“HTTP_ORIGIN”。 @MauvisLedford:你的意思是服务器端?该代码是 php,因此“HTTP_ORIGIN”可能仅是 php。原始标题应为“Origin”。该代码是用 Apache 服务器测试的,某些 $_SERVER 键可能在其他服务器上丢失或不同。 检查 Origin 标头有助于防止 XSRF,但不能提供完整的保护。请注意,您报告没有为 IMG 标签设置 Origin 标头,这意味着攻击者可以使用它来攻击您的网站。你还说你只使用 Chrome。重要的是您的用户使用的浏览器。请参阅j.mp/learn-xsrf,了解如何全面保护您的应用。 @Vroo 没有人说这是对所有人的全面保护。仅当您不遵循良好做法时,IMG 标签才能用于攻击。您绝不应该允许通过 GET 请求修改敏感数据。 我添加了评论,因为我认为阅读您评论的人可能认为检查 Origin 就足够了。我不是说你这么想。安全错误通常是由开发人员没有充分遵循良好实践引起的。例如,当缺少 Origin 标头时,允许通过 GET 请求修改数据以及 XSRF 保护不足 = 漏洞。【参考方案2】:

HTTP_ORIGIN 既不是所有浏览器都发送的,也不是安全的。

浏览器发送的任何内容都不能被认为是安全的。

【讨论】:

浏览器在加强网络安全方面发挥着至关重要的作用。如果您信任浏览器,则可以信任他们发送的HTTP_ORIGIN。在某些情况下,您不想信任任何随机 HTTP 客户端。在这种情况下,您的评论适用。浏览器中的任何内容都不可信。 @Manki 你永远不能相信浏览器。 @ceejayoz 您可以依靠浏览器最好地代表用户。它不会保护 you 免受用户的侵害,但与 HTTPS 结合使用时,它可以帮助保护开发人员和用户免受第三方的侵害(例如 CSRF/会话劫持)。 @erb 如果为真(您仍然必须不信任用户/浏览器输入)则毫无意义,无论如何都是假的。浏览器可能感染了恶意软件,从而发送用户不知道的恶意请求。 @ceejayoz 我知道还有更多的作用,我从来没有说过将它用于 CSRF 保护之外的任何其他事情是一个好主意。我只是不喜欢像“浏览器发送的任何内容都不能被认为是安全的”这样的笼统陈述,因为它对于 CSRF 保护肯定是安全的,这完全取决于你用它做什么。我不是说服务器应该信任浏览器,我说如果用户使用安全浏览器,那么服务器可以使用它来保护 user 免受攻击。当用作启发式时,我仍然同意该陈述,但我觉得它有点粗糙。抱歉,如果我不必要地吹毛求疵。【参考方案3】:

这里的人们认为这一切都是错误的——“CORS”标准并不是这样服务器就不会被黑客入侵,即使它除了它的作用之外还有助于这一点。目的是让“浏览器”有办法缓解违反同一来源策略的请求。如果客户端和服务器在同一个页面上,那么'CLIENT'可以决定是否允许请求。

显然,通过让服务器参与您在安全过程中提供帮助的决策。

但它不会保护服务器免受未经授权的访问 - 这就是密码和 cookie 的用途。

客户端可以是(正如有人提到的)一个 telnet 工具,其中制作的每一件东西都是假的。

但是 Chrome 和 FF 等的卖点之一是,它们会通过不允许 Javascript 进入同源沙箱之外来帮助您,这意味着默认情况下唯一可以妥协的东西是在“攻击者”自己的网站上。或其他决定不安全的网站。

CORS 技术可以让您说——嘿,我希望用户能够在他们使用的其他网站上通过 javascript 使用我的时髦服务。所以我要将此站点添加到我的例外中。这意味着您正在帮助您的授权用户在该特定站点的浏览器安全性中戳一个漏洞。这意味着黑客可以利用的漏洞。因此,您在设置服务时很小心,对吧?

这意味着任何未设置 CORS 的网站默认情况下都可以通过兼容浏览器的跨站脚本安全保护(当然,排除错误和黑客攻击)。浏览器会询问该服务是否要参与源站的javascript,如果跨站说“我对这个该死的站点一无所知”,则浏览器的javascript引擎将关闭连接并转储数据。

总结一下——CORS 并不能帮助您确保安全。它可以帮助您在浏览器能力上打一个洞,使用户更安全。但希望以一种有管理的方式..并且仅适用于特定网站..

【讨论】:

【参考方案4】:

HTTP 是一种纯文本协议。 ENTIRE 请求头/正文结构可以伪装成你想要的任何东西。

【讨论】:

HTTPS 怎么样?它是否也适用于通过 HTTPS 提供服务的网站?【参考方案5】:

HTTP 请求中的所有内容都可以伪造。

【讨论】:

除了 REMOTE_ADDR 不是 HTTP 协议的一部分,使用 HTTP 时不能有效地伪造。 @MichaelBorgwardt 代理呢? @nasirbest 在那种情况下也不是假的,请求确实来自代理。代理从其他地方转发请求超出了这个问题的范围,并且与请求由运行在服务器上的浏览器实例完成但由坐在完全前面的用户通过 VNC 控制的情况没有真正的不同。不同的计算机。【参考方案6】:

升级:

function isOriginAllowed($incomingOrigin, $allowOrigin)

    $pattern = '/^http:\/\/([\w_-]+\.)*' . $allowOrigin . '$/';

    $allow = preg_match($pattern, $incomingOrigin);
    if ($allow)
    
        return true;
    
    else
    
        return false;
    


$incomingOrigin = array_key_exists('HTTP_ORIGIN', $_SERVER) ? $_SERVER['HTTP_ORIGIN'] : NULL;
    $allowOrigin    = $_SERVER['HTTP_HOST'];

    if ($incomingOrigin !== null && isOriginAllowed($incomingOrigin, $allowOrigin))
    
        exit("CSRF protection in POST request: detected invalid Origin header: " . $incomingOrigin);
    

示例:

http://media.mydomain.com 是的 http://offline.mydomain.com 是的 http://domen1.mydomain.com 是的 http://domen_1.mydomain.com 是的 http://domen-1.mydomain.com 是的 http://ololomydomain.com 错误 http://mydomain.com 是的 http://pro.mydomain.com 是的 http://super.pro.mydomain.com 是的 http://super.pro.fakemydomain.com 错误 http://pro.fakemydomain.com 错误

【讨论】:

【参考方案7】:

更新,截至 2021 年:

HTTP_ORIGIN 几乎被所有浏览器完全支持,请参阅: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin#browser_compatibility

【讨论】:

以上是关于HTTP_ORIGIN 的安全性如何?的主要内容,如果未能解决你的问题,请参考以下文章

http_origin 可以被欺骗吗?

$_SERVER['HTTP_ORIGIN'] 不起作用

Nginx配置origin限制跨域请求(应对等保)

php:跨域

如何确保OA系统的安全性?

08.如何保证API接口的安全性问题01