2018年9月25日火曜日

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

エグゼクティブサマリ

PHPの脆弱性CVE-2018-17082はXSSとして報告されているが、現実にはXSSとしての攻撃経路はない。一方、Apacheのmod_cacheによるキャッシュ機能を有効にしているサイトでは、キャッシュ汚染という攻撃を受ける可能性がある。

概要

PHPの現在サポート中のすべてのバージョンについて、XSS脆弱性CVE-2018-17082が修正されました。以下は対応バージョンであり、これより前のすべてのバージョンが影響を受けます。ただし、Apacheとの接続にApache2handlerを用いている場合に限ります。
  • PHP 5.6.38
  • PHP 7.0.32
  • PHP 7.1.22
  • PHP 7.2.10
PHP 5.5以前も対象であり、これらは脆弱性は修正されていません。

脆弱性を再現させてみる

この脆弱性のPoCは、当問題のバグレポートにあります。

PHP :: Sec Bug #76582 :: XSS due to the header Transfer-Encoding: chunked

要約すると、Apacheハンドラを使用しているPHP環境に対して、壊れたchunkedエンコーディングのリクエストを送信すると、リクエストボディの内容がレスポンスにそのまま付加されてしまうというものです。
以下は、サンプルとしてもちいるPHPスクリプトです。拙著「体系的に学ぶ 安全なWebアプリケーションの作り方 第2版」から /31/31-001.php の転用です。

<body>
<?php echo htmlspecialchars(date('G:i')); ?>
</body>
これを以下のURLでアクセスします。88ポートを使っているのは、80ポートだとnginx経由となり、攻撃が刺さらないからです(後述)。
http://example.jp:88/31/31-001.php
このURLによるHTTPリクエストを以下の赤字のように変更します。
GET /31/31-001.php HTTP/1.1
Host: example.jp:88
User-Agent: Mozilla/5.0
Transfer-Encoding: chunked
Content-Length: 32

<script>alert('Hacked')</script>
以下のHTTPレスポンスが返りますが、赤字に示すように、リクエストボディに付加した文字列が追加されています。
HTTP/1.1 200 OK
Date: Sun, 23 Sep 2018 07:32:44 GMT
Server: Apache/2.4.25 (Debian)
X-UA-Compatible: IE=edge
Content-Length: 52
Connection: close
Content-Type: text/html; charset=UTF-8

<body>
16:32</body>
<script>alert('Hacked')</script>
ちなみに、Transfer-Encoding: chunked の場合、正しいリクエストは以下となります。20は16進数ですので、十進数にすると32ということになります。
GET /31/31-001.php HTTP/1.1
Host: example.jp:88
User-Agent: Mozilla/5.0
Transfer-Encoding: chunked

20
<script>alert('Hacked')</script>
0
             (空行)
CVE-2018-17082は、壊れたchunkedエンーコーディングの場合の処理にバグがあり、不正な結果を返すというものです。

CVE-2018-17082はXSSとしては攻撃できない

この脆弱性は元の報告やNVD等ではXSSとして報告されていますが、通常のXSSとは脆性の成り立ちが異なりますし、そもそもXSS攻撃はできません。
XSSとして攻撃するためには、被害者のブラウザから壊れたchunkedエンコーディングのリクエストを送信する必要がありますが、それは不可能です。このため、XSS攻撃はできません。

CVE-2018-17082によるキャッシュ汚染(mod_cache編)

しかし、脆弱性の影響がないわけではなく、キャッシュ汚染という手法が使える場合があります。筆者が調査した範囲では、プロキシサーバー形式のキャッシュサーバーでは影響がなく(後述)、Apacheのmod_cacheを用いたキャッシュ(リバースプロキシではなくApacheのレスポンスをダイレクトにキャッシュする場合)では影響があります。
以下は、キャッシュ汚染の模式図です。


攻撃対象サイト(Target site)は、Apacheとmod_cacheによるキャッシュを備えています。
攻撃者(Attacker)は、仕掛けを含むリクエストを送ると、レスポンスにJavaScriptを含ませることができますが、その際のレスポンスがファイル等にキャッシュされます。一般利用者が、キャッシュの有効期間中に同じURLにアクセスすると、汚染されたレスポンスを受け取ることになります。
攻撃の様子をデモ動画として用意しました。以下は、mod_cahceを用いてWordPressを高速化をしているサイトを想定したものです。




