-
-
[翻译]蓝军测试中PROXY protocol的应用
-
2020-4-7 20:00 7729
-
蓝军测试中PROXY protocol的应用
译者注1:攻防对抗中,关于红蓝军的概念国内外是相反的,故译者会以蓝军替代原文中的red team。
译者注2:PROXY protocol(代理协议),是HAProxy的作者Willy Tarreau开发和设计的一个Internet协议,可用于方便且安全地在复杂网络环境下传输完整的客户端连接信息(源IP、目的IP、源端口、目的端口等)。
最近,我对学习如何在蓝军测试中使用PROXY protocol非常感兴趣。如果读者熟悉可扩展系统的开发或负载均衡的使用,那么可能已经很了解PROXY protocol了。PROXY protocol的基本概念就是负载均衡器会在原始请求前面加上一行PROXY信息,如下所示:
PROXY TCP4 192.168.0.1 192.168.0.11 56324 443\r\n GET / HTTP/1.1\r\n Host: 192.168.0.11\r\n \r\n
各字段详细解释如下:
- PROXY表示PROXY protocol的版本是v1
- TCP4表示TCP协议。TCP4指的是TCP over IPv4,TCP6指的是TCP over IPv6。
- 192.168.0.1表示源IP地址,是原始客户端IP地址。
- 192.168.0.11表示目的IP地址。
- 56324表示源端口
- 443表示目的端口
- \r\n表示PROXY header的结尾
- GET / HTTP/1.1\r\n表示HTTP请求的开始
在传统的HTTP代理应用场景下,负载均衡器会插入包含源IP地址的X-Forwarded-For header。 如果要在使用HTTPS的情况下保留源IP地址,负载均衡器则需要先解密TLS连接,以便插入header,然后再另启一个的TLS连接将其重新加密传输到后端。老实说,大多数情况下不会出问题。
但是在安全攻防场景中,我们会使用“重定向”来替代“负载均衡”的概念。重定向器旨在保护我们的基础设施,但需要注意的是,重定向器可能比其他设施更容易受到威胁。 如果想复现威胁攻击,需要在非主流云服务商的各种服务上使用重定向器。可以考虑我朋友Topher和Mike的sketchyasfuckistan匿名野鸡VPS。
如果你使用野鸡云服务商,你可能不想处理在重定向器失效后转移SSL证书的问题,此外,你可能也不会相信服务器上生成的密钥不会在别的地方有备份,或者你是服务器的唯一拥有者。一般来说,你不会太信任这种服务器,这种情况下可以使用dumb TCP重定向器,bluscreenofjeff在蓝军测试基础设施设计中提到了一些。但是,dump TCP重定向器可能会丢失源IP的信息,一旦流量返回到信任的基础设施后,会影响后续判断。
PROXY protocol会让TLS重定向器保持dumb,而不会丢失客户端连接的信息。只要重定向器和目标服务器支持PROXY,那么就可以保留原始客户端地址。重定向器接收客户端的TLS连接,将header信息添加到TCP数据包之前,然后将其传输到服务器。服务器(存放TLS密钥的服务器)也必须支持PROXY protocol,否则将会报错。
流程图
复现步骤
我应该已经做了充分的解释,对吧?你可能只想看配置的部分,那我们直接跳到那部分,我将根据上图做标记。最近一次测试完成于2020年2月15日,测试环境为nginx version: nginx/1.14.0 (Ubuntu),操作系统是Ubuntu 18.04.4 LTS。
example.com
将DNS记录指向Untrusted Redirector 1的IP地址。在此例中,即192.168.0.4。
@ 300 IN A 192.168.0.4
Untrusted Redirector 1
这是的入口重定向器。恶意流量触达到该重定向器时会暴露IOC。我们不想它存放任何关键信息,并希望它在需要时尽可能容易地调整。它所做的只是监听443端口并指向Untrusted Redirector 2。
创建文件/etc/nginx/stream_redirect.conf
stream { server { listen 443; proxy_pass 192.168.0.3:443; proxy_protocol on; } }
在/etc/nginx/nginx.conf加入下面这一行,并确保它没有被包含在其他代码块中。
include /etc/nginx/stream_redirect.conf
重启nginx,到下一步的Untrusted Redirector 2。sudo systemctl restart nginx。
Untrusted Redirector 2
这是我们的中点重定向器,中点重定向器不是必需的,也可将Untrusted Redirector 1直接指向Trusted Ingress。但是,如果你想将example.com与实际的基础设施分离,那最好还是保留中点重定向器。如果你的基础设施托管在目标环境中,也会非常有用,这对于内部蓝军来说并不罕见,“所有秘密都藏在屋子里”。
创建文件/etc/nginx/stream_redirect.conf
stream { server { listen 443; proxy_pass 192.168.0.2:443; } }
然后像配置之前的重定向器一样,可以添加include /etc/nginx/stream_redirect.conf到/etc/nginx/nginx.conf。或者,可以使用socat或simpleproxy之类的dumb重定向器来代替在此层使用的nginx。该层并不需要知道代理的存在,实际上,如果你尝试在任何中间点上使用proxy_protocol on,可能会导致其失效。
重启nginx,到下一步的Trusted Ingress。sudo systemctl restart nginx。
Trusted Ingress
这是我们的入口系统,TLS终止于此,并且我们处于受信的环境中。example.com的关键信息位于该系统中,并且PROXY也将在此终止。
示例文件/etc/nginx/sites-enabled/example.com.conf:
server { server_name example.com; location / { proxy_pass 192.168.0.1:8080; proxy_set_header X-Forwarded-For $proxy_protocol_addr; } listen [::]:443 ssl ipv6only=on proxy_protocol; # managed by Certbot listen 443 ssl proxy_protocol; # managed by Certbot ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot }
注意在X-Forwarded-For中的$proxy_protocol_addr变量,这是PROXY protocol中的源IP地址,
也将其记录在Trusted Ingress nginx日志中。
/etc/nginx/nginx.conf中的示例代码片段:
[...] http { [...] ## # Logging Settings ## log_format proxy '$proxy_protocol_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent "$http_referer" ' '"$http_user_agent"'; access_log /var/log/nginx/access.log proxy; error_log /var/log/nginx/error.log; [...] }
你可能想仅对Trusted Ingress上的特定站点配置使用代理,需要在/etc/nginx/nginx.conf中保留access_log,并添加access_log /var/log/nginx/example.com.access.log proxy;至/etc/nginx/sites-enabled/example.com.conf。
Downstream Application
如果完全按照此教程操作,则应用程序需要解析X-Forwarded-For header。你可以在nginx层进行客户端IP过滤,将不需要的IP重定向到其他位置,这样的话应用程序甚至不必处理IP。
还有一种方法可以解决此问题,以便应用程序不需要解析X-Forwarded-For header,但是需要另外安装一个nginx模块(ngx_http_realip_module),但它不能作为单独的可安装模块使用,我不想在此文章中涉及有关从源代码构建nginx的整个部分。也许这是另一个帖子的主题。
结论
我不知道蓝军成员是否可以通过其他方式解决此问题,但此文所述的方法是一个很好的解决办法,因为它不需要任何中间服务器保存关键信息或获得授权。从技术上讲,服务器之间不太可能会传输错误的客户端IP地址,但仅在中间使用dumb重定向器,不会引入任何其他问题,因为你只会获得重定向器的IP,并且无法基于此直接做决策。因此,无论如何,还是用PROXY protocol吧。
照例。。。
原文链接:https://0xda.de/blog/2020/02/red-team-proxy-protocol-nginx/
翻译:看雪翻译小组 SpearMint
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。