前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >反向代理的攻击面 (下)

反向代理的攻击面 (下)

作者头像
随心助手
发布2019-10-15 00:55:40
1.6K0
发布2019-10-15 00:55:40
举报

让我们接着上节的内容,继续探讨。建议读者先阅读第一部分,这将有助于理解本节的内容。

服务端攻击

请求错误路由

例子2

这是关于Nginx的一个“bug”,准确的说它只是Nignx正常工作导致的(因此不会被修复)。

首先,服务器配置的规则为location /to_app,即/to_app是作为后面添加字符的前缀。因此,/to_app,/to_app/,/to_app_anything(包括特殊符号)都可以通过该规则。并且,/to_app后面的字符将被提取并与proxy_pass联合(解析)起来。 Nginx处理完/to_app_anything后,其转发(到后端服务器)的请求格式为http://server/any_path/_anything

location /to_app {
proxy_pass http://server/any_path/;
}

如果将这些特性结合起来,可以发现我们可以遍历后端服务器的所有位置。只需发送这样的请求:

GET /to_app../other_path HTTP/1.1

解释:首先/to_app与Nginx规则相匹配,然后Nginx提取出../other_path,再与proxy_pass/any_path/相结合,最终转发的请求为:http://server/any_path/../other_path。当后端服务器解析完毕后,我们就能够进入想要的目录。

例子3

在上篇文章开头,我已经介绍了反向代理服务器会根据主机头来转发请求至后端。

这里我使用Haproxy来举个例子。我将Haproxy配置为所有主机头为example1的请求都将转发至名为example1_backend192.168.78.1:9999的后端服务器。

frontend http-in
acl host_example1 hdr(host) -i example1.com
use_backend example1_backend if host_example1
backend example1_backend
server server1 192.168.78.1:9999 maxconn 32

对于这样的配置,攻击者似乎无法再访问后端的其他服务器?其实不然,攻击者可以轻易突破防线。因为Haproxy 不支持Absolute URI(上篇文章中介绍过了),然而大部分web服务器都支持此协议。当Haproxy 收到包含Absolute URI的请求时,它不会对Absolute URI做任何处理,直接转发至后端。因此,我们可以发送以下请求来访问其他后端服务器。

GET http://unsafe-value/path/ HTTP/1.1
Host: example1.com

那么,我们可以通过反向代理来访问其后端的任意服务器?其实在大多数情况下(Nginx, Haproxy, Varnish),这并不能轻松实现,但是Apache(某些版本)则可以。Apache从ProxyPass“解析”提取主机值,因此我们可以发送类似GET @evil.com HTTP/1.1的请求,Apache将其视为http://backend_server@evil.com,然后请求evil.com(你知道的,这可以导致SSRF攻击)。这里有一个此类攻击的例子。

客户端攻击

其实你再回过头细想方向代理的特性,你会发现只要与响应相关,就会有潜在的客户端攻击向量。由于浏览器在发送请求前通常会做一些处理,因此这类攻击有一些额外的限制,这将导致服务器会有非预期的表现。

浏览器处理

在一次客户端攻击中,攻击者需要强制受害者浏览器发送一个特殊的请求,然后服务器做出响应。但是,浏览器会遵循一些规范来处理路径,然后再发送请求。浏览器会解析该URL(例如抛弃fragment部分),对某些必要的符号进行URL编码处理(或许不会),然后在使路径变得规范化。因此,我们要想实施这种攻击,我们只能发送一个“有效”的请求。该请求必须切合这三个组件(浏览器,反向代理,后端服务器)。

当然,不同浏览器的实现(请求)存在差异,再加上一些特性上的区别,可以使我们找到一个切合点:

  • 例如,Chrome和IE不会解码%2f,因此它们将不对/path/anything/..%2f../这样的路径做规范化处理。
  • 在规范化处理之前,老版本的Firefox不做URL解码,但现在它和Chrome有类似的工作方式。
  • Safari不对路径做URL解码处理,因此我们可以强制(浏览器)原封不动地发送/path/%2e%2e/another_path/
  • 说起IE,它还是一如既往的奇特。如果主机头为本地地址,那么它不会对路径做任何处理。

滥用标头修改功能

对于反向代理服务器来说,增添,删除和修改后端请求中的标头是一项基本功能。有些情况在,这比修改后端本身简单的多。有时,反向代理会添加一些重要的安全标头。作为攻击者的我们,想要利用这些规则来使反向代理服务器做出错误的响应(通过滥用后端位置标头),从而攻击其他用户。

假如我们使用Nginx作为代理,Tomcat作为后端。Tomcat默认设置了X-Frame-Options: deny标头,所以浏览器无法将其嵌入frame中。由于某些原因,Tomcat web应用的一个组件(/iframe_safe/)必须通过iframe访问,因此Nginx配置中删除了X-Frame-Options标头。然而,为了服务器为了防范clickjacking(点击劫持)攻击,做了iframe_safe设置:

location /iframe_safe/ {
proxy_pass http://tomcat_server/iframe_safe/;
proxy_hide_header "X-Frame-Options";
}
location / {
proxy_pass http://tomcat_server/;
}

其实,作为攻击者的我们可以构造符合Nginx的iframe_safe规则,又能被后端Tomcat解析为完全不同的(访问)位置:

