セキュリティ・キャンプ 全国大会 2017 に通った

タイトルの通りキャンプに通りました。通知メールはサークルの部室にいた時に見ました。通ったのが分かった時は、ガッツポーズしながら「ヨッシャーッッ!!」と叫びました。キャンプに参加できるのも周囲のおかげだと思うので感謝したいです。

さて、恒例になっている応募用紙を公開する記事を書いてみます。私の場合は、募集開始がされてすぐに応募用紙を書き始めて提出したのは締め切り前日でした。でも、文字数は全体で20000字弱くらいなので少ないと思います。今後、キャンプに応募する方の参考になればと思います。

誤字脱字や技術的に間違えている部分もあると思うのであしからず..。
この記事では、長い部分を減らしたり要約したりしてあります。

共-1(1)

あなたが今まで作ってきたものにはどのようなものがありますか?いくつでもいいので、ありったけ自慢してください。

  • [1]. WebRTCを利用して20クライアントでビデオチャット
  • [2]. 高校の部内システム(インフラ)
  • [3]. 自作の静的サイト ジェネレータ
  • [4]. 気象センサが取得したデータを利用するWebアプリケーション
  • [5]. 自宅内のインフラ構築

共-1(2)

それをどのように作りましたか? ソフトウェアの場合には、どんな言語で作ったのか、どんなライブラリを使ったのかなども教えてください。追加したい機能や改善の案があれば、それも教えてください。

[1]. WebRTCを利用して20クライアントでビデオチャット

高校の課題研究で「WebRTCを使ったWeb会議システム」を開発しました。当初はWebRTCを扱っている書籍がなくサイトや英書で学んでいたが難しかったです。高校2年の後半になって国内でWebRTCをメインに扱った書籍「WebRTC ブラウザベースのP2P技術」が発売されました。それを使って勉強したら理解できていなかった部分が理解できました。

このアプリケーションの開発には大きく分けて4つのプロセスを経て開発しました。

  1. メディアの取得(カメラ映像、マイク音声をAPI経由で取得してWebブラウザに表示)
  2. 1対1での通信
  3. 1対Nでの通信(1と[多のそれぞれ]だけが繋がっている)
  4. N対Nでの通信(それぞれが相互に繋がっている)

また、このアプリケーションの作成のために大きく分けて「3つのサーバー」を構築しました。

1. Webサーバ 兼 ID(ROOM)管理サーバ

これはWebRTCの通信プログラム(JavaScript)やWebページ(html,css)をクライアント側へ配信する役割を担います。また、WebサーバにWebSocketサーバの機能も持つことでクライアントの入退室の管理(Room)をリアルタイムで行います。両サーバの機能をNode.jsとそのモジュール Socket.ioを使用してプログラムを作成しました。

なお、以下で記述しているシグナリングサーバ(PeerServer)にはルームの概念が含まれていない為、自作のID(ROOM)管理サーバ機能も実装しました。自作のID(ROOM)管理サーバ上では、シグナリングサーバで発行されるID(peerID)を管理しており、WebSocketでリクエストが来ると同一ルーム内にいるクライアントの一覧(PeerID)を返すという処理を行っています。IDの管理は2次元の連想配列を使って実装しました。Node.jsの書籍を購入してそれを読みながらプログラムを作成しましたが、バージョンが異なりエラーが出てかなり苦労しました。そうした時に、公式のドキュメントや海外のトラブルシューティングサイトの情報が解決に役立ちました。

2. シグナリングサーバ

シグナリングサーバにはライブラリpeer.jsに対応するPeerServerを使用しました。クラウドで提供されているサーバもありましたが、ファイアウォールがあるため学内に構築しました。これの構築にはNode.jsとパッケージpeer(peerServer)を使用することで構築しました。

3. STUN(TURN)サーバ

NATを越えて通信する為に必要なサーバでグローバルIPを知るために必要となります。これによって多段NATを使用している場合でも通信が可能になります。もし、STUNサーバが利用できない場合には、通信を中継するTURNサーバを使います。これらのサーバをオープンソースのrfc5766-turn-serverによって構築しました。

次に、Webサーバから配布されるクライアント側のプログラム(JavaScript)を作成しました。このプログラムの作成にはsocket.ioとpeer.jsを、WebのUIにはライブラリ Twitter Bootstrapを使用しました。さらに、WebSocketの通信が度々、切れることがあり再接続すると別のユーザとサーバに認識されてしまう問題が発生しましたが、Session Storageを使用することで切断された接続かを判断することで重複を防ぎました。

プログラム自体が出来上がり、通信テストをしてみると学校内のクライアント間、学校外のクライアント間では上手く通信できました。しかし、学校内クライアントと学校外クライアントの通信が上手くいきませんでした。設定を変えながら試したところ、この原因は学校のファイヤーウォールが接続を妨げていることによるものだと分かりました。具体的には学校から外部に送信できるのはTCP 80,443とUDP 53であり、WebRTCの通信はUDP 49152-65535を宛先とするためファイヤウォールをパケットが通過できないということです。

この問題を解決するのはとても苦労しました。まず、ポート番号をTCP 80,443に出来るものは変更することで対応しました。また、ネットワークの知識が不足していることもあり専門書を読んだりWebで調べたり、先生に相談してみました。最終的に、WebRTC通信(映像や音声の送受信)だけがUDPで問題となりました。そして、その解決策として次の3つが上がりました。

  1. TURN over TCP
  2. SoftEther VPN
  3. STONE

