読者です 読者をやめる 読者になる 読者になる

はちゅにっき

こっちのブログはまったり更新

本当に PHP の DoS 脆弱性 (CVE-2015-4024) キツくない?

hakaikosen.hateblo.jp
上記記事を「あら大変(棒読み)」とか思いながら読んでいたけれど、PHPBTS の方を読んでみたら確かに原理から再現手順まで細かく記載されていて
「なんかこれまずそう」と思ったので、docker を使って検証してみることに。


PHP 入りの Docker コンテナは、Official のものを利用しました。registry.hub.docker.com

今回の脆弱性、POST しないページには関係ないのかな?と思ってましたが、よくよく見ると PHP さえ動くページであればなんでもいいらしい。
ということで以下のような PHP ファイルを用意し、ここにアクセス (攻撃) をします。

  • htdocs/index.php
<!DOCTYPE html>
<html>
  <head>
    <title>PHP Bugs #69364</title>
  </head>
  <body>
    Hello, World!
  </body>
</html>

ごらんの通り拡張子こそ .php となっているものの、ただの HTML です。
攻撃側のコードは以下の通り。今回は PHP脆弱性を突くために Perl でかきます。深い意味はありません。
BTS を見ればすぐに分かるけれど、念のため攻撃の核心となる部分は伏せておきます。

  • bin/attack.pl
#!/usr/bin/env perl
use strict;
use warnings;
use feature qw/ say /;
use Furl::HTTP;
use Time::HiRes qw/ gettimeofday tv_interval /;

sub attack
{
    my $url      = shift;
    my $body     = "<<< ここが攻撃部分 >>>";
    my $furl     = Furl::HTTP->new(agent => 'PHP-Bugs/69364', timeout => 100);
    my $start    = [ gettimeofday ];
    my @response = $furl->post($url, [
        'Content-Type' => 'multipart/form-data; boundary=xYzZY'
    ], $body);

    say 'Status: ', join(' ', $response[1], $response[2]);
    say 'Elapsed time: ', tv_interval($start);
}

attack($ARGV[0]) if scalar @ARGV == 1;

準備ができたら docker コンテナを起動します。
まずは脆弱性対応が完了している、最新の PHP 5.6.9 から。

$ docker run -d -v $PWD/htdocs:/var/www/html -p 8080:80 php:5.6.9-apache
$ ./bin/attack.pl http://docker-vm:8080/
Status: 200 OK
Elapsed time: 0.134595

なんの問題もなく、0.1 秒程度でレスポンスが反ってきました。
続いて脆弱性が残っている 5.6.8。

$ docker run -d -v $PWD/htdocs:/var/www/html -p 8080:80 php:5.6.8-apache
$ ./bin/attack.pl http://docker-vm:8080/
Status: 200 OK
Elapsed time: 30.050448

なんとレスポンスが帰ってくるまで 30 秒かかりました。
その間 CPU の使用率は 100% に張り付き、見事攻撃に成功しました。
ちなみに、サポートが切れている PHP 5.3 でも再現することが確認できました。

$ docker run -d -v $PWD/htdocs:/var/www/html -p 8080:80 php:5.3-apache
$ ./bin/attack.pl http://docker-vm:8080/
Status: 200 OK
Elapsed time: 30.053104

というわけで、今回の脆弱性はそもそもの PHP のリクエストを処理するロジックに問題があるため、たとえ POST を処理しないページであっても危険だということがわかりました。
今回は手加減してリクエストを送りましたが、リクエストヘッダをもう少し凶悪にして、スレッド・プロセスを使ってより多くのリクエストを送りつければ、簡単に DoS 攻撃が成立するのではないでしょうか。
ね、簡単でしょ?

って話しを会社の人にしたら「ふーん」っていう感じの返事がきて「さすが PHP の人は鍛えられているな」と思いました。
1ヶ月後くらいに騒ぐのかな?それとも何事もなかったかのように沈静化するのかな。