ふるつき

v(*'='*)v かに

SECCON国内大会 参加記

 毎度のことながらSECCONは解けなさすぎてwriteupではなくて参加記になります。

 今年もまたSECCON国内大会にinsecureという命名センスが飛んでいったチームで参加しました。今年もまた連携大会を通しての出場で、KOSENセキュリティコンテストでの優勝によるもので、SECCON Onlineも良いところまでは行ったのですがxor32か何かの実装を間違えていてだめでした。ゆるさないぞWikipedia(英)。チームメイトはKOSENセキュリティコンテストのまま、ptr-yudai, yoshiking, thrust2799です。

 今年のSECCONはこれまでとはいろいろ違っていて、例えば会場とかがそうですが、最も困ったのが旅費支援でした。SECCON決勝大会は今まで大変気前よく我々の交通費や宿泊費を支援してくれていたのですが、今年からは連携大会を通じての参加チームはそれがなく、各連携大会側で出すかどうかを決めてくださいということでした。この情報が公式からは中々出されなかったことと、KOSENセキュリティコンテストの運営母体であるK-SECに伝わっていなかったことでいろいろ混乱しました。K-SECにお願いしたところ、報告書の提出によって旅費を支援していただけることになったのですが、どの程度出してもらえるかなどの情報がなく困ってしまいました。困っている間に電車は埋まるしホテルは高騰するんですよね。

競技について

 今年はinsecure初の快挙として「上から数えたほうが早い順位」におさまることができました。それもなんと5位で、こんなに良い成績をおさめられて感無量です。下に順位表を貼っておきます。

f:id:Furutsuki:20181223202307p:plain

 この成績のほとんどはptr-yudaiによるものなのですが、問題の感想と私の働きについて少しだけ書いておきます。

宮島(コードゴルフ問題)

 まずこのわかりにくい名前をやめてくれ。去年も府中とかなんとかで大変ややこしかったのを憶えているぞ。

 さてこの問題はptr-yudaiが解いていました。x86-64アセンブリを書く問題で、例えば int f(int a, int b) { return a/b; } と同等である関数の機械語を提出します。実行結果が正しければAttackフラグを得られ、更に最短ならばDefense Keywordを書き込むことができます。このような問題が30分ごとに合計12問あり、それぞれのAttackFlagは50点でした。

 問題自体はさほど難しくないと言うかABCで言えばPracticeにあたる感じで、ptr-yudaiも無事550点を入手していました。ただしコードゴルフ点は1点たりとも入れられませんでした。できて最短のものと同等で、提出のタイミングも敵わず。上位チームが強すぎました。

 この問題での私の貢献は最初のAttack Flagを入れたことで、これはptr-yudaiがAttack Flagのルールを把握していなかったか、ショートコーディングに凝っていて不安になったのでAttack Flagだけでも私が提出したやつです。ショートコーディングについても意見を出しましたが、どうやっても最短よりは短くなりませんでした。

天橋立XSS HELL)

 XSS HELLでいいだろ。

 各チームがHTMLとpayloadを提出でき、サーバ側のスクリプト/?encodeURI(payload)にアクセスします。結果として alert('XSS') が実行されればその提出は受理されます。このようにして受理された問題は他チームが解けるようになっていて、他チームはpayloadに当たる部分を提出してalert('XSS')を実行させます。このようにして解かれていない問題があるチームにDefense Pointが分配される仕組みでした。

 私の貢献は主にこの問題についてで、最初はルールがわからなかったのですが他チームの提出からチーム内では最速でルールを理解しました。ルールを把握してすぐに「payloadのハッシュをとって比較して alert(XSS)呼ぶだけで誰にも解けないのでは」と思い実装にうつりました。JavaScriptは標準でハッシュ関数を用意していないらしく困った挙げ句、以下のようなものをStackOverflowから戴いてきました。ちなみにpayloadはWEAREINSECUREです。

<script type="text/javascript">  
 
function h(hoge) {
 var hash = 0, i, chr;
 if (hoge.length === 0) return hash;
 for (i = 0; i < hoge.length; i++) {
   chr   = hoge.charCodeAt(i);
   hash  = ((hash << 5) - hash) + chr;
   hash |= 0; // Convert to 32bit integer
 }
 return hash;
};
if ( h(decodeURIComponent(location.search.substr(1))) === 1952217986 ) {
 alert('XSS');

}
</script>

ところがその頃にはすでにyharimaチームのsha256スクリプトが出回っており、insecureは一歩出遅れた感じになりました。結局この問題は各チームがsha256ハッシュをやるだけになってしまいゲームバランスが崩壊、なかよくDefense Pointを1点か2点程度稼ぐだけになりました。独自の難読化をしていたのはinsecureとTeamEnuくらいだったと思うのですが、insecureのハッシュは短かったので途中で破られ、TeamEnuのスクリプトもyharimaの人が1時間くらいかけて解析したようです。私もTeamEnuのスクリプトは解けないかと思って見ていたのですが早々に諦めてしまいました。ちゃんと解析して解いたyharimaの人はすごい。

 お昼ごろまではDefense KeywordのPostが自動化できないかと思ってrequestsを書いていたのですがうまく行かず、途中から最後まではyoshikingが手作業でDefense Keywordを書き換えてくれました。

松島(ポーカー)

 ポーカーをやって、フルハウスがでるとAttack Flag 100点、4カード以上で300点+Defense Keywordが書き込み可能という問題でした。この問題に関しては私は何もしていなくて、yoshikingが遊んでいたらフルハウスがでて100pt入れたのと、公開されていたカードの分配バイナリをptr-yudaiが丁寧に解析して4カードを当てたので終わりです。

 カードのシャッフルはsrand(time(NULL))rand()で1秒ごとに行われていたので当てるのはそんなに難しくないのですが、一度はtimeの値をいじろうとしていました。私はその時にLD_PRELOADで差し替えるための共有ライブラリを書く程度のことしかしておらず、しかもそれは結局使いませんでした。

その他の貢献

 Defense Keywordをとってくるスクリプトを書きました。ブラウザからとってくるのは大変なので、その部分の動作を解析して、常に最新のフラグが得られるポートを立てました。不思議なことにこちらからリクエストをした場合に降ってくるDefense Keywordと時間経過でpushされてくるDefense Keywordが異なっており*1、これに気がつくまでは毎回WebSocketを立ててリクエストしていたので間違ったフラグをチームメイトに配ってしまっていました。反省

const fs = require('fs')
const socket = require('socket.io-client')('ws://score.ja.seccon:8000');


socket.on('connect', () => {
        socket.on('flagword', (msg) => {
                for (let t of msg['flagwords']) {
                        if (t['team_name'] == 'insecure') {
                          console.log(t['flagword']);
                          fs.writeFileSync( "flag.txt" , t['flagword'] );
                        }
                }
        });
        socket.emit('flagwords');
});
$ socat TCP-L:8888,reuseaddr,fork EXEC:"cat flag.txt"

競技についての感想

 なんと言っても5位が嬉しくて、これまでずっと負け戦だったSECCONに少しでも爪痕を残せたかなと言う感じです。毎度連携大会から出場して下位を彷徨っていたので「連携大会の制度やめた方がいいのでは」と思っていたのですが、ここからちょっと自虐要素が減りました。

 問題については国際にリソースを割かれ過ぎたのかなという感じで、CTFというよりはQuizみたいな問題ばかりが3問になってしまい非常に悲しいです。ポーカーでがちゃがちゃやっているとフルハウスのみならず4カードも割とでるのは明らかにバランスが悪かったし、XSS HELLは運営でテストプレイしたなら明らかにこれはだめでしょってなるような問題でした。うーーーん。問題数も少なくてKoH要素が小さかったので後半暇だったのも悲しい。

競技以外の感想

  • 競技中に時々アナウンスがあるんですが、そのときだけでもお隣のセミナーの音消えませんかね。アナウンス聞き取れなくて困る
  • 今年ははじめて体力が残ったので、懇親会で何も食べられない人にはならずに済みました。ローストビーフにかかっていたやつとケーキがおいしかったです。
  • yoshikingが社交性バツグンだったので、yharimaの方とかst98プロとかとお話できてとても良かったです
  • こちらが一方的に因縁をつけているチームより上位だったのも良かった

 まだなにかあったような気もしますが、とりあえず今思い出せるのはここまでです。また来年、もし参加できたなら、次は更に良い成績を目指していきたいです。とりあえず今年は良い成績が出た嬉しさ、チームメイトへの感謝をもっておしまい、来年また精進です。

*1:これはブラウザでもそうで、リロードすると古いフラグが表示されてしまいDefense Pointがはいらなかったりした