当初は、TURN over TCPを使って試してみました。しかし、上手くいかないことからSoftEther VPNを使うことにしました。SoftEther VPNサーバを自宅に構築してトンネリングしたところ、外部との通信が上手く出来るようになりました。上手くいったこともあり、STONEでは試さずに終わってしまったので今後、試してみたいと思います。

この研究を通じてWeb、サーバ、プログラミング、ネットワークと幅広い分野を横断して問題解決ができたのが非常に良い経験になりました。特に、これらが密接に関わり合っていることが身をもって理解できました。特に、リアルタイム通信をtcpdumpでパケットキャプチャしたときにUDPパケットが常時流れ続ける様子には非常に興奮し、通信の実態を身をもって理解できました。

[2]. 高校の部内システム(インフラ)

部活動のデータ・情報共有を目的としてサーバを構築しました。主な構成は次の通りです。なお、導入前に自宅内に同様の環境を構築してテストを行った上で校内に構築しました。

[a]. Server01

OSはCentOS 6.6 i386を利用しました。主な用途はファイルサーバ(ストレージ)です。Samba はバージョン 3.6 をソースからインストールしました。ソースからインストールした理由としては1番使われるサービスであり安定性が重要になるからです。

共有(ドライブ)ごとにパーミッションを設定し、所属するグループ(game, it, cg, prog, officer)ごとにACL(ext3で構築)を使って自分の所属するグループと学年のディレクトリには読み書き可能、それ以外のグループと学年のディレクトリは読み取り専用に設定しました。また、各グループのリーダが属するグループ(officer)を作成し、リーダのみ読み書き可能なディレクトリを作成しました。さらに、ユーザ個別の共有(ドライブ)を作成しApache(パッケージから導入)のユーザディレクトリ機能を使用することでWebページを公開出来るようにしました。

加えて、nss_ldapとpam_ldapを導入することによってこのユーザ個別の共有(ドライブ)にSSHからアクセスできるようにしました。

その際、ユーザのシェルはrbashを使用しました。なお、使用可能なコマンドのシンボリックリンクを集めたディレクトリ(コマンド群ディレクトリ)を作成し、ユーザの各ホームからコマンド群ディレクトリへシンボリックリンクを貼ることで使用できるコマンドを一元管理できるようにしました。

[b]. Server02

OSはCent OS 6.6 i386を利用しました。主な用途はLDAPサーバ, Webサーバです。LDAPサーバはOpenLDAP 2.4 をソースから、Apacheはパッケージからインストールしました。LDAPとSambaの連携にはsmb-ldap-toolsを使用しました。LDAPは独自の用語とその概念、設計に苦労しました。余裕があれば2台構築することによる冗長化、LDAP over SSLによる通信の保護にも取り組みたかったです。LDAPは詳しい日本語の資料があまり見つからず、書籍「入門LDAP/OpenLDAP: ディレクトリサービス導入・運用ガイド」を買ったり、海外のサイトを読んでみるなど構築にはかなり苦労しました。

また、ユーザのパスワードをユーザ自身が変えられるようにWebアプリケーションを構築しました。これはWebブラウザ上でLDAPのパスワードを変更できるようにするものです。認証にはApacheのBasic認証(LDAP連携)を利用し、パスワード変更処理はコマンド smbldap-tools をプログラムから実行するという形をとりました。

このアプリケーションはセキュリティ的に十分とはいえない部分があり、ページトークンの導入やサーバをhttps化するなどより安全なシステムにする必要があったと感じています。

さらに、情報共有用にLDAP対応したDokuWikiを導入し、Sambaと同様に所属するグループ毎に読み取り、読み書きに権限を分けて設定しました。

これに加えて、サービス監視のためにmunin, nagiosを構築しました。また、自作のバックアップスクリプトを書いてcronに登録することで、定期的に別ストレージにバックアップを取るように設定しました。

[c]. Client Software

学校内に設置されたクライアントには環境復元ソフトウェアが導入されており、再起動をかけるとマシンが起動前の状態に復元されます。そのため、クライアント(Windows)でSamba(ネットワークドライブ)を割当(マウント)するスクリプト(Batch)を書きました。主な機能はユーザ名とパスワードを入力することで入力された資格情報にもとづいてネットワークドライブをマウントすることです。

[3]. 自作の静的サイト ジェネレータ

高校の同窓会Webサイトをリニューアルする際に制作しました。これまでは一部ファイル(ヘッダ、フッタ、サイドバー)を共通化し、個別のphpファイルでそれらを呼び出していました。また、スマートフォンとPCで別のファイルを作成して管理していました。しかし、この状態ではページが増えるにつれて管理するコストが高くなると考え、新たなシステムをphpでフルスクラッチで構築しました。システムの主な仕様は以下です。

  • 静的ファイルをプログラムで生成する(静的サイト・ジェネレータ)
  • 投稿データはテキスト形式で予め定義した独自タグとhtmlタグの組み合わせで記述
  • 投稿データ内で独自タグ[SITEMAP],[CHILD_LIST], [UPDATE_LIST]を使うことでそれぞれ、子ページ一覧、サイトマップ、最近の更新一覧5件(件数は変更可)を出力
  • ページテンプレートファイルを書き換えることでオリジナルのhtml出力に変更が可能
  • サイトのビルドはWebブラウザで指定のURLにアクセスすることで可能

