AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 1168972
Accepted
Ami Heines
Ami Heines
Asked: 2024-12-17 15:55:09 +0800 CST2024-12-17 15:55:09 +0800 CST 2024-12-17 15:55:09 +0800 CST

如果主机标头与 Apache 中的请求 URL 不同,如何拒绝主机标头?

  • 772

我有一个 Apache/2.4.6 (CentOS) 服务器,其中有多个子域作为 Apache VirtualHost 中的 ServerAlias。

类似于:

<VirtualHost *:443>
  ServerName mydomain.com
  ServerAlias a.mydomain.com
  ServerAlias b.mydomain.com

每个客户公司都应通过其子域进行访问,并且为了安全起见,每个客户公司都有不同的数据库,数据是分离的。

一位网络安全专家提醒我,存在一个漏洞,一个子域“a.mydomain.com”的用户可以通过在从客户端到 Web 服务器的调用中添加 Host 标头来访问另一个子域“b.mydomain.com”。

一开始我尝试用 PHP 获取信息,但失败了,PHP 没有获取到 headers 信息。然后我转而寻找在 Web 服务器级别(Apache)上解决此问题的方法。

当恶意用户试图欺骗服务器并使用主机头将请求发送到另一个子域时,我想要检测并拒绝,在此示例中,用户应该由 a.mydomain.com 而不是 b.mydomain.com 提供服务:

curl 'https://a.mydomain.com/users/login' \
  -H 'Host: b.mydomain.com' \
  --data-raw $'{"email":"[email protected]","password":"*****"}'

来自客户端应用程序的正常调用如下所示:

curl 'https://a.mydomain.com/users/login' \
  --data-raw $'{"email":"[email protected]","password":"*****"}'

我尝试过RequestHeader unset host,但是它并没有像我预期的那样工作。

我的预期是,如果恶意用户发送了“Host”标头,服务器应该会忽略它。这将导致上述两个 culr 调用实际上相同。

我认为发生的情况是 Apache 在调用中使用了 URL,但是如果存在“Host”标头,则它将优先使用并且使用该标头,而 URL 中的原始域将被丢弃。

如果是这种情况,则RequestHeader unset host不会向我的 PHP 代码发送任何主机,这会导致我的代码中断,因为它需要知道哪个客户公司正在调用它。

apache2
  • 2 2 个回答
  • 271 Views

2 个回答

  • Voted
  1. Best Answer
    grawity
    2024-12-17T17:40:03+08:002024-12-17T17:40:03+08:00

    这没有意义,因为HostApache 首先通过标头来了解 URL。

    常规 HTTP 请求不会向 Web 服务器提供文字 URL。如果您使用-v选项运行 curl,您会看到请求看起来像GET /users/login,即仅存在路径(和查询字符串)——它可能与您想象的不同 GET https://a.mydomain.com/users/login。(代理使用后者,普通请求不使用。)

    那么,当发出 HTTP 请求时,URL 的主机名部分会去哪里呢?就 HTTP 而言,它唯一Host:去的地方是标头。因此,标头不可能“不同于请求的 URL”,因为它就是请求的 URL。

    换句话说,更改 Host 标头实际上并不比更改 URL 更能“欺骗服务器”;只需这样做https://b.mydomain.com/users/login就会产生同样的效果。

    可能还有一些其他问题“专家”试图警告您(例如,也许他们正在谈论尝试发送两个Host 标头的请求,我相信 Apache 和 PHP 都已经对此进行了防范;或者也许他们的意思是服务器接受不匹配的 TLS SNI 和 HTTP Host,这本身也不是什么大问题),但您需要向他们寻求澄清。


    我大胆猜测,您的应用程序不会按域隔离 PHP 会话(或身份验证令牌),因此,如果用户登录并收到域 A 的会话 cookie(或访问令牌),但随后尝试发送域 B 的相同令牌,则应用程序会接受它作为域 B 的有效身份验证。这将是一个重大的安全问题,但与欺骗 Host 标头无关。

    现在,PHP确实知道它被调用的是哪个域($_SERVER["SERVER_NAME"]和/或$_SERVER["HTTP_HOST"]- 前者来自 Apache,后者实际上是标Host:头;PHP 实际上通过字段接收所有标头HTTP_*),所以如果我猜对了,那么可能需要存储这些字段并将其与 PHP 会话进行比较(或与您发布的任何 JWT 的受众或您用于身份验证的任何其他内容进行比较)。

    但同样,这只是一个猜测,你应该请专家为你提供更具体的解释,说明它们的真实含义。

    • 11
  2. Ferrybig
    2024-12-18T00:45:15+08:002024-12-18T00:45:15+08:00

    您误解了这里的漏洞,以顶部帖子中的示例为例:

    curl 'https://a.mydomain.com/users/login' \
      -H 'Host: b.mydomain.com' \
      --data-raw $'{"email":"[email protected]","password":"*****"}'
    

    这将通过 SNI 向服务器进行身份验证a.mydomain.com,然后发送主机头b.mydomain.com。

    Apache 默认会检测到这种情况,将错误记录到日志文件并返回 400 错误。

    通过 SNI 提供的主机名...和通过 HTTP 提供的主机名...不同

    另请参阅: https: //security.stackexchange.com/questions/134021/what-kind-of-attack-is-prevented-by-apache2s-error-code-ah02032-hostname-prov

    Apache 在变量中公开检测到的 SNI 的结果SSL_TLS_SNI

    请注意,您正在使用ServerAlias而不是为每个服务器创建单独的块。如果 SNI 告知它已连接到a.example.com,然后发送 Host 标头b.example.com,因为从 apaches 的角度来看,它是允许请求的同一台服务器。

    您希望拆分每台服务器,以确保 Apache 能够检测到 SNI 和主机头的不匹配。您可以使用块Include来加载通用配置文件,这样您就不必重复

    • 6

相关问题

  • 使用本地 IP 地址访问本地网络上服务器的 Web 服务器

  • 如何转发来自我的网络服务器的请求?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve