セキュリティ・キャンプ全国大会2016の応募用紙を晒す
今年も死んだよ。選択問題だけ晒す。
選択問題. 1
hogeはローカル変数であり、int型の10個ぶんの配列である。main関数の中でスタックポインタ(rsp)がずらされることにより、必要なサイズ(sizeof(int)*10bytes)
がスタック上に確保される。C言語で配列名は配列の先頭アドレスを指すので、hogeにはスタック上に確保されたメモリの先頭アドレスが格納されていることになる。よって、0x7fff539799f0
付近はスタックのアドレスであることがわかる。
fugaはintポインタとして宣言されており、malloc()
により動的に確保されたメモリのアドレスが格納されている。malloc()
はヒープ上にアドレスを確保するので、0x7fca11404c70
付近はヒープのアドレスであることがわかる。
選択問題. 2
- HTTPS
Webブラウザのアドレスバーに書かれている、スキーマからHTTPSを用いていることがわかる。Firefoxでは、ページ内で右クリック→ページ情報の情報を表示→「セキュリティ」タブと操作することで、より詳しい内容が表示できる。この内容から、認証局が「Google Inc」であることや、暗号化の方式が「TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256」であることがわかる。 - Cache-Controlヘッダ
Firefoxでは、ツール→Web開発→ネットワークと操作することで、Webサーバとのやりとりを詳しく見ることができる。その中で、サーバからの応答の中に、「Cache-Control: "private, max-age=0"」というヘッダがあることがわかる。privateのほうは、コンテンツが複数のユーザで共有するキャッシュに記録されるべきでないことを示している。max-age=0は変更をその都度確認させるための指定だ。「Expires: "-1"」というヘッダもあり、これは「Cache-Control: "max-age=0"」と同様の記述らしいが、ブラウザによっては片方しかサポートしていないため、両方書かれているらしい。 - X-Frame-Optionsヘッダ
「X-Frame-Options: "SAMEORIGIN"」というヘッダがあることから、自身と生成元が同じフレーム内に限り、ページを表示することができる。これによって、<iframe>タグなどを用いたクリックジャッキング攻撃を防止することができる。 - X-XSS-Protectionヘッダ
「X-XSS-Protection: "1; mode=block"」というヘッダがあることから、IEのXSSフィルターが有効になることがわかる。有効にするだけなら、「X-XSS-Protection: "1"」だけでよいのだが、mode=blockを指定することでより強固になる。過去のバージョンのIEでは、XSS Filterでブロックしたスクリプトをそのままブラウザ上で表示していた。これによって、XSS Filterを利用したXSSが生まれてしまった。現在はmode=blockがなくても、直接ソースが表示されるようなことはないようだが、過去のブラウザを利用している人も多いだろうから、mode=blockが指定されているのだと思う。
選択問題. 6
'や"など、SQLのメタ文字を入力してみる。なぜならば、IDとパスワードを入力してユーザ認証を行っているWebアプリは、大抵の場合、裏でデータベースにアクセスし、問い合わせの結果でログインの可否を判断しているからだ。もし、入力サニタイズが不十分であるなら、エラーが表示されるはずだ。そうなれば、SQLインジェクションができる可能性があり、大きな脅威となる。
選択問題. 8
まず、この逆アセンブルを眺めて気づいたのは、この逆アセンブルが大きく2つの部分に分かれることです。 0x400080...0x4000fcは、主にpushq命令で構成されていて、 0x400101...0x40012eは、主にretq命令、pop命令で構成されています。 脳内で上から順番に実行してみると、ROPのような挙動をすることがわかりました。 すなわち、0x400080...0x4000fcで戻りアドレスやレジスタにセットする値をスタック上にpushしておき、 0x400101...0x40012eでretqをjmp、popをmovのように使用しています。 したがって、これはROPを応用し、難読化が施されたバイナリの逆アセンブルであることがわかりました。 若干読みにくいので、手動で難読化を解除してみることにしました。
mov $0x0,%rax mov $0x0,%rdi mov %rsp,%rsi mov $0x0,%r10 mov $0x8,%rdx syscall ;read(STDIN,%rsi,0x8,0) mov $0xffffffffffffffe0,%rbp mov $0x7,%rcx xorb $0x55,(%rsi,%rcx,1) ;-> 標準入力から受け取った文字列の最後の文字と0x55のXORをとっている。 ; decが0x7->0x0までループする dec %rcx xorb $0x55,(%rsi,%rcx,1) ; ループここまで mov $0x0,%rdi movabs $0x63391a67251b1536,%rax cmp %rax,(%rsi) mov 0x3c,%rax (jne $0x40012c ;もし入力のすべての文字を0x55とXORした結果が$0x63391a67251b1536と一致しないなら) (syscall ;一致した時の処理, exit(0)) mov $0x1,%rdi syscall ;exit(1)
若干不整合がある気がしますが…
- 基本的には、標準入力から8文字受け取り
- すべての文字を
0x55
とXORをとった結果に変更し、 0x63391a67251b1536
と比較する(リトルエンディアンなことに注意する)- 一致していれば、
exit(0)
、していなければexit(1)
というプログラムのようです。
すなわち、"c@Np2Ol6"
という入力であれば、正常終了するプログラムであるということがわかりました。
(Pythonのインタプリタで、0x63391a67251b1536
をpackして、listにして、mapして...として求めました。
xorb $0x55,(%rsi,%rcx,1)
がどういう処理をするのか、最初わかりませんでしたが、
rasm2を用いてintel記法にしてみると、xor byte [rsi + rcx], 0x55
となり、理解できました。
正直、ループのところはあまりちゃんと読んでいないのですが、decとjneがあることから、%rcxが0まで回るループだろうなと断定して読み進めた結果、それらしい感じになりました。
CTFのような問題で、非常に楽しめました。個人的には一番好きな設問です。
提出前の僕
「選択問題 【8】」に機種依存文字、絵文字などが含まれています。[〜〜〜〜〜]
— げん@セキュキャン落ちた (@neglect_yp) May 30, 2016
となっているが、みつからず死んでいる
— げん@セキュキャン落ちた (@neglect_yp) May 30, 2016
犯人は"〜"でした
— げん@セキュキャン落ちた (@neglect_yp) May 30, 2016
@__x90__ 一行だけしか表示されなかったため、[〜〜〜〜〜]が、〜で引っかかっているということに気づくのに時間かかった
— げん@セキュキャン落ちた (@neglect_yp) May 30, 2016
〜とかいう文字もう一生使わねえからな
— げん@セキュキャン落ちた (@neglect_yp) May 30, 2016
その後
セキュキャン落ちました…
— げん@セキュキャン落ちた (@neglect_yp) 2016年6月14日
来年も一応応募資格はあるけれど、これで3回落ちているし最早受かる気がしないので迷っている。