[4]. 気象センサが取得したデータを可視化するWebアプリケーション

Live E!プロジェクトで提供しているAPIサーバ(REST/IEEE 1888)からデータを取得して可視化するアプリケーションを構築しました。本格的なWebアプリケーションを作ることが初めてで技術の習得とシステムの設計にかなり苦労しました。このアプリを作った時はセキュリティに関する知識が皆無でSQLインジェクションやクロスサイトスクリプティングなどの対策が出来ていなかったとソースを読み返して感じました。この時にセキュリティを理解しているか否かが制作する段階で重要になると身をもって分かり、無知なことの恐ろしさを感じました。主な技術的な構成は以下です。

  • サイト全体はHTML, CSS, JavaScript(jQueryも併用)を使用して構築
  • サイトのバックエンドはPHPで、データベースにMySQLデータベースを利用
  • APIサーバからデータを取得しその値をMySQLデータベースに保存するコード(getdata.php)をcronで5分毎に実行
  • PC, スマートフォン, タブレットに対応したレスポンシブWebデザイン

サイトの各ページとその挙動は以下です。

[a]. 「トップ」ページ
  • 指定した1地点の気象データ(温度, 湿度, 気圧, 風速, 風向, 雨量)と不快指数を表示
  • 表示する地点のデフォルトは検閲により削除を設定
  • パラメータを指定することで他の地点の気象データを表示可能
[b]. 「現在地」ページ
  • ブラウザでHTML5のGeolocation APIを利用して現在地を取得し, Ajaxで(位置情報用)APIサーバに経度,緯度を送信
  • (位置情報用)APIサーバでは渡された経度と緯度を基に、その位置に最も近い5地点をDBに登録された経度,緯度から算出して返す
  • ブラウザではAPIのレスポンスをもとに現在地周辺の地点5件をマップとリスト(リンク)で表示
  • ユーザが地点名リンクをクリックするとトップページにその地点の気象データが見れる

(位置情報用)APIサーバには渡された経度, 緯度の値がチェック機構がないのでSQLインジェクションの脆弱性が存在すると読み返して気づきました。

[c]. 「地点検索」ページ
  • 位置情報が取得できない, 正確でない場合に手動で検索が可能
  • 地点名か住所を入力して検索するとその文字列を含む地点を一覧表示
  • 検索処理は入力文字列をJavaScriptで取得してAjaxで(検索用)APIサーバに送信
  • (検索用)APIサーバは受け取った文字列と検索対象(地点名, 住所)をもとにあらかじめ登録されている地点一覧(データベース)から検索
  • (検索用)APIサーバはデータベースでの検索結果をtableタグ形式でブラウザに返す
  • ブラウザで受け取った表の地点名をクリックするとトップページで指定した地点の気象データが表示される

(検索用)APIサーバには渡された地点名をエスケープしておらず、SQLインジェクションの脆弱性が存在するとコードを読み返して気づきました。

[5]. 自宅内のインフラ構築

自宅でMicroServer(HP)とRapberry Pi Bでサーバを構築しました。これらのサーバで動くサービスは次のものです。

