KOSENセキュリティコンテスト 2017 Write-Up
PwnPwnPain(元EagleJump(元Harekaze))でKOSENセキュリティコンテスト 2017に参加してきました。結果は4位で2800点でした。そのうち自分が関わった900点についてのWrite-Upです。
ボスを倒せ - Binary 200
[Description]
とあるゲームを見つけたのだが、ボスがあまりにも強すぎて一切倒せそうにない。
どうにか倒す方法はないだろうか?
[Netcat]
nc score.kosensc2017.tech 40048
ユーザー名を入力し、その後自動で戦闘が進むプログラムだった。
20文字入力したら自分のHPが変動したので、どれくらいでオーバーフローするんだろうと思って8文字くらい入力したらボスのHPが30くらいになって何故か勝てた。奇跡。
FLAG: SCKOSEN{buffer_over_flow!}
簡単な符号化2 - Crypto 100
[Description]
ファイルからフラグを探せ
[Problem File]
https://score.kosensc2017.tech/contents/problem/6/binary
Base64エンコードされたものが渡されるため、とりあえずデコードするとバイナリのような物が出てきた。
これをバイナリエディタに貼り付けてfileコマンドやbinwalkで調べてみたりするが何も引っかからず悲しかった。
現段階でのファイルのシグネチャを見るとKPだったので、KPってなんだよ~って思って調べていたが何も見つからず。
家にお持ち帰りして深夜4時にこれリトルエンディアンではとひらめきCyberChefで変換すればシグネチャがPKなおなじみのバイナリが出てきた。(KPの時点でリトルエンディアンに気づくべきだった。)
jaganikuman$ file export export: Zip archive data, at least v2.0 to extract
zipを解凍したら以下のようにwordなファイルが沢山出てきたため、拡張子をzipからdocxに変えてwordで開いてFLAG獲得。
jaganikuman$ unzip export Archive: export inflating: _rels/.rels inflating: word/document.xml inflating: word/styles.xml inflating: word/_rels/document.xml.rels inflating: word/settings.xml inflating: word/fontTable.xml inflating: docProps/app.xml inflating: docProps/core.xml inflating: [Content_Types].xml
FLAG: SCKOSEN{TEXT_BUT_NOT_PLAIN}
ファイル送信pcap - Network 200
[Description]
これはファイルを送受信しているpcapです
[Problem File]
https://score.kosensc2017.tech/contents/problem/19/file.pcap
Lenna.png
とlock.zip
をPOSTしているpcapが与えられた。
lock.zip
にはLenna.png
とflag.txt
が入っていた。
pcapからLenna.png
とlock.zip
を取り出すと、zipにはパスワードが掛かっていた。
自分はLenna.png
にSteganoとかでパスワードが埋まっているんだろうと思ってstegano-lsbなど色々試したが、無理だった。
そこで、zipの中に入ってるLenna.png
が与えられているため、この事に着目して考えたら以下の記事に出会い、選択平文攻撃で出来そうと分かった。
Blog: 年越しCTF x86-64.jp大会 2014 を開催しました – x86-64.jp - くりす研
あとはチームメイトの@ushikenに投げてFLAG獲得。
FLAG: SCKOSEN{k_p_t_a}
灯台下暗し - Web 100
[Description]
パスワードを奪取せよ。
[Web Server]
http://score.kosensc2017.tech:40052
ログインフォームがあるWebページを与えられるが、その下にHintとしてphpのソースが乗っていた。
$try = false; $login = false; if( isset($_POST[‘name’]) && isset($_POST[‘password’])){ $name = htmlspecialchars($_POST[‘name’], ENT_QUOTES); $password = htmlspecialchars($_POST[‘password’], ENT_QUOTES); $db = new SQLite3(‘data.db’); $stmt = $db->prepare(“SELECT name FROM users WHERE name = ? AND password = ?“); $stmt->bindValue(1, $name, SQLITE3_TEXT); $stmt->bindValue(2, $password, SQLITE3_TEXT); $rows = $stmt->execute(); $row = $rows->fetchArray(); $try = true; $login = $rows && $row[‘name’]; $db->close(); }
sqliteのDBファイルを読み込んでいるので、このファイルが公開ディレクトリに設置されてて落とせるのではと思ってhttp://score.kosensc2017.tech:40052/data.db
にアクセスしたところ、ダウンロード出来た。
hintで与えられたソースに$stmt = $db->prepare(“SELECT name FROM users WHERE name = ? AND password = ?“);
とあるので、sqlite3でselect * from users;
でFLAG獲得。
jaganikuman$ sqlite3 data.db SQLite version 3.13.0 2016-05-18 10:57:30 Enter ".help" for usage hints. sqlite> select * from users; admin|SCKOSEN{database_bukkonuki!}
FLAG: SCKOSEN{database_bukkonuki!}
Web1 - Web 200
[Description]
no description.
[Web Server]
http://score.kosensc2017.tech:40050
難読化されたJavaScriptが読み込まれたWebページが与えられる。つまり難読化を読み解いていけと言うことですね。
___ = window; __ = document; s = “shift”; m = [“addEventListener”, “DOMContentLoaded”, “createElement”, “div”, “textContent”, “deobfuscate js and find the key”, “body”, “appendChild”, “length”, “join”, “forEach”, “parseInt”, “toString”, “toUpperCase”]; __[m[s]()](m[s](), ()=>{ _ = __[m[s]()](m[s]()); _[m[s]()] = m[s](); __[m[s]()][m[s]()](_); (()=>{ __ = [18234125, 323835316891, 11523, 907531478812, 744387234, 44203240442235, 844002446169231, 4601, ]; ____ = { _: m[s](), ___: m[s]() }; ____.__ = `____`[[____._]]; __[m[s]()]((n,_)=>{ __[_] = `${___[m[s | s]](n, _ + 1)[m[s ^ s ^ 1]](0O22 << 1)[m[-~-~s]]()}{${n}}`; if (__[_][____[“_”]] > 4) __[_] = Array(__[_][____[“_”]])[____[“___“]](“_”); } ); } )(); } , false);
アンダースコアを文字に置き換えて多少読みやすくした。
c = window; b = document; s = “shift”; m = [“addEventListener”, “DOMContentLoaded”, “createElement”, “div”, “textContent”, “deobfuscate js and find the key”, “body”, “appendChild”, “length”, “join”, “forEach”, “parseInt”, “toString”, “toUpperCase”]; b[m[s]()](m[s](), ()=>{ a = b[m[s]()](m[s]()); a[m[s]()] = m[s](); b[m[s]()][m[s]()](a); (()=>{ b = [18234125, 323835316891, 11523, 907531478812, 744387234, 44203240442235, 844002446169231, 4601, ]; d = { a: m[s](), c: m[s]() }; d.b = `d`[[d.a]]; b[m[s]()]((n,a)=>{ b[a] = `${c[m[s | s]](n, a + 1)[m[s ^ s ^ 1]](0O22 << 1)[m[-~-~s]]()}{${n}}`; if (b[a][d[“a”]] > 4) b[a] = Array(b[a][d[“a”]])[d[“c”]](“a”); } ); } )(); } , false);
これを自分に読み解いていくのは無理だと思ったので、各計算後に変数の内容をデバッグしていった。そうしたらFLAGが出た。難読化厳しい。
b[a] = `${c[m[s | s]](n, a + 1)[m[s ^ s ^ 1]](0O22 << 1)[m[-~-~s]]()}{${n}}`; console.log(b[a]);
FLAG: SCKOSEN{44203240442235}
通信を解析しろ - KoH 30
[Description]
pcapファイルを解析して、隠されたサービスを発見しろ。
[Problem File]
https://score.kosensc2017.tech/contents/problem/12/hoge.pcap
[Server Address]
http://10.201.1.102
13万パケットある12.4MBのpcapが渡された。
まず、pcap内からボーナスFLAGをチームメンバーの@tamanekoが見つけてくれた。
FLAG: SCKOSEN{p0rtkn0cking}
portknockingという事だったので、明らかにポートノッキングしてそうな通信が合ったためそれを再現してknockして、sshにアクセスしたり8081にアクセスしたりしてみるも何も返答がなかった。
競技終了後の解説を聞くとノックするポートは2つだけだったり、ノック後にアクセスする場所は443だったり、色々見当違いで悲しかった。
感想
今の自分には難易度的にはちょうどよい大会だった。
ただ、1日目後半にファイルシステムの500点問題が追加され、独自ファイルシステムの解析が出来ず上位3チームと綺麗に500点分差が生まれてしまった。
今回の負けの原因は完全にこのファイルシステムの問題なので、早いうちに各プロのWrite-Upを参考にしながら解いて力にしていきたい。