Web安全-HTTP Host头攻击

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Web安全-HTTP Host头攻击

文章目录
漏洞背景
漏洞危害
密码重置
基础案例
注入覆盖
缓存污染
基础分析
实际案例
进阶危害
绕过访问控制
SSRF Attack
漏洞检测
基础检测
进阶挖掘
漏洞修复
漏洞背景
Host 首部字段是 HTTP/1.1 新增的,旨在告诉服务器,客户端请求的主机名和端口号,主要用来实现虚拟主机技术。

运用虚拟主机技术,单个主机可以运行多个站点。以下图为例,hacker 和 usagidesign 两个站点都运行在同一服务器A上,不管我们请求哪个域名,最终都会被解析成服务器 A 的 IP 地址,这个时候服务器就不知道该将请求交给哪个站点处理,因此需要 Host 字段指定请求的主机名。

我们访问 hacker 域名,经 DNS 解析,变成了服务器 A 的 IP,请求传达到服务器A,A接收到请求后,发现请求报文中的 Host 字段值为 hacker,进而将请求交给 hacker 站点处理。

漏洞危害
为了方便获取网站域名,开发人员一般依赖于请求包中的 Host 首部字段。例如,在 php 里用_SERVER["HTTP_HOST"]。但是这个 Host 字段值是不可信赖的(可通过HTTP代理工具篡改),如果应用程序没有对 Host 字段值进行处理,就有可能造成恶意代码的传入。

很多应用是直接把这个值不做 HTML 编码便输出到了页面中,比如:

<link href="http://_SERVER['HOST']" (Joomla)
1
还有的地方还包含有 secret key 和 token:

(Django, Gallery, others)
1
这样处理问题一般会很容易遭遇到两种常见的攻击:缓存污染和密码重置。缓存污染是指攻击者通过控制一个缓存系统来将一个恶意站点的页面返回给用户。密码重置这种攻击主要是因为发送给用户的内容是可以污染的,也就是说可以间接的劫持邮件发送内容。

密码重置
根据 HTTP Host 头攻击的攻击特点,它被广泛应用于密码重置中毒:攻击者可以操纵网站在重置密码情况下生成的密码重置链接,使其发送攻击者指定的域下,利用此来窃取重置任意用户密码的令牌。

常见的一个重设密码(忘记密码)功能的大致流程如下:

用户输入其用户名或电子邮件地址,然后提交密码重置请求;
该网站检查该用户是否存在,然后生成一个临时的、唯一的、复杂的令牌,该令牌与后端的用户帐户相关联;
该网站向用户发送一封电子邮件,其中包含用于重置其密码的链接。重置令牌的参数包含在相应的URL中:https://normal-website.com/reset?token=0a1b2c3d4e5f6g7h8i9j;
当用户访问此URL时,网站将检查提供的令牌是否有效,并使用它来确定要重置哪个帐户。如果一切都符合,则可以进入用户重置密码步骤。最后,令牌被销毁。
以上步骤的安全性依赖于:只有目标用户才能访问其电子邮件,从而可以访问其唯一的令牌。密码重置中毒是窃取此令牌以更改另一个用户密码的一种漏洞。

如果网站重置密码的流程完全依赖用户的可控输入(如HTTP Host头),这可能导致密码重置中毒:

攻击者获取受害者的用户名或者电子邮件,作为提交重置密码的请求,攻击者会拦截重置密码的请求并修改 HTTP Host 头为其指定的域,如evil-user.net;

受害者会收到一封重置密码的邮件,但由于攻击者修改了 Host 头,而 web 程序生成重置链接又完全依赖于 Host 头,导致生成以下URL:https://evil-user.net/reset?token=0a1b2c3d4e5f6g7h8i9j;

如果受害者点击了该链接,重置密码的令牌就会发送到攻击者的服务器 evil-user.net 上;

当攻击者获取到重置密码的令牌之后,就会进行相应的构造访问真实重置密码的 URL 进行密码重置。

