どうも、非想定解太郎と申します。InterKosenCTF 2020 に出題した問題の題意や解法についての記事です。
出題された問題はこちらのリポジトリから見ることができます。
ptr-yudaiの作問writeup記事
- [web] matsushima2 (121pts / 46 solves)
- [web] miniblog (353pts / 14 solves)
- [web] just sqli (383pts / 11 solves)
- [reversing] harmagedon (182pts / 36 solves)
- [crypto] ciphertexts (201pts / 33 solves)
- [crypto] bitcrypto (326pts / 17 solves)
- [crypto] padding oracle (326pts / 17 solves)
- [crypto] padrsa (426ps / 7 solves)
- 作問の感想・反省
[web] matsushima2 (121pts / 46 solves)
SECCON 2018 Finalで出題された松島、という問題が強烈に印象に残っていたのでオマージュ問題です。松島はポーカーだったので、ではということでブラックジャックを実装して*1その後で脆弱性を決定しました。
この問題はJWTで状態(スコアや使ったトランプ)を維持しているのですが、過去のCookieを保存しておいて負けたら巻き戻すということをやると負けをなかったことにして勝つまで試行することができます。という簡単な問題でした。
かなり簡単でwarmupにふさわしい難易度、解かれ具合だと思います。
ptr-yudaiによるwriteup
[web] miniblog (353pts / 14 solves)
Webはよくわからないのでとりあえず脆弱性から決めようと思ってSSTIでRCEをすることに決めました。テンプレートがインジェクションできる状況を都合よく作るためにファイルアップロード時のtarの解凍時のzip slipのような脆弱性を使ってもらうことにしました。問題をちゃんと読めばある程度やることはわかるんじゃないかなと思っています。
ただ、テンプレートをエディットできるということで'{%'のようなパターンは正規表現で弾いていたのですが、途中に改行文字を挟むことでこのチェックをすり抜けることができてしまいました。甘かったです……。
また、問題公開時はtypoによりマルチスレッドが有効になっておらず、問題サーバが重たくなってしまって競技者の皆さんにはご迷惑をおかけしました。
ptr-yudaiによるwriteup
[web] just sqli (383pts / 11 solves)
問題名の通り、ただSQL Injectionをするだけの問題です。miniblogよりはかなり簡単だと思うのですが、問題公開のタイミングなどもあってsolve数は思ったほどではなかったですね。この問題では自明なSQL Injectionが存在しているのですが、SELECT
だけは正規表現で弾かれています。問題の要求を考えるとUNION SELECT
をして行を追加したいところなのですが、SELECT
が使えないと困ってしまいます……というところで sqlite.org を見に行くと、UNION VALUES (v1, v2, ...)
という記法が使えることがわかり、解けます。
何かSQLの面白い仕様を使った問題が出来ないかと考えてドキュメントを見ていたら知らない仕様に出会ったので問題にしました。今回はSELECT
が使えない状況でしたが、同様の要求に対して、UNION
を使わずに解く方法がないか模索中です。
ptr-yudaiによるwriteup
[reversing] harmagedon (182pts / 36 solves)
かなり良く解かれた問題です。ただコンパクトなバイナリがあって、アセンブリをちゃんと読むと4分木を辿ってあるノードにたどり着けるような経路を見つければ勝ちです。想定解法は4分木を葉から根に向かって辿るだけ、という感じでしたが、全探索でも解けるようです。
もともとはもっと大きな、それこそGB単位のバイナリでptr-yudaiに怒られたので頑張ってコンパクトにしました。それっぽい文字列を作るように選択肢を選んでも解けないことはないと思いますが、Ruktun0rDi3
をそれっぽいと感じるのはむずかしいと思います。これは問題を作っているときに平沢進にはまっていたせいでこういう名前になりました。
ptr-yudaiによるwriteup
[crypto] ciphertexts (201pts / 33 solves)
Cryptoのwarmup問題です。かなり簡単にしたつもりでしたがharmagedonやlimitedよりも全然解かれていないんですね。
問題は単純で、というようにそれぞれの剰余でフラグをRSA暗号化しただけです。RSA暗号運用でやってはいけない n のこと #ssmjp を読んでいれば、としてCommon Modulus Attackをすれば良さそうということがわかりますし、あるいはを求めてからとして [tex: cd \mod r] を計算することでもフラグが得られそうだとわかります。
ptr-yudaiによるwriteup
[crypto] bitcrypto (326pts / 17 solves)
xorに関する準同型性という珍しい性質を持つ、Goldwasser-Micali cryptosystemに関する問題ですが、多くの方はこの暗号の名前にはたどり着かずに自力で暗号を解析してそのような性質があることを突き止めたようです。解法は簡単で最初に短いとはいえ好きな文字列を暗号化してくれるので、これで0, 1に対応する暗号文を手に入れて準同型性を使って0, 1に対応することなる暗号文を量産するだけです。量産はわりと雑にできるので、解けるなら何でも良いと思います。
ただしこの問題にも非想定解、というか作問ミスがありました。問題中では len(m) > 8
となるような入力に対してエラーを返すことで送った文字列を並び替えて暗号文を作る、ということを禁じたのですが、少ない文字数で多くのバイト数を持つ、非asciiな範囲の文字列を送ることでチェックを無効化できたようです。ごめんなさい。
yoshikingによるwiteup
[crypto] padding oracle (326pts / 17 solves)
最近ではPadding Oracle Attackもptrlibに収録されるなどして解きやすくなっていますが、原理を理解していますか、という問題です。 Padding Oracle Attackを用いるような問題で使われているパディング方法は PKCS#7 というやつですが、 PKCS#7 では末尾に与えられるパディングがこの問題では先頭につく、という改変を加えています。これで特に難しくなるということはなく、通常のPadding Oracle Attackでは後ろからやっていたことを、前からやるように組み替えるだけで解けるのですが、苦戦された方もいたようです。
サーバが遠い場所にあってネットワークが遅くなりがちなのにタイムアウトを短く設定していたり、平文を長くしていたりして、すみませんでした*2
yoshikingによるwriteup
[crypto] padrsa (426ps / 7 solves)
cryptoのボス問題のつもりで作成しましたが、作問ミスによりそんなに難しくなかったようです。問題としては、平文にパディングを付与してRSA暗号化することでhastad's broadcast attackのような手法を抑止しているというものです。ただ、paddingが小さいので小さい平文を小さいeで暗号化してもらえばsmall public exponent attackでpaddingに使われている乱数を求めることができ、Franklink-Reiter Related Message Attackが適用できるようになります。
というのが想定解法でしたが、パディングの作り方が雑だったこともあり、128回ほど暗号化をした場合にパディングに乱数の影響が現れず、hastad's broadcast attackが成立してしまっていたようで、主にこの方法で解かれていたようでした。これならまあ謝ることはないのでしょうが、個人的には手痛いミスです。
ptr-yudaiによるwriteup
作問の感想・反省
自信をもって面白い問題を作っていたつもりで、その実作問ミスや非想定解がぽこぽこ見つかるのは本当に滑稽で、思い込みの激しさやチェックの杜撰さが露わになった感じがあります。ただ、作問ミスでこんなに凹んでいるのも私だけで、評価としては概ね良かったのもなんだかもにょっとしています。