[a]. MicroServer(CentOS 6.6)
  • Webサーバ
  • 家族写真の閲覧(OSSのフォトビューワーを設置して保存した画像を見れる)
  • リモートデスクトップの踏み台(wakeonlanでWindowsマシンを起動する自作アプリ https://github.com/tomoyk/php-wakeonlan-gui)
  • PXE Bootサーバ(ネットワークブートでCentOSをインストールする際に構築)
  • VPNサーバ(SoftEther VPNをインストールしてWebRTCの研究やリモートデスクトップの踏み台で利用)
  • ファイル共有(samba)サーバ(ファイル共有を目的に構築。SambaとLDAP連携の勉強にも使用)
  • LDAPサーバ(OpenLDAPを部活サーバで構築する練習に使用)
  • TURN/STUNサーバ(WebRTCの研究用に構築。iptablesのDNATで内部以外のIPから来たTCP 80宛パケットはこのサーバに届くように設定)
[b]. Raspbery Pi B(Raspbian)
  • DHCPサーバ(不審な端末を締め出すホワイトリスト形式で構築。リースファイルが収集できるためネットワークの全容がつかみやすくなった)
  • Webサーバ
  • DHCPサーバのリース情報を表示するWebアプリ(リース情報を基にネットワークに現在接続している端末の一覧を表示, phpとシェル芸で作成)
  • 本体温度を取得してグラフ化するWebアプリ(本体温度をコマンドで取得してテキストファイルに書き込みその履歴からJavaScriptでグラフを描画。phpとjavascript, シェル芸で構築)

共-1(3)

開発記のブログ、スライドなどの資料があれば、それも教えてください。コンテストなどに出品したことがあれば、それも教えてください。

[1]. WebRTCを使ったWeb会議システム

[2]. 高校の部内システム(インフラ)

[3]. 静的サイト ジェネレータ

[4]. API(IEEE 1888)を利用したWebアプリケーション

  • Live E! サイエンスコンテスト 2013 技術賞 「スマートフォンにおける気象データの可視化」 検閲により削除
  • Live E! サイエンスコンテスト 2014 プログラミング部門優秀賞 「マルチデバイスにおける気象データの可視化」  検閲により削除

共-1(4)

Twitterアカウント、Github、ブログをお持ちでしたら、アカウント名、URL等を記載してください。

  • Twitter: @tmyk_kym
  • GitHub: @tomoyk
  • Blog: https://blog.koyama.me/

共-2(1)

あなたが経験した中で印象に残っている技術的な壁はなんでしょうか?(例えば、C言語プログラムを複数ファイルに分割する方法など)

印象に残っている技術的な壁は、「ファイヤウォール越え」です。先に上げたとおり、WebRTCを利用したテレビ会議アプリを構築した時に学校内ー学校外の通信ができず苦労しました。しかし、この問題を通じて「セキュリティの対策をする立場」と「セキュリティを迂回する立場」の両方について理解することができました。

共-2(2)

また、その壁を乗り越えるためにとった解決法を具体的に教えてください。(例えば、知人に勧められた「○○」という書籍を読んだなど)

まず、研究を始めた当初はネットワークの知識が不足しており、特に送信元(Source)と送信先(Dest)の概念の理解が不十分なため、通信できない原因を突き止めるのに非常に苦労しました。そうした状況から、以下の2冊でネットワークを勉強しました。

  1. マスタリングTCP/IP 入門編
  2. ハイパフォーマンス ブラウザネットワーキング

さらにWebRTCに関する知識をWebサイト(HTML5 Expertsなど)と次の書籍で学習しました。

  1. Real-Time Communication with WebRTC
  2. WebRTC ブラウザベースのP2P技術

1冊目を買う段階では、国内にWebRTCをメインに扱った書籍が無かった為、英書を購入しました。しかし、英語で書かれていることもあり思うように理解が進みませんでした。日本語のWebサイトを読みながら並行して書籍を読み進めていく形で勉強しましたが完全な理解は出来ませんでした。その後、2冊目の和書が発売され、これを読むことで理解できていなかった部分を理解することが出来ました。その上で、私は自分なりに学校側のセキュリティをいかに迂回するか(あえて言えば攻撃者の視点で)調査した結果、次のことが分かりました。

  • 作成したアプリで通信が上手くいかないのは学校のファイヤーウォールが原因(他のポートが開放された自宅などの環境で通信できる為)
  • 学校から外部に送信できるのはTCP 80,443とUDP 53のみ(主要ポートにテストを行った)
  • WebRTC通信はUDP 49152-65535を宛先とする通信

これを踏まえて次の対策をしました。

  • 宛先ポートの変更が可能なものはポート番号をTCP 80,443へ変更
  • 宛先ポートの変更が出来ない(ポートが不定)もの(UDP)は、TCPでカプセリングして送信

その上で、TCPでのカプセリング, トンネリングには次の3つの技術が候補として上がりました。

  1. TURN over TCP
  2. SoftEther VPN

当初は、1つ目のサーバ側で設定が完結するTURN over TCPを使う予定でしたが、設定をしても学校内−学校外の通信ができませんでした。そこで、2つ目のSoftEther VPNを使ってみたところ学校内−学校外へ通信が出来ました。この時の充実感と達成感は他のものには変えられないものでした。苦労した分だけ喜びも大きかったのだと思います。2つ目で成功したので3つ目の方法は試さずに終わってしまいました。3つ目も今後試したいと思います。

私は、この研究を通じてWeb、サーバ、プログラミング、ネットワークと幅広いレイヤーを横断して問題解決ができたのが非常に良い経験になりました。特に、これらが密接に関わり合っていることが身をもって理解できました。特に、リアルタイム通信をtcpdumpでパケットキャプチャしたときにUDPパケット(WebRTC)が高速で常時流れ続ける様子には非常に興奮し、それと同時に通信の実態を身をもって理解できました。また、ファイヤウォール越えを通じて「守る側の考え方」と「それを迂回する側の考え方」という2つの異なる視点からファイヤウォールについて考えることが出来ました。

共-2(3)

その壁を今経験しているであろう初心者にアドバイスをするとしたら、あなたはどんなアドバイスをしますか?

ネットワークの基礎が理解できていなければ、ファイヤウォールを理解することは出来ないと思います。そのため、私が初心者にアドバイスをするとしたら、最初に「ネットワーク入門書を読んでみる」ことを勧めます。これは既に知っている知識と、新たな知識を体系的に学ぶ上で書籍の情報が最も良いと考えた為です。もし、私がアドバイスする立場であれば以下の2冊を勧めます。

  1. ネットワークはなぜつながるのか 第2版 知っておきたいTCP/IP、LAN、光ファイバの基礎知識
  2. マスタリングTCP/IP 入門編 第5版

書籍を読んだ上で、分からないことがあれば詳しい人に聞いてみたり、インターネットで検索したりすることを勧めます。調べる際にはサイトに掲載されているコードやコマンドを単にコピペするのではなく、「意味を理解」した上で利用することを勧めます。可能であれば、掲載されているコードを自分で書き換え実行してみることを勧めます。

また、学んでいくにあたって「なぜ?」を意識して学ぶのが大切だとアドバイスします。なぜなら、事象の原因(理由)を理解することが本質(仕組み)を理解する上で必要不可欠だからです。上手く動作する場合と動作しない場合のどちらにも、必ず原因(理由)が存在します。上手く動作することが当たり前だと考えていると、どうしても本質を理解することに至りません。そのため、学ぶ上で原因(理由)と結果の因果関係を理解することが大切だと考えます。

共-3(1)

あなたが今年のセキュリティ・キャンプで受講したいと思っている講義は何ですか?(複数可)そこで、どのようなことを学びたいですか?なぜそれを学びたいのですか?

興味を持った講義は多くありました。その中でも特に受講したい3つの講義に絞って書きました。

  • C2 ID連携と認証基礎
  • A5 Availability Challenge ~サービスの可用性を確保せよ~
  • E6~7 インシデントレスポンスで攻撃者を追いかけろ

長くなりそうなので要約

C2 ID連携と認証基礎

  • 自分が当たり前に思っている認証を改めて学びたい。
  • システム設計時に認証と認可は重要な考え方で理解して設計できるようになりたい
  • それぞれの認証における長所や短所を理解して選択できるようになりたい。

A5 Availability Challenge ~サービスの可用性を確保せよ~

  • 三大要件(機密性、完全性、可用性)のどれも疎かにしないバランスが取れたシステムの作り方を学びたい
  • システム設計を1度してしまうと変えることが大変になるから理解して設計できるようになりたい
  • 自分もバックアップを考えずにシステムを設計した結果HDDが壊れた時に復元できなかった経験がある

E6~7 インシデントレスポンスで攻撃者を追いかけろ

  • 情報に着目する力をつけたい
  • 単なるデータ解析だけでなく、隠された攻撃者の意図や狙いを理解できるようになりたい
  • 経験のない未知の領域だからこそ学んでみたい

共-3(2)

あなたがセキュリティ・キャンプでやりたいことは何ですか? 身につけたいものは何ですか?(複数可) 自由に答えてください。

[やりたいこと]

セキュリティ・キャンプでやりたいことは、他の参加者との交流です。他の参加者とお互いの得意分野の知識を共有することで自分のあまり知らない分野についてより深く知りたいです。同世代のメンバーと関わることで互いに刺激しあってより能力を高め合いたいです。また、参加者同士の意見交換の中で共通の直面している課題や問題があれば、共にそれを解決するコードやシステムを考えたいです。さらに、キャンプを通じて「これだけは他人に負けない!」という分野や技術を探したいです。

[身につけたいもの]

【技術面】

これまで以上にハードウェアに関する知識を増やしたいです。なぜなら、ハードウェアとソフトウェアを連携させたモノを作りたいと考えているからです。例えば、同じレイヤー3のパケット処理でも「L3スイッチでのハードウェアベース処理」のほうが「ルータでのソフトウェアベース処理」に比べ高速な処理が可能です。このようなハードとソフトの長所、短所をより深く学び使い分けられるようになりたいです。

さらに、バイナリなど低レイヤーの部分の知識も増やしたいと考えています。なぜなら、バイナリを理解していればパケット解析する際にパケットに含まれるバイナリファイルの挙動など細かい部分まで分析できると考えたからです。現状では、多くの場合でネットワークを介してマルウェアが侵入しています。UTM(IPS)がマルウェアを検知するようにネットワーク分野でもバイナリの知識が必要だと考えています。その為、キャンプを通じてバイナリ解析について深く学びたいです。

【技術以外の面】

各分野の第一線で活躍する講師の方々からそれぞれの分野におけるセキュリティの考え方や経験に基づいた話を聞いてみたいです。なぜなら、常に新たな技術を追いかけることはもちろん大切ですが、セキュリティの根本的な核となる考え方を身につけることも大切だと思ったからです。キャンプを通じて時代が変化しても役立つ基本となる考え方を各分野のパイオニアから深く学びたいです。

また、この先セキュリティを深く学び、触れるにあたり「セキュリティに対してどう向き合うべきか」を学びたいです。セキュリティ技術は使い方を誤れば第三者に被害を及ぼすことも可能です。こうした危うさのある技術を扱う上で意識しなければならないことを改めて学びたいと考えています。また、マルウェア検体や脆弱な環境を扱う上で気をつけるべきこと、プロはどういった方法で実験したり検体を保管しているのか知りたいです。キャンプの中で「セキュリティに関わるエンジニアとしてあるべき姿」について新ためて向き合ってみたいと考えています。

選-A-1.

添付したファイルに記録された通信を検知しました。この通信が意図するものは何か、攻撃であると判断する場合は何の脆弱性を狙っているか。また、通信フローに欠けている箇所があるがどのような内容が想定されるか、考えられるだけ全て回答してください。なお、通信内容を検証した結果があれば評価に加えます。

q1.pcapをWiresharkで開くとTCP通信をしていると分かります。また、http通信をしているとわかります。まず、http通信をWiresharkの 追跡[TCP Follow Stream] -> HTTPストリーム で見ると、Content-Typeが普通では考えにくい量の文字列(通常は text/html など)含まれているのがわかります。試しに「multipart/form-data’).(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS」をネットで検索してみると「Struts2のリモートコード実行可能脆弱性(CVE-2017-5638)」についての記事(http://takahashikzn.root42.jp/entry/2017/03/08/132147)が見つかりました。 そこで、検索エンジンで脆弱性 CVE-2017-5638 について詳しく調べてみました。すると複数のサイトに掲載されているサンプルコードと先のhttp通信のContent-Typeとが「OGNL形式で書かれていること」や共通した文字列 「com.opensymphony.xwork2.ActionContext.container 」と 「com.opensymphony.xwork2.ognl.OgnlUtil@class」を含むなど、類似点が複数あることから脆弱性「CVE-2017-5638」を狙った攻撃だと判断しました。

調べたところ、CVE-2017-5638(S2-045)はApache Struts2に存在する「リモートからコマンド実行可能」となる脆弱性でした。実際に手元に仮想マシン(Virtual Box:Lubuntu)を構築し、実験環境(JDK, Tomcat, Struts)を構築しました。そして、Webで見つけたコードを実行して実際に脆弱性の概要を確かめてみました。

Apache Struts2の脆弱性(CVE-2017-5638)を自分なりに検証した | koyama’s memo

次にq1.pcapのContent-Type部分をテキストエディタに貼り付けて ). で改行するなどして実際のプログラムのように見やすく整形してみました。コードを読んでみると以下の部分が気になりました。

#cmd='cat /etc/passwd'
#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))
#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})

上記2行目ではサーバのOSがWindowsか判定しており、3行目ではWindowsであるのかで実行するプログラムを変更していると分かりました。具体的には、Windowsでは cmd.exe /c cat /etc/passwd , それ以外では /bin/bash -c cat /etc/passwd を実行しようとしているとわかります。つまり、攻撃者は「マシンのユーザ一覧の情報を入手しようとしていた」ことが分かります。

しかし、Windowsの場合はコマンド「cat /etc/passwd」は使用できないため、別のコマンドを実行する必要あります。もし、上記1行目を攻撃者の視点で修正するのであれば #cmd=(#iswin ? ‘net user’ : ‘cat /etc/passwd’) などが考えられました。なお、その際には #iswin から始まる上記2行目と #cmd で始まる1行目を入れ替える必要があると考えました。

#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))
#cmd=(#iswin ? 'net user' : 'cat /etc/passwd')
#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})

これらを踏まえてBurpSuiteを使った検証を行ってみました。

(1). BurpSuiteを起動しFirefoxのプロキシ設定を127.0.0.1:8080に設定
(2). BurpSuiteのタブ[Proxy] -> [Intercept]を開き[Intercept On]を確認
(3). FirefoxでStruts2が動くサーバにアクセス(読み込み中になる)
(4). BurpSuiteで[Headers]タブをクリックして、Content-Typeにq1.pcapからコピーしたContent-Typeを貼り付け

Content-Typeを貼り付け

(5). BurpSuiteで[Intercept On]をクリックして[Intercept Off]にする
(6). Firefoxを開くとコマンド(cat /etc/passwd)の実行結果が表示された

cat /etc/passwd
パケットキャプチャ

 

さらに、パケット全体(q1.pcapの内容全体)に対して分析をしてみました。

まず、TCPは3Way-Handshakeで SYN -> SYN/ACK -> ACKという順にパケットを送信します。Wiresharkで条件式「tcp.stream eq 0」を指定して表示をhttpリクエストのあるTCPストリームに絞ってみました。Follow TCP Streamでストリームを追跡してみると、192.168.74.130:8080(サーバ) -> 192.168.74.1:55552(クライアント) のパケットが0byteであることからサーバからクライアントへレスポンスが帰ってきていないことが分かります。

また、Wiresharkのフローグラフ機能で全体のパケットの流れを見てみると7番目と8番目のパケットの間に約60ミリ秒の遅延が存在していることに気が付きました。7番目以前はレスポンスが1ミリ秒未満で帰ってきていることからすると7番目と8番目の間にキャプチャ漏れかネットワーク遅延が発生していると考えられました。

これに加えて、9,11番目のパケットにFinフラグが立っていることに気が付きました。これはTCPのティアダウン(切断)が起きていると考えられます。そこで、8,9,11,12番のパケットのAck番号とSeq(シーケンス)番号、Win(ウィンドウサイズ)について比較してみました。

  • 8番目 SEQ: 1093, ACK: 1464, Win: 525568
  • 9番目 SEQ: 1093, ACK: 1464, Win: 525568  [FIN]
  • 11番目 SEQ: 1464, ACK: 1094, Win: 525568  [FIN]
  • 12番目 SEQ: 1094, ACK: 1465, Win: 525568

この結果から8,9番目で 192.168.74.1:55552(クライアント) -> 192.168.74.130:8080(サーバ) のクライアントからの切断パケットが送信されています。そして、それに対するACK, AKC/FINパケットが 192.168.74.130:8080(サーバ) -> 192.168.74.1:55552(クライアント) で送信されます。しかし、このキャプチャファイルを読むとTCPストリーム上には11番のパケットの前には9番しかなく不自然に感じました。これは9,11番目の間に10番目のパケット(TCPストリーム:1)とは別に失われたパケットが存在していると考えられます。

次に、q1.pcapの5番目以降のACKを投げたまま「TCP ACKed unseen segment」や「TCP Previous segment not captured」になっている原因を考えてみました。

はじめに、11番目のパケットがWiresharkで[TCP Previous segment not captured]と表示されている原因を調べてみました。この表示の原因についてインターネットで調べてみたところ表示される原因として次の2つが書かれていました。

WiresharkとTCPのエラー » りんけーじ

  1. 直前のパケットが失われた
  2. パケットの順序が入れ替わった

先に述べたように11番目のパケットにはFinフラグが立っていること、12番目のパケットは11番目のパケットとは逆の通信方向(同一であれば11番目の12番目の入れ替わりも想定された) 192.168.74.1:55552(クライアント) -> 192.168.74.130:8080(サーバ) であることを考えると11番目と12番目のパケットは繋がりが無いと考えられました。したがって、11番目のパケットに表示される [TCP Previous segment not captured] の原因は11番目の前に存在すべきパケットが失われたと考えられました。なお、パケットのキャプチャ漏れが発生した原因としては、「キャプチャデバイスのスペック不足(NICやケーブルの転送速度も含む)や途中でケーブルが抜けた」などが考えられました。

続いて、8,9,12番目のパケットに表示されている[TCP ACKed unseen segment]について調べてみました。インターネットで検索してみると次のサイトが見つかりました。

TCP ACked Unseen Segment – Wireshark Q&A

このサイトから次のことが分かりました。

  • TCP ACKed unseen segment はACKデータがキャプチャ出来ていないことを意味する
  • 転送と受取側のACKデータは問題ない
  • Wiresharkがパケットをキャプチャの中から見つけられなかったことを表している
  • これはキャプチャデバイスが早くない時にしばしば普段から起きる

こうしたことから、「キャプチャデバイスのスペックが不足している」可能性が高いと考えられました。これ以外にもケーブルの問題で一時的に通信が遮断された可能性も考えられました

最後に、8番目と12番目のパケットがかなり類似しているのが気になりました。具体的にはSrcPort, DestPort, SrcIP, DestIP, WindowSizeが同一であること、8番目のパケットと12番目のパケットでSeq NumberとAck Numberがそれぞれ1増加していることです。このことから 8番目 -> 9番目 -> 12番目 の順でパケットに繋がりがあるのではないかと思いました。しかし、Ack NumberとSeq Numberが同時に1増加するのは不自然に感じました。これについて私は、おそらく9番目と12番目に失われたパケットが存在しているのではないかと推測しました。

選-A-7

Same Origin Policyに関する脆弱性から自分がもっとも気になっているものを選び、その脆弱性がどのようなものかを説明してください。次に、あなたがもし悪意を持つ側だとしたら、その脆弱性をどのように悪用(活用)するかを想像して書いてください。

JVN脆弱性データベースでSame Origin Policyに関する脆弱性を探してみました。何件か見つかった中で興味を持ったのは「JVNDB-2015-005234 Adobe Flash Player における iframe 内のコンテンツを上書きしてしまう問題」(http://jvndb.jvn.jp/ja/contents/2015/JVNDB-2015-005234.html)です。この脆弱性では、Adobe Flash PlayerがSame Origin Policyを回避してしまい、iframeタグ内のコンテンツを不正に書き換えてしまいます。つまり、Flash Playerの脆弱性を利用することでユーザの意図しないサイトを表示させること(誘導)が可能になるということです。

もし、私が悪意を持つ攻撃者の視点で考えると次のことが考えられました。

まず、この脆弱性を利用してiframe内コンテンツを書き換えて、自分の用意したWebページに誘導します。この用意したWebページにはAdobe Flash Playerの脆弱性を利用したドライブバイダウンロード攻撃を実行させるプログラムを配置しておきます。こうすることで、ユーザに気づかれないままマルウェアに感染させることが出来ます。そして、マルウェアによって遠隔操作をしたり不正送金したり、ランサムウェアを配布することで身代金を要求したりすることが出来ます。Webの記事(ドライブバイダウンロード攻撃で悪用される脆弱性の97%がFlashによるもの -INTERNET Watch)によれば「ドライブバイダウンロード攻撃の97%はAdobe Flash Playerの脆弱性によるもの」であるため、これら2つの脆弱性を組み合わせることで高い割合で攻撃することが可能だと考えられました。

この対策として以下が考えられました。

  • Adobe Flash Playerを最新版にアップデートする
  • Adobe Flash Playerの利用が必要か考え、不要であればアンインストールする
  • Adobe Flash Playerをユーザの確認なしに実行するといった設定を見直す(確認してから実行に変更)
  • Webブラウザ, OSに最新のアップデートを適用する

選-A-8

いわゆる「セキュリティ技術」の中で、あなたがもっとも興味があるテーマひとつについて、好きなだけ語ってください。

私が興味のあるテーマは「ネットワーク・セキュリティ」です。

ネットワークの面白さ

ネットワークはプログラミング以上に面白いと思っています。その理由にネットワークという分野の広さがあると思います。単にネットワークといってもOSI参照モデルにある通り7階層にもわたります。低レイヤー(物理層)から高レイヤー(アプリケーション層)までの全ての技術が組み合わされることでネットワークが成り立っていると考えれば奥深いことがよくわかります。

私がネットワークを学んでいて特に面白いのはトラブルシューティングです。ネットワークのトラブルは「インターネットにつながらない」や「サイトにアクセス出来ない」など種類も様々です。そうした、原因が分からない問題に対して「何が原因なのか?」と考えてコマンドやツールを駆使して原因を切り分けることが「論理的なゲーム」のようで面白いです。また、原因が複合的に発生している場合は一つひとつの問題を分けて考えるなど複雑であるほど面白いです。

さらに、ネットワーク上で何かを実現したい時に「どんな技術同士を連携させることで可能か」と考えたり、「身の回りにあるシステムを構成するネットワーク技術」について考えたりすることも面白いです。

このようにネットワークは様々な技術が組み合わさることで成り立っており、それぞれの技術を学ぶことが非常に面白いです。また、技術を知ることで今までと違った視点で物事を考えられるので新鮮でもあります。

セキュリティ分野との出会い

Twitterで見つけたSECCON 2015 福島大会(サイバー甲子園)に興味を持ち、友人を誘って参加しました。参加してみると思っていた以上に難しく悔しい思いをしました。それと同時に、同世代で高得点を取る参加者の存在に圧倒されました。もちろん、CTFが全てではありませんが、ネットワークを学んでいるのにキャプチャファイルが渡された時に解析できないようではまずいと思いました。自分も高得点を取れるような「スーパCTFプレーヤーになりたい」と思い、セキュリティ分野を勉強することにしました。

セキュリティ分野に興味を持ってから

サイバー甲子園後は、Twitterでセキュリティ系の人をフォローしたり、セキュリティ記事をRSSで購読するなど情報収集をはじめました。また、過去にNHKのプロフェッショナル仕事の流儀で名和利男さんが出演されていた放送を見てセキュリティ技術者の仕事内容やその姿に強く惹かれました。

攻撃側の発想に脱帽

セキュリティ記事を購読して情報収集していて驚き、感心してしまった記事が以下です。

遠隔操作ウイルスの制御にDNSプロトコルを使用する事案への注意喚起 | LAC WATCH | 株式会社ラック

私は、http経由でC&Cサーバと直接通信するマルウェアがあることは知っていました。しかし、この記事ではC&C通信にUDP 53を使用したり、C&CサーバにTwitterなどのSNSを利用したマルウェアが存在していると書かれていました。この記事を最初に読んだ時に「そんな発想があったのか」と驚き、それと同時に攻撃者の発想の柔軟さを恐ろしく感じました。この経験を通じて、「どうせ、〜〜だろう」といった固定観念(決め付け)を払拭したほういいことを身をもって学びました。

ネットワーク技術の理解

セキュリティを意識してネットワークを構成する技術を学んでみると、その一つひとつがセキュリティ上も意味を持ってくるのだと感じました。例えば DHCP Snooping はホワイトリスト式(MACアドレス登録式)のDHCPサーバと組み合わせることで、許可しない端末の接続を防ぐことが出来ます。例えば、悪意を持った第三者が端末をネットワークに接続して固定IPを設定してもDHCP Snoopingによって弾かれるため通信出来ません。また、DHCPサーバからアドレス取得を試みてもホワイトリストに載っていないMACアドレスであるためIPアドレスはリリースされません。

ほかにも、VLANやファイヤウォール、IEEE 802.1xなどセキュリティに役立つ技術が多数存在していることに気づきました。このようにセキュリティを学ぶ上でネットワーク技術の理解が重要であることが分かりました。

手を動かすことの大切さ

公開されている情報をもとに自分で手を動かすことで、より理解が深まり発見も多いことが分かりました。

例えば最近、話題になっているWannaCryについて検証してみると身をもって脆弱性の危険度が理解できました。実際に、EternalBlue(エクスプロイトキット)とDoublePulsar(バックドア)を入手して仮想環境マシン同士で攻撃する側、攻撃される側の環境を構築して実行してみると攻撃される側で任意の操作が実行されていることが分かりました。

また、WannaCryの検体を入手して(隔離環境で)実行してみると調べて知っていた通りの挙動をすると同時にその増殖能力に驚きました。その際に、検証したVirtualMachine(Windows 7)のネットワーク設定をパブリックにしておくと攻撃を受けずホームにしておくと攻撃を受けることに気づきました。これはパブリックにしておくとWindowsのSMBサービスが起動しない為であると考えました。こうした事実は手を動かすことではじめて気付けたことだと思います。その為、これからも手を動かして自分で確かめていきたいと思います。

自ら積極的に学ぶ

最近、セキュリティ系の勉強会に積極的に参加するようにしています。勉強会に参加すると知らなかった知識を吸収することができ、最新の動向や対策など参加しなければ得られない知識が多くあることを痛感しています。特に、「OSSセキュリティ技術の会 第一回勉強会」ではSELinuxが生まれた経緯やアクセス制御の方式などセキュリティの根本的な考え方や歴史的背景を知ることが出来ました。

今やっていること

今、やろうとしていることはLinuxカーネルのソースコードを読むことです。大学の先生にキャンプのことを相談した際に、「Linuxカーネルのソースを読んでみてはどうか」と勧められました。前から読んでみたかったのですが、ハードルが高い用に感じて出来ていませんでした。そこで、kernel.orgからソースをダウンロードしてネットワークまわりから読み始めています。tcpなどは2000行近くあり大変そうなので、まずicmpを読んでいます。ネットワークまわりのソースを読むことはC言語の美しいソースを見ながらプロトコル構造を学べるという一石二鳥であり、非常に面白いです。

次のステップへ

私が今、やってみたいと考えているのは、4Kに代表される「高解像度動画を含むパケットのライブデコーディング」です。今後、高解像度の映像がネットワークを流れると予想されます。こうした動画をキャプチャしてそれをライブでデコードする技術は既に存在しますが、これを高解像の動画データで行う事例は聞いたことが無いのでやってみたいと考えています。これにはソフトウェアだけでなくハードウェアレベルでも処理をすることが必要になってくると考えています。最近、注目されているFPGAを利用してこうしたことが出来ないかと考えています。この技術が役に立つ場面は思いつきませんが何かの機会に役立つのではないかと思います。

私は、まだ知識が不十分です。そのため、これからも自ら行動して知識を吸収していきたいと考えています。キャンプを通じて、より知識を吸収する速度を加速させたいと考えています。


以上です。ちなみにパケット問は「実践パケット解析」という本が非常に役立ちました。