しました。
セキュリティ・キャンプ
わりと昔から知ってたんですけど、セキュリテイに特段興味があったわけじゃなかったので、ふーんってカンジだったんですけど、 去年の末にCTFを始めてから、セキュリティ興味あるある!ってなったので、今年はじめて応募してみた次第です。
結果
セキュキャン受かったよ
— sekai (@sekai67) June 14, 2016
なんか微妙な気持ち。 他の参加者さんを見てると、知識や気概が自分よりはるかにあって、スゴイなーって。 わりと軽いキモチで応募した自分なんかが入って良いのだろーか、みたいな。
そんなことを言ってますが、なんだかんだ言って嬉しいです。 せっかくセキュキャンに行くからには、ガチでガンバリます。 ↓の応募用紙を見直してて勉強不足を痛感しましたし、精進します。
ということで、末席に名を連ねる運びと相成りましたが、どうぞよろしくお願い致します。
応募用紙
どんなことを書いたのか、晒します。(恥ずかしい。。。)
共通問題1
- あなたが今まで作ってきたものにはどのようなものがありますか?いくつでもいいので、ありったけ自慢してください。
- それをどのように作りましたか?ソフトウェアの場合にはどんな言語で作ったのか、どんなライブラリを使ったのかなども教えてください。
- 開発記のブログなどあれば、それも教えてください。コンテストなどに出品したことがあれば、それも教えてください。
そのまま書くとアレなので、抜粋。
- プログラミングはゲームを作りたくて始めたよ
- ゲームたくさん作ったよ
- HSPプロコンで入賞したりしたよ
- U-20プロコンで賞をもらったよ
- ソシャゲの情報を勝手に収集して公開するWebサービスを作ったよ
- クローラはJava、DBはMySQL、フロントはPHPだよ
- 月間15万PVくらいあるよ
- 大学のサークル向けのクローズドなSNSを作ったよ
- サーバはnode.jsでSocket.ioで通信するよ
- SAML IdPになって他のサービスと連携できるようになってるよ
- クライアントはHTML/JSで書いて、いわゆるハイブリットアプリにてラクしたよ
- OSSプロジェクトにちょっとだけコード投げてるよ
みたいな事を書いた。
共通問題2
- あなたが経験した中で印象に残っている技術的な壁はなんでしょうか?(例えば、C言語プログラムを複数ファイルに分割する方法)
- また、その壁を乗り越えるために取った解決法を具体的に教えてください。 (例えば、知人に勧められた「〇〇」という書籍を読んだ)
- その壁を今経験しているであろう初心者にアドバイスをするとしたら、あなたはどんなアドバイスをしますか?
抜粋。
- ドキュメントが充実してないライブラリ的なを使うのが辛かった
- ググっても情報が手に入らないし、もう全部ソース読むわ
- ソース読んだら中身がメッチャよくわかるし神(それはそう)
- 困ったらソース読もう
- ソース読んだらそのプロジェクトにContributeもできる!!!楽しい!!!!!
共通問題3
これ、自分が思うに 一番大事な設問 な気がします。 強いけど学ぶ意欲が見られない人 と 強くはないけどメッチャやる気のある人 だったら、後者が通るだろうなぁ、って。 その学ぶ意欲的なものをアピールするのがココなので。。。
かく言う自分の書いたヤツ、微妙。。。 なんか他の人が上げてるヤツ、ヤバい。まず分量が桁違い。 なんでボク通ったんだろうか。
(1)あなたが今年のセキュリティ・キャンプで受講したいと思っている講義は何ですか?(複数可) そこで、どのようなことを学びたいですか?なぜそれを学びたいのですか?
「クラウドセキュリティ基礎」や「サーバ運用におけるパスワード管理」を初めとする、ネットワーク、Web系の講義に最も興味があります。 先に述べたような、Webアプリケーションを作ったり、CTFコンテストに参加したりして、脆弱な実装は本当に怖いということを身を持って感じました。 そこで、セキュアなアプリケーションを作れるように、どのような攻撃手法が存在し、防ぐにはどうすればよいかを詳しく知っておきたいです。 また、「ID連携基礎」にも興味があります。実際に複数のアプリケーションでID連携をするソフトウェアを制作したのですが、 直接パスワードなどを扱う部分であるため、本当に気をつけて実装しなければならないと感じ、認証技術についてより詳しく知らなければならないと思いました。 また、「人工知能とセキュリティ」にも興味があります。私は人工知能の研究にも興味があったのですが、それとセキュリティを関連付けて考えたことがありませんでした。 そのため、人工知能とセキュリティについて、知ることができれば、今後人工知能を扱うときに参考になるかと思いました。 また、「オンラインゲームアタック&ディフェンスチャレンジ」や「スマートフォン向けゲームのセキュリティ」にも興味があります。 私はこういったゲームでよく遊ぶのですが、こうしたゲームで散見されるチート行為、それがどのように行われ、運営者はそれをどのように見つけているのか、ずっと疑問に思っていました。 また私は大学のサークルでゲーム制作をしているので、オンラインのゲームを作る際に不正をどうやって取り締まればよいのか知っておきたいと思いました。
(2)あなたがセキュリティ・キャンプでやりたいことは何ですか?身につけたいものは何ですか?(複数可) 自由に答えてください。
「今少し知っている」知識を深めることもそうですが、「今ほとんど知らない」分野の知識についても、出来る限り獲得したいと思っています。 セキュリティの分野で活躍するには、ある特定の分野にだけ長けているのでは対応しきれないと思っていて、 もちろん自分の得意な分野を極めるのもそうですが、様々な関連分野の知識を持ち、 そうした広い分野についての知識を持っておくことで、何をするにしても広く視野を持つことができるような人間になりたいと思います。 セキュリティ・キャンプに参加することで、そうしたセキュリティのエキスパートへの第一歩を踏み出せればと思います。 また、同じ分野に興味を持つ同年代の人と知り合える数少ない機会であるので、人脈を作ることもできればと思っています。
選択問題2
Googleは、自社のサービスのセキュリティを高めるために様々なことを行っています。
ブラウザからGoogleの検索サービス( https://www.google.co.jp/ )にアクセスを行い、どのようなセキュリティ施策が行われているかを見つけなさい。
ブラウザは任意のもので構いません。ブラウザのどういった点からどういった施策を行っていると判断できるのか、その理由も含めてできるだけ多くの項目を回答してください。
拡張機能を利用しても構いませんが、ブラウザ以外の方法でアクセスしてはいけません。
間違ってそう。
Chromeでアクセスするとまず目につくのは、アドレスバーに表示される緑色の鍵マークです。 クリックして詳細を表示すると、「安全なTLS接続」と表示されますが、 これはTLSを用いた接続を行っており、通信が正しく暗号化されていることを示しています。 また同時に「有効な証明書」と表示されますが、これはサーバー証明書の検証に成功し、 このコンテンツは確かにGoogle社のサーバーから提供されたものであることを示しています。 またスマートフォン版のChromeから見ると、「証明書の透明書に関する有効な情報がサーバーから提供されました」と表示され、 これはCertificateTransparencyという技術で、これはGoogleのサーバが提示した証明書が不正な証明書でないことを表しています。 また、「ECDHE_ECDSA」が鍵交換に使用されている旨が表示されますが、 ECDHEには前方秘匿性があり、サーバの持つ秘密鍵が万が一流出したとしても、過去の通信記録からその内容が暴かれることがなくなります。 またECDSAは、一般的なRSAと比べると同じセキュティレベルを得るために必要な鍵の長さが短いとされており、より安全性が高いと考えられます。 FirefoxでTLS証明書を見ると、署名アルゴリズムに「SHA-256」を利用しており、これは古い方式SHA-1に比べハッシュ衝突に対する高い耐性を持ちます。 また、Firebugなどの拡張機能を用いて通信を見ると、「X-Frame-Options: SAMEORIGIN」ヘッダが送信されているのがわかり、 これによって、フレームを利用しててこのページを別のサイトに組み込むことが出来ず、クリックジャッキングを防ぐことが出来ます。 また「X-XSS-Protection: 1; mode=block」ヘッダが送信されており、これによってブラウザのXSS対策機能を有効化しており、これによりある程度のXSSを防止することが出来ます。 また「Content-Type: text/html; charset=UTF-8」のようなヘッダで文字コードが指定されており、レガシーなブラウザを標的としたUTF-7 XSS攻撃も対策されています。 HTMLソースを表示すると、埋め込まれたJSコードも含め、圧縮(難読化)されているのがわかり、攻撃者にページ構造を理解させない措置とも見ることが出来ます。
選択問題4
突然だが、RH Protocolで用いられるRHパケットのフォーマットを以下に示す。なおRH Protocolは実在しないプロトコルであり、その内容について特に意味は無い。
(略)
添付するバイナリは、とあるRHストリームのうち片方向のみを抽出したものである。
このバイナリストリームを読み込み、1つのRHパケットが以下の条件のすべてにマッチするときに標準出力に文字列"PASS"、 それ以外の場合は"REJECTED"と表示するCもしくはC++のプログラムを記述し、実行結果と共に提出せよ。
また、マッチングにかかるCPUサイクル及びメモリ使用量を計測し記載した場合、評価に加味する。
(略)
ごちうさ。
なんかボクの書いたやつ、ミスってる気がする。 応募用紙上げてる人の出力結果と一致してない……オワタ……ってなってた。 (結局わからず)
#include <iostream>
#include <string>
using namespace std;
/* データの長さ */
#define MAGIC_LENGTH 2
#define SRC_LENGTH 20
#define DST_LENGTH 20
/* RH Packet 構造体 */
typedef struct {
string Magic;
string Source;
string Destination;
int DataLength;
string Data;
} Packet;
/* 文字列を小文字に */
string toLower(string in){
for(int i = 0; i < in.length(); i++){
in[i] += ('A' <= in[i] && in[i] <= 'Z' ? 32 : 0);
}
return in;
}
/* 16進数のcharを10進数のintに */
int hexToDec(char a){
return '0' <= a && a <= '9' ? a - '0' : a - 'a' + 10;
}
/* ストリームから1byte分のデータを読む */
char readByte(){
char buf, buf2;
while(cin >> buf){
if(('0' <= buf && buf <= '9') || ('a' <= buf && buf <= 'f')){
cin >> buf2;
return 16 * hexToDec(buf) + hexToDec(buf2);
}
}
return -1;
}
/* ストリームからintを読む */
int readInt(){
int val;
for(int i = 3; i >= 0; i--){
char byte = readByte();
if(byte == -1){
return -1; /* 標準入力が終端に達しているとき-1を返す */
}
((char*) &val)[i] = byte;
}
return val;
}
/* ストリームから文字列を読む */
string readString(int length){
char bytes[length + 1];
for(int i = 0; i < length; i++){
bytes[i] = readByte();
}
bytes[length] = '\0';
return bytes;
}
/* ストリームからパケットを読む */
Packet readPacket(){
Packet p;
p.Magic = readString(MAGIC_LENGTH);
p.Source = readString(SRC_LENGTH);
p.Destination = readString(DST_LENGTH);
p.DataLength = readInt();
p.Data = readString(p.DataLength);
return p;
}
/* パケットの正当性確認 */
bool checkPacket(Packet p){
return
/* Condition 1 */
( p.Magic == "RH" ) &&
/* Condition 2 */
( toLower(p.Source) == "rise-san" ||
toLower(p.Source) == "cocoa-san" ) &&
/* Condition 3 */
( toLower(p.Destination) == "chino-chan" ||
toLower(p.Destination) == "chino" ) &&
/* Condition 4 */
( toLower(p.Source) != "cocoa-san" ||
toLower(p.Destination) != "chino" ) &&
/* Condition 5 */
( p.Data.find("BlueMountain") != string::npos ||
p.Data.find("Columbia") != string::npos ||
p.Data.find("OriginalBlend") != string::npos ) &&
/* Condition 6 */
( p.Data.find("DandySoda") == string::npos &&
p.Data.find("FrozenEvergreen") == string::npos ) ;
}
int main(){
while(!cin.eof()){
Packet p = readPacket(); /* 1パケットを読む */
if(p.DataLength == -1){
break; /* 読み込みができていないとき */
}
cout << (checkPacket(p) ? "PASS" : "REJECTED") << endl; /* パケットを確認 */
}
return 0;
}
出力結果
PASS
PASS REJECTED PASS REJECTED PASS PASS REJECTED PASS REJECTED PASS REJECTED PASS REJECTED REJECTED PASS REJECTED PASS REJECTED REJECTED REJECTED PASS REJECTED PASS REJECTED REJECTED REJECTED REJECTED PASS REJECTED PASS REJECTED REJECTED REJECTED REJECTED REJECTED PASS REJECTED PASS REJECTED REJECTED REJECTED REJECTED REJECTED REJECTED
選択問題6
IDとパスワードを入力したユーザの認証を行うWebアプリがあります。
あなたがこのアプリに対してセキュリティテストを行う場合、まず、どのようなテストをしますか?
なぜそのテストを選択したのか、その背景や技術的根拠と共に記載してください。
アプリの内部で使われている技術やシステム構成に、前提を置いても構いません。
なんか応募する直前にksnctfをやってたので、ksnctfの問題にあった脆弱性をてきとうに挙げました(ノ≧ڡ≦) (ひどい)
まず、適当なURL、「./user.db」「./accouts.sqlite3」などにアクセスを試みます。 SQLite3を使用したシステムの場合、このようなデータベースファイルへ外部からアクセスできるようになっている場合、ユーザーの情報が簡単に盗まれてしまいます。
次に、ログインフォームに「'」や「"」といった文字列を入力し挙動を見たり、、パスワードに「' OR '' = '」のような文字列を入力してログイン出来ないか調査します。 サーバーがデータの格納にSQLを使用しており、SQLで意味のある文字を適切にエスケープしていない場合、このようなSQLをインジェクション攻撃によって、 不正にデータを書き換えたり、秘匿なデータを盗み出したり、パスワードを知らずともログインできたり、パスワードがハッシュ化されていても平文を求めることができてしまいます。
次に、スクリプトを用いて高頻度のログインリクエストを送信します。 高頻度のリクエストに対して、Captchaのような画像認証をはじめとするBOT対策がなされていないと、ブルートフォース攻撃に晒される可能性があります。
次に、「password」のようなパラメータ名が設定されているフォームに対し、「password[]」のようなパラメータでリクエストを送信します。 サーバがPHPで実装されており、strcmpのような関数と曖昧な比較演算子(==)でパスワード比較がされていると、これでパスワード認証を突破される可能性があります。
次に、ユーザの入力したデータが再び表示されるようになっていないかを確認します。(パスワードが間違っていた場合、ユーザー名が予め入力されているなど) このような機能がある場合、<script>タグでコードを埋め込めるようになっていないかを確認します。 適切にエスケープされていない場合、XSS攻撃でCookieなどを盗まれる可能性があります。
次に、セッション情報のCookieがどのような形で渡されているのかを確認します。 Cookieにユーザー識別情報が乗せられていて、MD5のような脆弱なハッシュ関数で署名されていた場合、書き換えられる可能性があります。 また、署名の作り方によっては、LengthExtension攻撃などによって認証を突破される可能性があるので、この攻撃も試行します。
選択問題11
2015 年に発行された CVEの内、あなたが興味を持った"サーバに存在した"脆弱性について1つ提示してください。
その脆弱性を悪用した攻撃を検知する方法について詳細に記述してください。また、興味を持った理由を記述してください。
CVE番号:CVE-2015-◯◯◯◯
私が興味を持ったのは、CVE-2015-8669です。 この脆弱性は、phpMyAdminの古いバージョンに存在し、/libraries/config/messages.inc.phpという、 UI文字列情報が格納され、他のphpファイルからインクルードされることを想定したファイルに直接アクセスすることで引き起こされます。 このファイルに直接アクセスすることによって、本来は別のphpファイルで定義されるはずの関数が定義されておらず、 それを呼び出してしまうことで、スクリプトのフルパス情報を含むエラーメッセージを出力してしまうというものです。
[攻撃を検知する方法]
HTTPサーバのアクセスログを確認することによって、容易に検知することが出来ます。 攻撃を受けた場合、/libraries/config/messages.inc.phpへのアクセスが記録されます。 また、エラーログには実際に攻撃者に表示されたものと同じメッセージが記録されており、ここからも検知が出来ます。実際のログ
127.0.0.1 - - [30/May/2016:00:51:02 +0900] "GET /phpmyadmin/libraries/config/messages.inc.php HTTP/1.1" 200 266 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0"
[Mon May 30 00:51:02.871439 2016] [:error] [pid 8968:tid 1836] [client 127.0.0.1:52477] PHP Fatal error: Uncaught Error: Call to undefined function PMA_fatalError() in C:\xampp\htdocs\phpmyadmin\libraries\config\messages.inc.php:14\nStack trace:\n#0 {main}\n thrown in C:\xampp\htdocs\phpmyadmin\libraries\config\messages.inc.php on line 14\[興味を持った理由]
まず、phpMyAdminは自分がよく利用するプロダクトの一つであったからです。 次に、この脆弱性では、(サーバの設定によっては)ブラウザから当該のURLにリクエストを送るだけで成立してしまうなど、比較的簡単に攻撃が成立するのが面白いと思いました また、これはベンダの発表文書でも述べられていたことですが、PHPの設定自体が適切にされていれば攻撃は成立せず、 この設定(display_errors = off)はテスト用サーバー以外では普通は設定されるものであり、 また仮に攻撃が成立したとしても、その被害はさほど大きなものでなく(phpMyAdminが設置されるパスが漏れるだけ)、 私は一瞬「大した脆弱性ではないのではないか」と思ってしまいましたが、 こうして大々的に記録されているところを見て、このようにどんな小さな脆弱性であっても、それが大きな攻撃の糸口とならないよう、 常に注意していくべきなのだなと、考えを改めさせられました。 このように、自分のセキュリティに対する意識にも関わるものであったため、このCVEに興味を持ちました。