<iframe src="http://nginx_with_tomcat/iframe_safe/..;/any_other_path">

浏览器不会对其做规范化处理。这又符合Nignx的iframe_safe规则。Tomcat支持路径中插入参数,取/any_other_path。所以在这样的配置下,通过frame可以访问Tomcat的所有位置,这将导致clickjacking(点击劫持)攻击。

做一些思维发散,我们可以利用它来滥用其他安全有关的标头(例如:CORS, CSP)。

缓存

缓存是最有趣的攻击向量之一,对于各类攻击都有很好的开发潜力。但是在反向代理领域利用缓存(攻击的方法)仍然鲜为人知。最近,与缓存相关的攻击越来越受关注了,网上有一些很酷的研究例如Web缓存欺骗和实用的Web缓存中毒。在本篇文章中我也关注到了缓存:我想要分析出缓存的各种实现,从而有助于研究出缓存欺骗和缓存中毒攻击的方法。

它是如何工作的

我将介绍一些反向代理中关于缓存的要点,这将帮助你理解这类攻击。

实现缓存的方式很简单。在某些情况下,一台反向代理服务器会将来自后端的响应存储到缓存中,以后直接调用缓存而不用访问后端服务器。一些反向代理服务器默认支持缓存,另一些则要求用户自行配置。一般来说,反向代理服务器会使用缓存标志,该标志与请求的主机头值和路径相关联。

反向代理对某个响应缓存与否,它会先检查请求中的Cache-ControlSet-Cookie标头。反向代理不会对存在Set-Cookie标头的请求做任何缓存,但是对于Cache-Control有些不同。它会将其视为缓存策略,请求额外的解析。Cache-control标头框架非常复杂,但是有基本的功能标志,例如决定是否缓存,设置缓存时限等。

Cache-control标头形式有下面这些:

Cache-Control: no-cache, no-store, must-revalidate
Cache-Control: public, max-age=31536000

第一个是禁止反向代理缓存,第二个相反。Cache-control标头滥用是允许反向代理储存响应。

大量的web服务器,应用服务器和框架自动且正确地设置Cache-control标头。在大部分情况下,如果web应用的某个脚本使用了session功能,那么该应用会严格设置Cache-control标头的缓存功能,因此如遇到这种情况,开发者不需要考虑(安全)。然而有例外,例如,如果web应用使用它自己的session安全机制,Cache-control标头可能会存在漏洞。

攻击

反向代理的一个常用功能是“积极缓存”(这不是官方词汇,但可以描述其作用)。在一种情况下(后端严格限制,完全不允许缓存),管理员没有修改后端,而是修改反向代理规则,修改严格的Cache-control标头从而开启了缓存响应。这时,管理员一般都会错误设置。例如,只缓存响应中某些扩展名(.jpg, .css, .js)或者某个路径(/images/)。

如果是这种情况,攻击者可以创建符合反向代理规则又被后端误判的路径。

这里还是Nginx+Tomcat的组合。下面这条规则强制使Nginx缓存Tomcat上/images目录的所有响应。

location /images {
proxy_cache my_cache;
proxy_pass http://tomcat_server;
proxy_cache_valid 200 302 60m;
proxy_ignore_headers Cache-Control Expires;
}

作为攻击者,我们可以滥用该规则,从而实现web缓存欺骗。只需受害者打开下面的这个URL(例如使用img)。

<img src="http://nginx_with_tomcat.com/images/..;/index.jsp">

然后受害者的浏览器将发送请求(携带经认证的cookie)。Nginx发现请求中存在/image,于是直接转发该请求值Tomcat,然后缓存响应(Tomcat->Nginx,此时Cache-Control标头无效)。Tomcat在处理时将甄别出/index.jsp,因此攻击者可以强制Nginx缓存任何页面,攻击者仅需更改路径/images/..;/index.jsp从而盗取受害者的敏感数据(例如token->csrf攻击)。

这看起来只是一个web缓存欺骗的变种,但其实不然。

让我们来考虑缓存中毒攻击。此类攻击依赖于在请求中找到未加密的值(标头),这将显著地影响(从安全角度)接下来的响应,但是在这里,这个响应必须由反向代理服务器缓存,同时Cache-Control标头应当设置为允许。如果我们把所有东西中和起来,我们能够找出一些方法来造成缓存中毒攻击。

让我们想象一下这个场景。有一台Nuster(基于Haproxy的缓存代理)服务器和一个web应用。这个web应用上的/account/attacker有一处self-XSS漏洞(只在攻击者自己的账户上触发)。Nuster配置了缓存web应用上/img/目录的所有响应。

nuster cache on
nuster rule img ttl 1d if { path_beg /img/ }

攻击者仅需构造特殊URL/img/..%2faccount/attacker/,Nuster将会应用“积极缓存”规则,这时web应用返回self-XSS响应(可以看到存在/account/attacker/)。这个带有XSS Payload的响应将被Nuster缓存,因此攻击者结合XSS与缓存滥用来攻击该应用的用户。这就是从self-XSS到正常XSS的一种方法。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 nginx遇上redis 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 服务端攻击
    • 请求错误路由
    • 客户端攻击
      • 浏览器处理
        • 滥用标头修改功能
          • 缓存
            • 它是如何工作的
              • 攻击
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档