セキュリティ・キャンプ2016 応募用紙

どうも、馬です。

なんか2017年セキュリティ・キャンプ全国大会の募集が始まった事により、

www.ipa.go.jp

 

去年以前にセキュリティ・キャンプに行った人の応募用紙がまとめられてるスプレッドシートができる事態になっています。

 

というわけで、僕も流れ的に晒して、スプレッドシートに載ろうと思います。

 

ただし一つ注意点。

晒してるみなさんはプロの人達ばっかで、それに比べて僕の応募用紙はみすぼらしいものとなっています。他の方と比較されると、どうしても劣って見えるかと思いますが、その点ご容赦ください。

 

問題文

https://www.ipa.go.jp/files/000053055.pdf

 

 

共通問題 【1-1】:https://063.jp/location2/  (今は動かしてない)
今いる場所から近い順に駅を表示するアプリを作りました。GPS情報が変わることをトリガーに情報を更新しているので、移動している時に、リアルタイムに一番近い駅を出せます。また、最寄り地点リストは、線路情報から、一番近い線路を出すことができます。このアプリにより、今どの路線に乗っていて、次の駅まで何mくらいあって、周辺の鉄道はどんな路線があるのかなどが簡単にわかるようになりました。
技術的な自慢としては、駅情報は約3万件、線路地点情報は約100万件のデータベースの検索を、一般的な土地では1秒以内に終わらせられるようにチューニングした点です。
また、googlemapへの表示も、なめらかにカーブが表示されるように工夫しています。

共通問題 【1-2】:サーバー側はPHP7でAPIが動いています。このAPIにリクエストを送ると、APIは駅情報などを保存しているMySQLに対してクエリを発行し、帰ってきたデータをJSON形式でクライアントに返します。
クライアント側はReact.jsで書かれています。また、表示をきれいにするために、bootstrapも用いています。

共通問題 【1-3】:組み終わったあとにブログ記事を書きました。
http://goryudyuma.hatenablog.jp/entry/2016/02/05/225848

共通問題 【2-1】:データベースの正規化がよくわからなかった。具体的には、正規化する目的、正規化するにはどうすればよいのか、正規化のメリットデメリットなど。
共通問題 【2-2】:ネットの記事を読み漁った。書籍では「理論から学ぶデータベース実践入門(奥野幹也)」を読んだ。また、実際に正規化を試してみたりした。
共通問題 【2-3】:正規化する目的は、同じデータを同じカラムにデータそのもののまま入れることを防ぐことにある。一つのデータを更新したい時に、データがそのまま入っている状態だと、そのデータと同じものをすべて更新しないといけない。しかし、そのデータそのものが入っているところにリンクとして入れておき、データそのものは別のところで持っておくことで、更新は一回ですむ。正規化する基準としては、同じデータが複数同じカラムに入っていて、更新がかかる可能性があるとき。メリットとしては更新時に一回のみ更新すれば良くなること、デメリットとしてはテーブルが増えてしまうので、きちんとドキュメント化しておかなければ管理できないほどテーブルが増えてしまうこと。
共通問題 【3-1】:5-A サーバー運用におけるパスワード管理
普段、自分はVPSを運用している。その上で動いているサービスや、他のところで動いているサービスには、パスワード認証が使われている物が多い。これからさらに自分が扱うサーバーの数は増えていくことが予想され、扱うパスワードも増えるであろう。まさにこの講義でパスワード管理の問題点と対処法を学び、自分の力としたい。

2-C 人工知能セキュリティ
詳細にも述べられている通り、人工知能に関するセキュリティと言われてもなにも思い浮かばないので、とても惹かれた。人工知能機械学習は様々な分野で使われており、自分も興味がある。確実に自分の知らないことを講義してくださると思うので、楽しみにしている。

3-A Webアプリケーションの脆弱性の評価と発見
Webアプリケーションを運用する上で、脆弱性は特にあってはいけないものだ。自分で作るときは自分で分かる範囲では対策するが、自分が知らない脆弱性については対処しようがない。個人レベルでしか脆弱性があるかチェックできないので、本講義を通して、より実践的な脆弱性の発見の手法を身につけ、今動いているWebアプリケーションや今後作るWebアプリケーションにおいて、脆弱性を発見して理解し、対処していきたい。