下面会通过两个具体的案例演示以上攻击场景。

基础案例
详细了解了上面的密码重置中毒的流程和原理之后,这里通过 HTTP Host 头攻击导致的基础的密码重置中毒来演示。

1、首先输入用户名或者用户的电子邮箱来重置指定用户的密码:

2、提交之后,会发送一封重置密码的电子邮件到 wiener 用户的邮箱中(数据包如右图):
3、注意重置密码的链接,可能是受Host头的值的影响?我们来验证一下是否存在 HTTP Host 头攻击,修改 Host头 的值为 baidu.com:

4、以上结果证明请求是可以被后端服务器接收的,所以是存在 HTTP Host 头攻击的。这里就输入受害用户 carlos 进行重置密码,然后抓包将 Host 头的值改为我们自己的服务器:

5、然后在我们自己的服务器上就可以通过访问日志看到被窃取的重置密码 Token:
6、然后根据已知链接规律,构造重置密码的链接:

https://ac651f551e5317b8800207bd008f000f.web-security-academy.net/forgot-password?temp-forgot-password-token=00YIexUDyNLEJkaBXDoCILWtZAGaxgi7
1
7、随即进入输入新密码的界面,密码重置中毒成功:

注入覆盖
有时候直接修改 Host 头、添加重复 Host 头的值以及混淆 Host 头都不行:
可以尝试使用与Host头功能相同的 HTTP 字段,如 X-Forwarded-Host、X-Forwarded-For 等,可以进行 Fuzz:
实际上他能够被 X-Forwarded-Host 字段影响,导致 Host 头攻击,当同时添加多个字段使请求被拦截时,可以尝试类似排除法、二分法来排查哪个字段有效。

对受害用户 carlos 进行密码重置投毒:
然后构造链接即可:

缓存污染
基础分析
通过 Host header 来污染缓存的攻击方法最初是 Carlos Beuno 在2008年提出来的。但是在现在的网络架构中,这种攻击还是比较困难的,因为现在的缓存设备都能够识别 Host。比如对于下面的这两种情况他们绝对不会弄混淆:

GET /index.html HTTP/1.1 > GET /index.html HTTP/1.1
Host: example.com > Host: evil.com
1
2
因此为了能使缓存能将污染后的 response 返回给用户,我们还必须让缓存服务器看到的 host header 和应用看到的 host header 不一样。

比如说对于 Varnish(一个很有名的缓存服务软件),可以使用一个复制的 Host header。Varnish 是通过最先到达的请求的 host header 来辨别 host 的,而 Apache 则是看所有请求的 host,Nginx 则只是看最后一个请求的 host。这就意味着你可以通过下面这个请求来欺骗 Varnish 达到污染的目的:

GET / HTTP/1.1
Host: example.com
Host: evil.com
1
2
3
应用本身的缓存也可能受到污染。比如 Joomla 就将取得的 host 值不经 html编码便写进任意页面,而它的缓存则对这些没有任何处理。比如可以通过下面的请求来写入一个存储型的 xss:

GET / HTTP/1.1
Host: cow"onerror='alert(1)'rel='stylesheet'
1
2
响应其实已经受到污染:

<link href="http://cow"onerror='alert(1)'rel='stylesheet'/" rel="canonical"/>
1
这时只需要浏览首页看是否有弹窗就知道缓存是否已经被污染了。

实际案例
当存在 Host头 攻击的 Web 站点不存在密码重置的功能的时候,此时该漏洞就显得没有影响,因为不可能驱使用户去抓包修改 Host 头,辅助攻击者完成一系列的攻击。但是,如果目标站点使用 Web 缓存,则可以通过缓存投毒给其他用户提供带有病毒的缓存响应。此时的 Host 头攻击漏洞转变为类似 XSS 存储型类的漏洞。

构造 Web 缓存投毒攻击的步骤:

