CODEBLUE CTF 2018 Quals writeups

チームNaruseJunで参加して全体で2361点入れて11位、個人ではWatch CatsにアシストとLittle Riddleを解いて703点入れました。

Watch CatsとLittle Riddleのwriteupを載せます。

Watch Cats

C++で書かれたソースコードコンパイルされたバイナリが与えられる。問題はゲームになっていて下図の様にスタートからゴールまで路が出来るようにジョイントを回転させてケーブルを繋げさせるゲームとなっている。またルールとしてジョイントを回転させることが出来る制限回数が存在する。 フラグを得るためには5つのステージを全て解かなければならない。

初期状態
f:id:kotarou777775:20180729223837p:plain

完成状態
f:id:kotarou777775:20180729223841p:plain

攻略法

ステージ1~4は手動or総当りで現実的な時間で解くことが出来る。

ステージ1

0を押す

ステージ2

0,0,1,1,1,3,5,5,5を押す

ステージ3

0,0,2,4,4,4,6,8を押す。

ステージ4

3,4,4,6,6,9,10,13を押す。

ステージ5

バグをつかないと32番目のジョイントのせいでクリアできない。と言われてここから自分が取り掛かり始めた。 0,1,1,2,2,2,11,11,11,13,15,17,17,17,19,19,19,20,21,21,21,25,25,25,26,30,4,6,6,6,7,7,9を押した後に33を押して32を129回押して次に33を押す。

回転させると該当するジョイントのchar型であるdirectionがインクリメントされオーバーフローすることによって負数になってしまうバグを利用した。通常、ジョイントが持っていたdirection変数は0~3の値を取ることが想定されているが、ジョイントを一度回転させる度に起きる更新処理でスタート地点の0番目のジョイントからケーブルを通じて繋がっていない場合はジョイントのdirecton変数が更新されず、インクリメントし放題になってしまう。適当な回数回転させると32番目のジョイントが全ての方向のケーブルとつながるのでゲームクリアとなりフラグが出てくる。

Little Riddle

RubyのSandbox問
ruby2.2.10でセーフレベル3, Seccompでexecve, forkを禁止した環境下でのフラグの読み出しをする問題。
セーフレベルについてはリファレンスマニュアルを参照したところ自分で入力した文字列や生成されたオブジェクトを引数にしてコマンドを実行やファイルの読み出しが出来ないらしい。
セキュリティモデル (Ruby 2.2.0) また、セーフレベル、Seccompのはなしとは別にARGVがfreezeされているためARGF経由でファイルを読み出すこともできなくなっている。

解法

File.readの引数の変数はtainted?がfalseになるようなものしか入らないのでそのような変数か定数'flag'を探せば良い。

ObjectSpace.each_object {|e|
    if not e.tainted? and e == 'flag'
        p File.read(e)
    end
}
__END__

感想

今までのPwnと少し違う感じがしたのとRubyのsandbox問に苦手意識があったので少し苦戦した気がするが2問だけでも解けてよかった。