共通問題 【3-2】:今まで、自分はセキュリティに対して一種の恐怖感を持っており、例えばアプリケーションを作る際、できるだけ個人情報となりうるものは保存しないように徹底していた。個人情報を持ちたくないがために、作りたいと思ったアプリケーションの仕様そのものを変えたこともあるくらいである。自分程度が組むアプリケーションなら、脆弱性など有って当然だと思っていた。もし流出したら・・・と考えると、どうしても保守的な考え方になってしまっていた。しかし、そろそろわがままも言えない状態になってきていて、個人情報の保存に手を出さざるを得なくなりそうだ。もし可能ならば、セキュリティキャンプに参加し、セキュリティ脆弱性について知識をつけ、自信を持った上で今後のサーバー運用やアプリケーションの開発に挑みたい。
選択問題 【1】:
選択問題 【2】:
選択問題 【3】:
選択問題 【4】:プログラム(C++)

-----------


#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>

#define DEBUG 0

struct FRH {
        char Magic[3];
        char Source[21]; /* null(‘\0’) terminated ascii strings */
        char Destination[21]; /* null(‘\0’) terminated ascii strings*/
        uint32_t DataLength; /* min 0, max 4,294,967,295 */
        char *Data; /* null(‘\0’) terminated ascii strings */
};

//デバッグ用の出力関数
void show(FRH now) {
        std::cout << "Magic       :" << now.Magic << std::endl;
        std::cout << "Source      :" << now.Source << std::endl;
        std::cout << "Destination :" << now.Destination << std::endl;
        std::cout << "DataLength  :" << now.DataLength << std::endl;
        std::cout << "Data        :" << now.Data << std::endl;
        std::cout << std::endl;
}

//条件1のチェック
bool checkCondition1(FRH now) {
        if (now.Magic[0] == 'R' && now.Magic[1] == 'H') {
                return true;
        } else {
                return false;
        }
}

//条件2のチェック
bool checkCondition2(FRH now) {
        std::string S = now.Source;
        transform(S.begin(), S.end(), S.begin(), ::tolower);
        if (S == "rise-san" || S == "cocoa-san") {
                return true;
        } else {
                return false;
        }
}

//条件3のチェック
bool checkCondition3(FRH now) {
        std::string D = now.Destination;
        transform(D.begin(), D.end(), D.begin(), ::tolower);
        if (D == "chino-chan" || D == "chino") {
                return true;
        } else {
                return false;
        }
}

//条件4のチェック
bool checkCondition4(FRH now) {
        std::string S = now.Source;
        std::string D = now.Destination;
        transform(S.begin(), S.end(), S.begin(), ::tolower);
        transform(D.begin(), D.end(), D.begin(), ::tolower);
        if (!(S == "cocoa-san" && D == "chino")) {
                return true;
        } else {
                return false;
        }
}

//条件5のチェック
bool checkCondition5(FRH now) {
        std::string data = now.Data;
        if ( ( int)data.find("BlueMountain") != -1 ||
                        (int)data.find("Columbia") != -1 ||
                        (int)data.find("OriginalBlend") != -1) {
                return true;
        } else {
                return false;
        }
}

//条件6のチェック
bool checkCondition6(FRH now) {
        std::string data = now.Data;
        if ( (int)data.find("DandySoda") == -1 &&
                        (int)data.find("FrozenEvergreen") == -1) {
                return true;
        } else {
                return false;
        }
}

