42

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

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

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

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

4

7 回答 7

62

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

它在请求标头中的名称是Origin. 在我的 PHP 脚本的服务器上,我看到它就像HTTP_ORIGIN$_SERVER数组中一样。此标头仅在某些情况下发送,当需要针对 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似乎只包含protocoland domain,末尾没有斜杠:“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)。

于 2011-11-10T22:26:44.757 回答
32

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

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

于 2010-12-30T21:27:18.413 回答
16

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

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

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

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

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

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

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

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

于 2015-10-11T02:07:02.370 回答
15

HTTP 是一种纯文本协议。可以伪造整个请求标头/正文结构来说出您想要的任何内容

于 2010-12-30T21:28:48.983 回答
8

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

于 2010-12-30T21:28:07.710 回答
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 错误
于 2012-09-26T10:42:31.767 回答
0

更新,截至 2021 年:

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

于 2021-11-12T15:33:21.813 回答