需要寻找映射到其他用户请求的缓存键;
下一步则是缓存此恶意响应;
然后,此恶意缓存将提供给尝试访问受影响页面的所有用户。
1、寻找Host头攻击点

通过对站点的主页添加重复的 Host 值,可以达到覆盖的效果,并验证存在 Host 头攻击:

2、寻找是否使用了Web缓存

缓存键是什么?从上图中也可以发现,站点使用了 Web 缓存功能,并且配合 Host头 攻击,可以缓存 /resources/js/tracking.js 资源文件。

3、构造恶意资源文件

在攻击者服务器上创建一个同名的 /resources/js/tracking.js 资源文件,内容为:alert(document.cookie);。然后通过 Host 头注入攻击者服务器域名,可以看到在响应中正确地对应了我们的 /resources/js/tracking.js 资源文件:
4、进行缓存投毒

发送多次请求,使该请求的响应变为缓存:
当其他用户请求站点主页时,服务端就会提供该恶意缓存给用户,造成缓存投毒。

进阶危害
绕过访问控制
出于安全考虑,通常网站对某些功能的访问限制为内部用户使用。但是通过Host头攻击一定可能上可以绕过这些限制。对于一个站点,从发现 Host 头攻击到利用,下面来展示一个完整的流程:

1、访问主页,随意修改 Host 的值:
【注意】这里的 Host 的值不会出现响应包中,但是依然可能存在 Host 头攻击,因为响应依然成功,说明服务端没有对 Host 头做验证。

2、寻找敏感页面,通过 /robots.txt 知道 /admin 为做了访问控制的页面(根据错误信息提示,/admin 页面只允许本地用户访问):
3、将 Host 改为服务端内部地址,从而绕过 IP 访问控制:

SSRF Attack
Host 头攻击可能会导致基于路由的 SSRF 攻击,称为:Host SSRF Attack。经典的 SSRF 攻击通常基于 XXE 或可利用的业务逻辑,将用户可控的 URL 作为 HTTP 请求发送;而基于路由的 SSRF 依赖于云部署的体系结构中,包括负载均衡和反向代理,这些中间件将请求分配发送到对应的后端服务器处理,如果服务端未校验 Host 头转发的请求,则攻击者可能会将请求发送(重定向)到体系中的任意系统。

这可能需要知道内部系统的IP地址(私有地址),一般可以通过信息收集或者 Fuzz 来判断有效的私有IP地址(如枚举192.168.1.1/16)。

下面来看一个实际案例,普通方式访问不到 /admin 页面(404):
猜测 /admin 存在于内网中,需要内网机器才能访问,但是配合 Host 头攻击+SSRF 可以绕过并访问。

1、判断Host是否被使用,可用 DNSLog 外带

这里我使用 Burp 自带的 “Burp Collaborator client” 来实现外带:
说明服务端是根据 Host 头的域名来请求资源的。

2、基于 Host 头的 SSRF 探测内网主机

假如一些敏感的页面(比如管理页面),深处于内网,外网无法访问,但是通过 Host 头攻击+ SSRF 可达到绕过访问控制,从而访问内网资产,这里 Fuzz 内网的IP的C段为 192.168.0.0/24,直接利用 Intruder 枚举:
得到内网IP为 192.168.0.240:

最后构造 /admin 页面,在 Host 处换位内网IP:

漏洞检测
基础检测
Host 头攻击漏洞的检测比较简单,只需要抓包,修改 Host 字段值,提交,查看响应中是否包含修改后的 Host 字段值即可。下面我分三个场景,介绍一下Host头攻击漏洞存在的表现。

1、跳转

【场景一】正常请求,响应302,Location 首部字段指明跳转的地址,其中 Location 字段值为 Host 字段指定的地址。

将请求包的 Host 字段值修改为 www.baidu.com 提交,响应包中的 Location 地址也被更改为 www.baidu.com。

2、拼接