int main() {
        //ファイルとして開く
        std::ifstream fin("pyonpyon.rh", std::ios::in | std::ios::binary);
        if (!fin){
                std::cout << "ファイルが開けません" << std::endl;
                return 1;
        }

        FRH now;

        //順番に処理する
        while(fin.readsome(now.Magic, 2)) {
                fin.readsome(now.Source, 20);
                fin.readsome(now.Destination, 20);

                //4byte読み込んでuint32_tに変換する
                now.DataLength = 0;
                char x[4];
                fin.readsome(x, 4);
                now.DataLength = 0;
                for (int i = 0; i < 4; i++) {
                        now.DataLength <<= 8;
                        now.DataLength += x[i];
                }

                //文字数+1だけメモリを確保する
                now.Data = new char[now.DataLength + 1];
                fin.readsome(now.Data, now.DataLength);

                //flagが一度でもfalseになればREJECTED、ならなければPASS
                bool passflag = true;
                if(passflag && !checkCondition1(now)){
                        passflag = false;
                }
                if(passflag && !checkCondition2(now)){
                        passflag = false;
                }
                if(passflag && !checkCondition3(now)){
                        passflag = false;
                }
                if(passflag && !checkCondition4(now)){
                        passflag = false;
                }
                if(passflag && !checkCondition5(now)){
                        passflag = false;
                }
                if(passflag && !checkCondition6(now)){
                        passflag = false;
                }

                if(passflag) {
                        std::cout << "PASS" << std::endl;
                } else {
                        std::cout << "REJECTED" << std::endl;
                }


                if(DEBUG) {
                        show(now);
                }

                delete now.Data;
        }
}

-----------

以上プログラム

実行結果

-----------

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

-----------

以上実行結果

選択問題 【5】:OSとは、ハードウェア(物理的なもの)を操作する仮想的なインターフェースだ、と考えています。汎用OSでは、さまざまなメーカーが製造する部品の合作である現在のコンピューターを、共通のインターフェースで操作できるようにしようとしたものであり、逆に組込みシステムは、自分の会社の製品に特化して無駄な機能は取り除き、必要な機能のみにすることで、メンテナンスしやすくしたり保存に必要になる容量を少なくしたり、コストを下げたりできます。しかし最近、一台のハードウェアに対応するOSは一つである必要性はないという考え方が主流になってきました。マルチブートで複数のOSを一台のハードウェアに入れて、好みや役割により使いたいインターフェースを選ぶなどもできます。また、動いているハードウェアに対応するOSの上に、仮想的にハードウェアを作り対応するOSを動かす、バーチャルマシンもできてきました。
OSがハードウェアを操作するので、OSそのものには様々な機能が備わっています。OSがCPUをどのように使うのかを決め、OSがメモリをどのように使うのかを決め、OSがマウスやキーボードをどのように使うのかを決めます。OSはコンピューターのすべてを操作する頭脳の役割を果たしています。

選択問題 【6】:IDとパスワードを入力して認証ということは、どこかにデータベースがあり、そこでSQLが使われていると考えました。そこで、SQLインジェクションに対するセキュリティテストを行います。SQLインジェクションがもし成功すると、データの改ざんから個人情報の取得まで、幅広くダメージが与える事が可能です。一度でも信頼を大きく失ったアプリケーションは、今後使われることはないでしょう。これはとても大きな損害で、実際に問題になっています。
セキュリティテストテストですが、まず、IDやパスワードの入力欄に、「'」(シングルクォート)や「`」(バッククォート)などを入れて送信します。もし入力文字列をエスケープせず、文字列結合によりSQLを生成している場合、ここで何かしらのエラーや予期せぬ結果が出ます。
つぎに、入力欄に、「%」(パーセント)や「_」(アンダーバー)などを入れて送信します。入力文字列に適切なエスケープがされていなければ、ワイルドカードとなるのでこちらも予期せぬ結果が出力されるでしょう。

選択問題 【7】:
選択問題 【8】:
選択問題 【9】:マイナンバーカードは、本人とマイナンバーを紐付ける大切なカードである。別人に送られてはいけない。自分なら、カードの申請時に住所に誤りがないかをチェックしてもらい、情報が確認取れ次第、本人限定受取で郵送されるというクレジットカードの送付と似たシステムにするだろう。郵送時の誤りは極力抑えられるとして、申請時に誤りが入りにくいようにしなければならない。マイナンバーカードが発行されるのは、マイナンバーが発行された後なので、発行したい人はすでにマイナンバーを手元に持っているはずである。よって申請時には、マイナンバーと、氏名年齢などの個人を特定できる情報を要求し、データが一致していた時に申請が通るようにする。ネット弱者にも配布できるように、市役所などの窓口でも申請はできるようにしなければならないが、これはこの申請手続きの代行である。
選択問題 【10】:
選択問題 【11】:

 

 

(メールそのままコピってきた)

 

以上です。自分でもなんで通ったかあんま分かってないし、その分今後に期待されてるのかなと勝手に思ってます。今後とも、精進いたします。