CVE-2018-17082によるキャッシュ汚染(キャッシュサーバー編)

一方、リバースプロキシによるキャッシュサーバーでは影響がないようです。
その理由は、壊れたリクエストを送るとリバースプロキシの時点でエラーになり、リクエストがApacheまで届かないためです。
このパターンについて色々調べてみました。リバースプロキシではエラーにならないが、Apacheではエラーになるパターンがあれば、攻撃できる可能性があります。そのようなパターンとして以下を発見しました。
GET /31/31-001.php HTTP/1.1
Host: example.jp:88
User-Agent: Mozilla/5.0
Transfer-Encoding: chunked

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

このリクエストは、nginxだと、リクエストボディの 5 の後に続く空白以降を無視するので、chunkedエンコーディングとしてバリッドとみなされ、エラーになりません。一方、Apacheだと空白以降を無視しないので、以下のようにエラーになります。
HTTP/1.1 400 Bad Request
Date: Mon, 24 Sep 2018 08:36:24 GMT
Server: Apache/2.4.25 (Debian)
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
<hr>
<address>Apache/2.4.25 (Debian) Server at example.jp Port 88</address>
</body></html>
5 <script>alert('Hacked')</script>
やったーと思いましたが、nginx経由でApacheにリクエストを送信すると、エラーになりません。どうも、nginxがApacheにリクエストを中継する際に、チャンク長 5の後の余計な文字列を除去しているように思います。調べた結果、Apacheにリクエストを中継する際にnginxが冗長なTransfer-Encoding: chunked を除去していることが分かりました。ということで、nginx(他にもsquid、Apache+mod_proxy)によるプロキシサーバー経由では、攻撃を再現させることはできていません。

影響を受けるサイト

当脆弱性が再現するのは Apacheとの接続にApache2handlerを用いていて、以下のPHPバージョンを利用しているケースです。
  • PHP 5.5以前
  • PHP 5.6.37 以前
  • PHP 7.0.31 以前
  • PHP 7.1.21 以前
  • PHP 7.2.9 以前
ただし、Apache + mod_cahce によるキャッシュを用いている場合のみ攻撃経路が判明しています。したがって、mod_cacheによるキャッシュを用いているPHPサイトは至急のバージョンアップまたはパッチ適用を強く推奨します。
その他の場合でも、対象のPHPバージョンを使っている場合、早めの対応を推奨します。

各Linuxディストリビューションの対応

RHEL / CentOS / Debian / Ubuntuの主要Linuxディストリビューションのうち、本校執筆時点では Ubuntuのみが対応を完了しています。Ubuntu 14.04、Ubuntu 16.04、Ubuntu 18.04が対象です。その他のディストリビューションは未対応のようです。

対策

PHPの最新版(5.6以降)をインストールすることで対策となります。Ubuntuの標準パッケージのPHPを使っているサイトは、前述のように、最新のパッチを適用することでも対策になります。
PHPのバージョンアップやパッチ適用が当面できないという場合は、CGIあるいはFast CGIモードでPHPを動かすことでも対策になります。また、HTTPDとしてApacheの代わりにNginx等を用いることでも対策になります。


まとめ

PHP の脆弱性 CVE-2018-17082 について報告しました。
当該脆弱性はXSSとしての攻撃はできませんが、キャシュ汚染としての攻撃が可能であることを示しました。PHPスクリプトの中身によらず攻撃が可能なので、攻撃可能な条件に該当するサイトは即時の対応を推奨します。そうでなくても、該当バージョンのPHPをお使いのサイトは、早めのバージョンアップまたはパッチ適用を推奨します。


免責

このセキュリティ情報は予告なしに改訂される場合がある。このセキュリティ情報を適用した結果について徳丸浩およびEGセキュアソリューションズ株式会社は一切の責任を負わず、利用者の利益のために、あるがままの状態で公開するものである。

PR

【10月24日(水)・11月7日(水)】徳丸本によるホワイトハッカー入門 ~基礎講座・応用講座~ 開講 申し込み受付中

0 件のコメント:

コメントを投稿

フォロワー

ブログ アーカイブ