【场景二】正常请求,正常响应,将 Host 字段值拼接到标签属性值中。

将请求包的 Host 字段值修改为 www.baidu.com 提交,发现服务器将 www.baidu.com 拼接到了 script 标签的 src 属性值中。

3、代码注入

【场景三】这其实也属于拼接,只不过在场景二的基础上写入了恶意代码。

利用 Host 字段写入 script 标签,弹出警告框。

进阶挖掘
如何发掘 HTTP Host 头攻击?首先要判断服务端是否检测 Host 头?检测完了是否还使用Host头的值?

通过修改 Host 的值,如果服务端返回错误信息:
则说明服务端检测了 Host 的内容。至于有没有使用 Host 头的值,有以下几种方法去发掘:

1、修改Host值

简单的来说,可以修改 HTTP 头中的 Host 值,如果观察到响应包中含有修改后的值,说明存在漏洞。

2、添加重复的Host头

添加重复的 Host 头,通常两个 Host 头之中有一个是有效的,可以理解为一个是确保请求正确地发送到目标服务器上;另一个则是传递 payload 到后端服务器中。

GET /example HTTP/1.1
Host: vulnerable-website.com
Host: attackd-stuff
1
2
3
3、使用绝对路径的URL

尽管许多请求通常在请求域上使用相对路径,但是也同时配置了绝对URL的请求。

GET https://vulnerable-website.com/ HTTP/1.1
Host: attack-stuff
1
2
4、注入覆盖 Host 头的字段

与 Host 头功能相近的字段,如X-Forwarded-Host、X-Forwarded-For等,这些有时候是默认开启的。

GET /example HTTP/1.1
Host: vulnerable-website.com
X-Forwarded-Host: attack-stuff
1
2
3
诸如此类,还有其他的字段:

X-Host
X-Forwarded-Server
X-HTTP-Host-Override
Forwarded
1
2
3
4
5、忽略端口仅校验域名

当修改、添加重复 Host 头被拦截的时候,可以尝试了解 Web 应用程序是怎样解析 Host 头的。比如,一些解析算法会忽略 Host 头中的端口值,仅仅校验域名。这时候可以将 Host 修改为如下形式:

GET /example HTTP/1.1
Host: vulnerable-website.com:attack-stuff
1
2
保持域名不变,修改端口值为非端口号的其他值(非数字), 将 Host 头攻击的 payload 放在端口值处,同样能进行 Host 头攻击。

漏洞修复
最简单的方法是避免在服务器端代码中完全使用Host头,可以只使用相对URL。其他方法包括:

1、正确配置绝对域名URL

当必须使用绝对域名 URL 时,应在配置文件中手动指定当前域的 URL,并引用配置的值,而不是从 HTTP 的 Host头中获取。这种方法可防止密码重置的缓存投毒。

建议对 Host 字段进行检测,检测应用是否在请求目标站点时返回的 URL 是直接将 Host 头拼接在 URI 前。

Nginx,修改 ngnix.conf 文件,在 server 中指定一个 server_name 名单,并添加检测。
Apache,修改 httpd.conf 文件,指定 ServerName,并开启 UseCanonicalName 选项。
Tomcat,修改 server.xml 文件,配置 Host 的 name 属性。
Web应用程序应该使用SERVER_NAME而不是host header。在 Apache 和 Nginx 里可以通过设置一个虚拟机来记录所有的非法 host header。在 Nginx 里还可以通过指定一个 SERVER_NAME 名单,Apache 也可以通过指定一个 SERVER_NAME 名单并开启 UseCanonicalName 选项。

不要使用类似JSP中request.getServerName( )方法引用客户端输入的 hostname 值。拼接生成 URL 时引用静态变量定义的服务器域名,或者使用相对路径生成URL。

2、白名单校验Host头的域

如果必须使用 Host 头,需要正确校验它的合法性。这包括允许的域,并使用白名单校验它,以及拒绝或重定向对无法识别的主机请求。这包括但不仅限于单个 Web 应用程序、负载均衡以及反向代理设备上。

3、不支持主机头覆盖

确保不适用与 Host 头功能相近的字段,如X-Forwarded-Host、X-Forwarded-For等,这些有时候是默认开启的。

值得一提的是,不应该将内网使用的 Host 主机(不出网)与公网的应用程序托管在同一个服务器上,否则攻击者可能会操纵 Host 头来访问内部域。
————————————————

                        版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_39190897/article/details/103594695

目录
相关文章
|
4天前
|
缓存 安全 应用服务中间件
Web安全-HTTP Host头攻击
Web安全-HTTP Host头攻击
21 7
|
27天前
|
开发者 安全 SQL
JSF安全卫士:打造铜墙铁壁,抵御Web攻击的钢铁防线!
【8月更文挑战第31天】在构建Web应用时,安全性至关重要。JavaServer Faces (JSF)作为流行的Java Web框架,需防范如XSS、CSRF及SQL注入等攻击。本文详细介绍了如何在JSF应用中实施安全措施,包括严格验证用户输入、使用安全编码实践、实施内容安全策略(CSP)及使用CSRF tokens等。通过示例代码和最佳实践,帮助开发者构建更安全的应用,保护用户数据和系统资源。
38 0
|
27天前
|
开发者 前端开发 Apache
【绝不错过!】揭秘Wicket大神级插件,带你飞越编程极限,探索Web应用开发新大陆!
【8月更文挑战第31天】Apache Wicket是一个成熟的Java Web框架,以其组件化体系结构、直观的API及对MVC的支持著称。其活跃社区贡献了大量插件和扩展,显著提升了Wicket的功能性。本文推荐几个实用插件,如**Wicket Ajax Support**,可轻松添加Ajax功能,提升用户体验;**Bootstrap for Wicket**则将Bootstrap与Wicket结合,美化应用界面。
29 0
|
27天前
|
SQL 安全 JavaScript
深入剖析Blazor应用的安全性:从常见Web攻击谈起与传统Web应用的对比与防护策略
【8月更文挑战第31天】本文探讨了Blazor应用的安全策略,通过与传统Web应用的安全措施进行比较,详细分析了如何防范常见的网络攻击。首先介绍了Blazor框架如何通过其基于组件的模型和服务器端DOM控制来减少跨站脚本攻击的风险;接着讨论了使用ORM工具如Entity Framework来预防SQL注入攻击的方法;最后分析了跨站请求伪造攻击,并说明了在Blazor应用中如何利用AntiforgeryToken增强安全性。尽管Blazor提供了许多内置的安全防护,但开发者仍需结合良好的编程习惯来全面保护应用。
30 0
|
1月前
|
Linux Python
【Azure 应用服务】Azure App Service For Linux 上实现 Python Flask Web Socket 项目 Http/Https
【Azure 应用服务】Azure App Service For Linux 上实现 Python Flask Web Socket 项目 Http/Https
|
Web App开发 前端开发
|
Web App开发 前端开发 测试技术
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
一、迁移步骤 1.首先安装最新版本gitlab(gitlab7.2安装) 2.停止旧版本gitlab服务 3.将旧的项目文件完整导入新的gitlab   bundle exec rake gitlab:import:r...
705 0
|
Web App开发 前端开发 Java
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
 Connection reset by peer的常见原因: 1)服务器的并发连接数超过了其承载量,服务器会将其中一些连接关闭;    如果知道实际连接服务器的并发客户数没有超过服务器的承载量,看下有没有网络流量异常。
852 0
|
Web App开发 存储 前端开发
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont
NoSuchObjectException(message:There is no database named cloudera_manager_metastore_canary_test_db_hive_hivemetastore_df61080e04cd7eb36c4336f71b5a8bc4) at org.
1072 0
|
Web App开发 前端开发 数据库

热门文章

最新文章