水深1024m

技術的なメモとか日記的なもの

iOS9 で導入される ATS とは結局何なのか

iOS9 で導入される ATS (App Transport Security) の話です。 ATS は OSX, iOS アプリケーションが NSURLConnection, CFURL, NSURLSession を利用してサーバに接続する際 現時点で最善に近いセキュアな接続をデフォルトとする仕組みです。 この記事で言いたいことはだいたい 公式ドキュメント に書いてあるのですが、"よくわからんから全てにおいて ATS を無効化する" で終わらないためにどうすれば良いかについて書きます。 個人的に AWS をよく使っているので、AWS における事情なども適宜付加します。

何が変わるのか

"Default Behavior" の項目に記載されていますが、 ATS が有効になっていることによって外部接続先に要求される要素は、以下のものです。

  • サーバは TLS 1.2 をサポートしていなければならない
  • 利用できる暗号 (正確には Cipher Suite) は、Forward Secrecy を提供できる (かつ、ドキュメントに示されている) ものに限られる
  • 利用されるサーバ証明書は SHA256 以上のハッシュアルゴリズムによって署名されており、2048ビット以上の RSA 鍵、もしくは 256ビット以上の ECC 鍵が使われている必要がある
    • 検証できない証明書はエラーとなり接続ができない

また当然というか前提ですが、サーバは HTTPS に対応している必要があります。

対応の要否と対応方法について

接続先サーバが HTTPS に既に対応しているのであれば、あとは上に書いた3つの条件を満たせば問題なく通信できます。 cipherscanQUALYS SSL Labs の SSL Test を使うとこの条件を一度に検証できるでしょう。 以下に、SSL Test を利用した場合の例について記載します。 (検査対象のドメインがしばらくトップページに載るので、イヤな方は "Do not show the results on the boards" にチェックを入れてください)

TLS 1.2 に対応しているかどうかは "Protocols" 欄を見れば分かります。 f:id:kani_b:20150908000129p:plain

対応していない場合は TLS 1.2 を有効にする必要があります。現代のソフトウェアで TLS1.2 を有効にできない環境は意図的に設定しない限りそう無いと思いますので、 有効にしてください。

提供する Cipher Suite の確認は "Cipher Suites" 欄で確認できます。 横に小さく FS と記載されているものが Forward Secrecy (前方秘匿性、詳細はググれば分かります) を提供する CipherSuite です。 より厳密には、Apple の公式ドキュメント に記載されている "accepted ciphers" に記載があるものが含まれていれば OK です。 f:id:kani_b:20150908000149p:plain

こちらも、ここ数年のサーバ環境であれば問題なく設定できると思います (AWS ELB であれば、対応する CipherSuite にチェックを入れるだけです)。

最後に気づきにくいのが、サーバ証明書のハッシュアルゴリズムと鍵の強度について。 RSA 公開鍵長については2048ビット未満の鍵長を使った証明書発行が既に禁止されているため、 この条件を満たせないことがほぼ無いかと思われます。 問題となるのは "SHA256 以上のハッシュアルゴリズムによって署名されている" 部分でしょう。 AWS 公式サイトの結果を例とすると、以下のように、Signature Algorithm として SHA256 という表記が含まれていれば問題ありません。 f:id:kani_b:20150908000758p:plain

対応していない場合は、例えば SHA1withRSA といった表記になります。 こちらはまさに移行期間真っ最中 (いわゆる SHA-2 移行) というところですので、対応がサーバによってまちまちだと思われます。 最近証明書を購入された方であれば、明示的に SHA-1 証明書を購入していない限り問題はありません。 長い有効期間の証明書を購入している場合でも、多くのケースでは既に認証局側に SHA-2 証明書を再発行してもらえば移行することが可能なはずです。 ただし、SHA-2 証明書に移行することにより、いわゆるガラケーはじめ未対応端末での接続ができなくなりますので、クライアント環境をよく確認して移行するようにしてください。

対応ができないケース

多くの場合、特に iOS アプリケーションは開発者が直接面倒を見ていない (例: 広告配信) サーバに接続することがあると思います。 そうした場合、 Web サービス全体の HTTPS 事情を見ていても、 iOS9 リリースと同時に全接続先で ATS を有効にすることは困難だと思います。 そのため、最初のうちはまず自社 (あるいは自身) で作っている接続先を ATS 対応できるようにした上で、接続先サーバの対応を待って完全 ATS に切り替えていく必要があるでしょう。 私は検証できていませんが、ATS はドメインごとに有効/無効を指定できるようです。 またドキュメントにも書いてありますが、個々の要素 (TLS サポート、Cipher Suite など) を個別に無効にすることもできます。 SHA-2 証明書にまだ移行できない場合でも他の要素は有効にできるというケースも多いのではないでしょうか。

ATS 無効化は "セキュアではない" のか

諸説あるとは思いますが、ATS を切ることそのものが危険な状態に繋がるわけではなく、 こうしたものをあまり理解せずに切ってしまったり、切ったまま対応を考えないといったことが危険な状態を招くと考えています。 (ATS はあくまでベストプラクティスへの準拠を要求するものであり、ATS を切ったとしても安全な通信は可能です) 個人的には、世の中の HTTPS 化の流れは避けられない (かつ、移行すべき) と考えているので、歓迎している動きではあるのですが、 Apple が ATS で示しているものについて、あまり理解されていないのかなーと感じたので書いてみました。

なお、私は普段 iOS / OSX 開発に携わっているわけではありませんので、間違いなどがありましたらご指摘いただけると嬉しいです。

AWS ウルトラクイズで優勝してきた (AWS Summit 2015)

ちょっと日が経ってしまったけど、先週AWS Summit 2015 という AWS のカンファレンスに行ってきました。

http://www.awssummit.tokyo/

参加自体は今年で3回目。ちょうど社会人になってから毎年参加していることになります。 個人的に今年のメインはデベロッパーカンファレンス (DevCon) でした。 去年の Summit に行った時に、だんだんターゲット層が変わってきたなーというのを 発表内容とかを見ながら思っていたのだけど、ちょうどそう思う人達に向けたようなカンファレンスでした。来年もぜひお願いします。

どのセッションでも発表中はカメラのシャッター音が鳴りまくっていて、登壇者が「資料あとで公開します」と言っても鳴り止まなくて、大変だなーという気持ちになりました。

個々の発表内容については資料とか映像を参照するとして、全体的な感想としては、 これまであまり繋がりのなかった分野の技術者 (テレビ局とかもっと大きい規模のところ) と AWS で繋がって交流できているのは面白いなーと思いつつ参加していました。 データセンターという枠がなくなって、共通化される部分が大きくなったというのがあるのかな。

全セッション終了後に最後のイベントとして JAWS-UG (勉強会) があり、そこでは AWS ウルトラクイズという、AWS に関するクイズ大会がありました。優勝賞品はラスベガスで行われるカンファレンス re:Invent の参加一式 (渡航費宿泊費参加費)。 新卒1年目、2年目と参加して両年とも4位(入賞は3位から)という微妙すぎる順位で毎年帰ってきていたので、今年は一発当てたいと思っていたところ、優勝しました。 ガソリン入れて気合注入と思っていたら緊張のためか開始時には4缶空けていて途中の問題をよく覚えていないのですが、最後の問題はその日の朝にリリースされた Kinesis のパラメータの変更 (PutRecord の最大サイズ) でした。 ちょうど Kinesis 使いたい構成を考えていた時に読んでいたリリースだったこともあり、まあ運が良かったと思います。

ちなみに AWS は色々なリリースを粒度に応じてか、色々な場所で公開してくる (AWS Blog, 各サービス (Mobile とか Security) の Blog, forum, etc) ので、フィード購読して流し読むと"えっそんな変更あったの"が少なくなります。
今の自分の仕事は "AWS を使うこと"ではなく "サービスをユーザに届けること" なので、そんなん細かく読んでる意味あるの?みたいな自問自答もしますが、むしろ自分たちが(半分)身を預けてるサービスだし、とことん使い倒さないと意味ないなーと。 別に AWS だろうと GCE だろうと Azure だろうと同じですが、いわゆるロックインを恐れて中途半端に使う状態が一番最悪ですね。 むしろ他のサービスもとことん使っていった上で最適なものを選んで使うことができれば、それが一番健全なのかなーと思います。各社色々なサービスを出してきていますし、もうちょっとするといわゆるマルチクラウドのような環境で色々できるようになるんでしょうか。楽しみです。

というわけで、同じく1年目から運良く参加し続けている re:Invent に今年も無事参加できることになりました。10月なのでまだまだ先ですが楽しんできます。わーい。

ISUCON4 予選2日目2位通過

できました。楽しかったー
ISUCON については公式ページをご覧ください。
ISUCON公式Blog

.dat というチームで参戦しました。チームメイトは @TakatoshiMaeda@y_matsuwitter というメンバー。
以前一緒の会社で働いてて、@TakatoshiMaeda とは現職でも同僚。
一緒に朝までデバッグしてたりつらいことを共有してきた仲ということもあり、色々やりやすかったです。

今回の ISUCON4 予選最大の誤算は ShellShock と AWS リブート祭でした。 ISUCON の性質上 Web インフラ界隈の参加者が多いようですし、 他の参加者でも巻き込まれた方々が多かったんじゃないでしょうか。お疲れ様でした。
ほんとは僕の自宅でモニタとか持ち込んで前日からワイワイやる予定だったのですが、 状況を冷静に考えて会社のオフィスでやることにしました。
祭が 3:00 AM - 7:00 AM JST という時間ゆえに当日影響を確認しつつ眠れたのは 5:30 AM という状態で、 @TakatoshiMaeda に「オフィスのこのへんで寝てるから起こして」と書き残して眠りについたら、
本人曰く「遠足前の小学生」だったテンションでその3時間後に叩き起こしてくれました。感謝。

#isucon 4予選参戦記 - 2日目暫定3位でした - takatoshi-maeda’s diary
#isucon 2014予選二日目を三位で通過した話 - Qiita

うちのチームがやったことは大体上記 URL の二人の記事に書いてありますので今更書くこともそんなに無いと思います。
@TakatoshiMaeda が全体の分析や初期のサーバセットアップ周りをめっちゃ前から準備してくれていて、当日非常にスムーズに開始できました。 大体11時前には環境構築、初期のベンチマーク、ひと通りの計測、コードリーディングをざっと済ますことができたことは非常に大きかった。
うまくいった理由は特に以下の3点だと思っています。

  • 3人の得意分野がいい感じにばらけていて補完できた
  • 上にも書いたように初期準備が非常にスムーズにいった。@TakatoshiMaeda++
  • ベンチを取りながら最初にガッとコードを読み、当初決めた戦略 (martini の入れ替えとフル Redis 化) がそのままピッタリハマった。

最初にコード読んだ段階で、ロジックの整理しやすい login_log 周りにかなりのコストがかかっており、レギュレーションの確認(再起動後もデータを保っている必要がある)がとれたので、かなり初期の段階で方針については合意できました。
僕は kernel, nginx, Redis のチューニング、あとはアーキテクトっぽいこととデバッガぽいことくらいしか仕事がなかった気がします。実際ノーチューンというか削れるだけ削りましたみたいな my.cnf は一度も触りませんでした。
あとはベンチマーク中の I/O などを眺めつつ、できるだけパフォーマンスを上げられるような設定を詰めていきました。
全部1サーバでやるという制約上、多少なりともオーバーヘッドのあるネットワーク通信を使いたくなかったので、 nginx - Go App - Redis 間は全て UNIX domain socket に変更していて、ベンチマーク的にはこれも結構効果が大きかったのではと思っています。
カーネル周りのチューニングは ISUCON 頻出というか現実世界でも頻出な TCP 周りの設定を入れ、 nginx は基本的なチューニングと静的ファイルを nginx で返すように設定。 あとは細かい点を直したり、他の二人の実装レビューしたりデバッグ手伝ったり、で終了。
何度も再起動したり AMI から作りなおしたりして確認後に AMI 提出。 暫定3位でしたが正式順位発表で2位となりました。
ISUCON4 本戦出場者決定のお知らせと本選出場者の利用言語比率 : ISUCON公式Blog

ISUCON では普段やっていないことはできないし、大胆なことをやるなら初期の段階にやるのが良いというのをなんとなく察していたので、状況によっては巻き戻して MySQL でやれるだけやることも(自分の中では)考えていたのですが、 @y_matsuwitter の進撃の実装力により何ら問題なく変更が完了したので杞憂に終わりました。 よかった。

感想と本戦に向けて

予選は1サーバのみで全てやるという制約上、とにかくメモリに載せるという戦略がどうしても取りやすくなってしまうとは思うのですが、単にメモリに載せるだけではダメで保持しているデータをどうするか、などの問題も絡んでくるので、やっていてとても楽しかったです。普段の仕事でもやるようなことを考えるので、"あ、これゼミでやったところだ!!!" 的なことも色々とありました。
本戦は過去の例を見ていると複数のサーバを使うことになりそう、つまり今回あまり重要な要素ではなかったネットワークをどう使うかという部分が重要になってきそうで、非常に楽しみにしています。
尻に火を付けられてガリガリやっていく感覚というのは健康上あまりずっと味わいたくはないわけですが、たまにやるエクササイズとしては最高ですね。
直前になって ShellShock みたくおしゃれニックネームとかおしゃれアイコンとか特設 Web サイトが登場するような脆弱性が出ないこと、インスタンスが大量リブートしたりすることのないことを祈りつつ、楽しみに本戦を待ちたいと思います。
運営のみなさま、大変だとは思いますが引き続きよろしくお願い致します!

AWS で作るシステムのセキュリティ考

AWS アカウントを複数人で使ってシステムを作っていく時に、 セキュリティの面からやるべきことについて。 主に Web アプリケーションを想定した内容ですが、特に書いてあることは特殊ではないと思います。 各所の Blog にも記事書かれてますが思っていることをつらつらと書いてみます。 なんか変なこと言ってたらご指摘ください。

参考: AWSのセキュリティが気になるなら読んでおくべきAWSセキュリティのベストプラクティス - yoshidashingo

はじめに (AWS アカウントと IAM ユーザ)

前提というか用語の話。

  • AWS アカウント
    • アカウント作成時のメールアドレス、パスワードでログインして使うユーザ
  • IAM ユーザ
    • AWS アカウントから発行できる、ユーザ名とパスワードでログインして使うユーザ

AWS アカウント周り

AWS アカウント (ルートユーザ) で作業できないようにする

AWS アカウントは Linux で言う root ユーザみたいなものなので、アカウント内全てのリソースにアクセス可能です。 構築運用面で最初に IAM ユーザを作成する時以外、アカウントで作業する必要があることはほとんどないです。

  • 操作用の IAM ユーザを作る
  • AWS アカウントに紐付いてる Access Key とか証明書を消す
  • AWS アカウントに MFA を設定する

あとは、重要なシステムのあるアカウントであれば MFA のハードウェアキー買って設定して 金庫にでも突っ込んでおくと良いです。

IAM ユーザを使う人ごとに分割する

IAM を使うと、作業者個人単位で専用のユーザを持てるので、これを使いまわす必要はどこにもないです。 使う人それぞれに IAM ユーザを作成して、必要に応じて権限設定して使いましょう。 CloudTrail 使えば大体の操作は後からトラックできるようになります。 例えばいわゆる Admin な人たちにはほぼ全権を渡しておいて、そうでない人には Describe 系の API だけ渡すとかの切り分けをしておきます。 IAM にも MFA が設定できるので、好みに応じてハードウェア買うかスマートフォンにアプリ入れて MFA を有効化しておきましょう。 アクセスキーとシークレットキーはいずれにせよそれなりに死守する必要があることに気をつけてください。 Mac な人なら envchain 使うとなお良いと思います。

OS X キーチェーンから環境変数をセットするツールを作りました - クックパッド開発者ブログ

難点はユーザ数が増加していくと管理するのが難しくなるところでしょうか。ここはまだうまい解が分からないところです。。。

アプリにキーを埋めない

例えば EC2 で特定の S3 バケットにファイルアップロードするアプリとかバッチを動かす時など。 一昔前まではそのアプリ用の IAM ユーザ発行してキー埋めたりすることもあったと思いますが、 キー埋めないで IAM Role for EC2 Instance 使いましょう。

Amazon EC2 の IAM ロール - Amazon Elastic Compute Cloud

AWS SDK 使える環境であれば大体の実装ではキーの取得とローテーションへの追随もやってくれます。 サーバ設定もデプロイも自動化したけどキーの配布どうしよう、みたいな問題はこれで大体解決するのでは。 難点は今のところインスタンス"起動"時にしかロール指定できないこと。Stop/Start じゃダメです。 イミュータボーでディスポーザボーなインフラをお持ちの各位であればそんな難しいことではないのでは。

Unix アカウント周り

IAM アカウントは分離していても EC2 インスタンスのユーザは ec2-user や ubuntu ユーザを共有して使っている方も多いと思います。 が、インスタンスを扱うユーザが多くなるのであれば、OS レイヤでの権限分離もちゃんとやる必要があります。 Chef とか Puppet で管理する手もあるんですが、ユーザ情報を変更するたびに全台への apply が必要なのも厳しい感じがします。 ここを分離したいのであれば今のところはおとなしく LDAP を使うのが良いでしょう。 OpenSSH を使っていると、ちょっと前まではパッチ当てない限り公開鍵認証にするために LDAP ユーザであっても 対象のインスタンスに事前に公開鍵を配布しておく必要があったのですが、 OpenSSH 6.2 から LDAP 側に保持している公開鍵を読む、みたいなことができるようになったので、ここも心配する必要がなくなりました。

ref. OpenSSH 6.2を使って公開鍵認証もLDAPで行いたい。 - Qiita

ただし LDAP サーバが壊れると全てが崩壊するので、cloud-init で作成されるユーザと EC2 のキーペアは無効化せずに あくまでキーペアを共有しない (これも金庫とかに放り込んでおく) だけに留めておいたほうが良いかもしれません。

暗号化

AWS の例えば S3 や EBS にはサーバサイド暗号化 (SSE) という機能がついてます。 暗号化鍵の管理を AWS 側がやってくれて、使う側としては透過的にデータを暗号化できる機能です。 透過的にというのは要は、API 越しにデータ送信する時は平文で、送信後格納されるタイミングで暗号化されて、 読み出しの際は復号されたデータが降ってくるというやつです。 これを有効化するだけで全てのデータが暗号化されて最高便利という機能に見えるのですが、 API の認証が通れば復号化されたデータが降ってくるので、実際に権限外のアクセスから保護できるケースはそんなに多くないです。 例えば AWS 側の管理者が悪意を持ってアクセスしてきたり、AWSAPI のバグで他人のオブジェクトにアクセスできたり、 AWS がセキュリティペーパーに書いてある通りじゃなく使い終わった HDD を適当に捨てていた場合なんかには保護できるかもしれませんが、 それよりも開発者の誰かがアクセスキーを Github に visible な状態で突っ込んでいたり、メールアドレスとパスワードを使いまわしていて AWS アカウントにログインされたりして死ぬ可能性のほうが遥かに高いんじゃないでしょうか。 というわけで暗号化については"それで守れる範囲"をちゃんと考えた上で、必要な場合はちゃんと実装したほうが良いでしょう。 例えば S3 を例に挙げると、 AWS SDK for Java, .NET, Ruby には S3 にアップロードする際クライアントサイドで任意のキーを渡して暗号化してからアップロードできるようになっています。 これは API がどうこうという話ではなく完全にクライアントサイドで暗号化しています。

Protecting Data Using Client-Side Encryption - Amazon Simple Storage Service

あるいは鍵を AWS に渡して暗号化してもらう SSE-C というのもあります。

Protecting Data Using Server-Side Encryption with Customer-Provided Encryption Keys (SSE-C) - Amazon Simple Storage Service

完全な SSE より、R/W に実際の鍵が必要な分保護できるケースはもちろん増えますが、端的には "暗号鍵を渡すことと引き換えに暗号化処理をオフロードする"というものなので、 暗号化を考えた時にこれがしっくりくるケースってあるのかなーと感じています。

EBS でも、AWS サイドで暗号化の手段が用意されています。

Amazon EBS Encryption - Amazon Elastic Compute Cloud

副次的な効果として、スナップショットを public にしたりアカウントをまたぐことが仕組み上できなくなりますので、 この効果だけ欲しいという方には良いのかも。そもそもの懸念については S3 のものと大差ないと考えています。 自前で暗号化やるのであれば、パートナーが提供してるソフトウェア使う手もありますし、 Linux であれば dm-crypt 使っても良いと思います。

ここだけ長くなっちゃいましたが、要は何を何から守るのかちゃんと考えて実装しようよというだけの話です。

ロギング/監視

オンプレ環境との大きな違いを挙げるとすれば、AWS 上ではコアスイッチでミラーポートを使ってネットワーク監視するみたいなことが難しいので、 基本的に各インスタンス上で監視を行う必要がある点でしょうか。 トレンドマイクロの DeepSecurity とかはそういったアプローチだと思います。

AWS API 周りであれば前述の CloudTrail を使うのが一番良いんじゃないでしょうか。 全サービスをカバーしているわけではないということに留意する必要がありますが。 ファイルは S3 に json で吐かれるので、MongoDB なり ElasticSearch に突っ込んで検索可能にしておくと トラブルシューティングの時などにも捗るとおもいます。 ログを S3 に置いておくのであれば、そのバケットのアクセス権をちゃんと設定するのは必須として、MFA Delete も有効化しておきましょう。

MFA Delete - Amazon Simple Storage Service

おわり

正直粒度もバラバラでまとまらないですが、ざっと書いてみました。 AWS 固有のことが(アカウントとか)それなりにはありますが、その他はこれまで普通にやられてきたことと大差ないと思います。 ここでカバーしていない内容も多々ありますが、そういうのも徐々に書いていきたいです。

完全にオフトピックですが、イミュータブルインフラとかテスト駆動インフラみたいな話って セキュリティ運用とも相性が良いよなあと最近考えています。 例えば Heartbleed なんかが記憶に新しいですが、ミドルウェア脆弱性があってバージョンアップしないとなんて時も パッチしたミドルウェアの検証は(もちろんカバレッジによりますが) Serverspecinfrataster で可能ですし、 実際の入れ替え作業も、既存のサーバを止めてバージョンアップするのではなく新しい構成のサーバを起動して入れ替えるだけで良ければ、かかる労力はかなり小さくなるでしょう。

最近の Web インフラ界隈の流れにうまいこと乗りつつ、より便利でセキュアな環境を作りたいですね。 以上です。

触って試す AWS MFA

相次ぐパスワードリスト攻撃もあり、いわゆる MFA (Multi-Factor Authentication) が使えるサービスが増えてきました。 AWS でもデバイスによる MFA ができるようになっています。 この仕組みとかについて書きます。 AWS について主に書いていますが他のサービスで使われているものも大体同じ (少なくとも GitHub とかは) はずです。

AWS MFA で使われている仕組み

IAM の FAQ でも書かれていますが、 AWS で使うことができるのは TOTP (Time-based One-Time Password Algorithm) です。 アルゴリズムの説明は こちら などがわかりやすかったです。 TOTP の RFC もそんなに分量ないので読んでみると良いと思います。 ざっくり言うと TOTP がしているのはすごく単純なことで、

  • 認証を行う側と認証される側で同じ鍵を共有しておく
  • お互いが同じ鍵を用いて同じ計算方法でワンタイムパスワードを生成する。生成時、変化する要素として現在時刻が使われる

これだけです。鍵の共有時を除けば認証する側とされる側で通信する必要がないので、 スマートフォンを MFA デバイスにしている場合それがオンラインである必要はありません。

ちょっとコード書くとその様子を眺めることができるので後述します。

ハードウェア MFA とバーチャル MFA

AWS の MFA ではハードウェア MFA デバイスとバーチャル MFA デバイスの2種類が使えるようになってます。

ハードウェア MFA

AWS の場合、ハードウェア MFA は専用のベンダーが一社あり ここ から購入します。 現在は小さい USB メモリみたいなものとカード型のものを選ぶことができますが、 カード型の方は日本から買えないようです。無念。

ベンダーのページに記載されていますが、これらも Time-based との記載がありますので TOTP が使われているものと思われます。 使っているアルゴリズムは同じですが、ハードウェア MFA とバーチャル MFA の違いは鍵の共有方法にあります。 若干推測ですがハードウェア MFA の場合、ベンダーはハードウェアのシリアルナンバーとそれに紐づく鍵を何らかの安全な方法で AWS 側に渡しているはずです。 そのため、このハードウェアを購入して AWS アカウントに使おうとすると、シリアルナンバーを入力するよう求められます。 このシリアルナンバーは実際の生成に使われるわけではなく、入力するとそれに紐づく鍵が AWS 側で呼び出されて、 以降その seed を元にワンタイムパスワードを計算するようになるという仕組みです。 また、このハードウェアには耐タンパー性がありますので、外から鍵を盗みとられるという可能性も少ないと思います。

バーチャル MFA

ハードウェア MFA の他にバーチャル MFA を選択することもできます。多くの人はこちらを使っていると思います。 バーチャル MFA の場合もパスワードの生成方法はハードウェアと全く同様ですが、スマートフォンアプリ (Google Authenticator, Amazon MFA) など 専用ハードウェアではないものの上で生成を行うところが差異です。 また鍵の共有方法も違います。ハードウェア MFA の場合鍵は予め AWS 側に渡っていますが、 バーチャル MFA の場合 AWS 側で生成した鍵を手元のデバイスで受け取る必要があります。 手段は多くの場合2通りで、QR コードを使うか鍵を手で入力します。

QR コードには、アカウントの名前や鍵, 認証の種類 (TOTP or HOTP) が含まれています。 Google Authenticator の wiki に詳しい説明が載っているので興味のある方はご参照ください。

キーを手動で入力する場合は、アカウントの名前などは情報として含まれないため手動で入力する必要があります。 また、鍵が格納されるのは結局スマートフォン上の記憶領域なので、その安全性はそのアプリや端末のセキュリティレベルによるというところが ポイントかと思います。

自分でやって観察してみる

ruby だと ROTP という gem があって、この OTP 周りの処理をやってくれます。 コード読んでみると実際どういう処理をやる必要があるのか見えてくると思います。 https://github.com/mdp/rotp

require 'rotp'
key = ROTP::Base32.random_base32
totp = ROTP::TOTP.new(key)
puts key
puts totp.now

こんなコードを書くと、16文字の base32 で生成されたキーと、それを元に生成したパスワードが返ってきます。

$ ruby rotp.rb 
amxz5qyc54sap3qp
271576

ここで生成されたキーを Google Authenticator に入力してみます。 サービスを新規追加する画面から、手動で入力 を選択し、アカウント(適当な名前) とキー (生成されたキー) を入力します。 時間ベース (TOTP) にチェックが入っていることを確認して完了ボタンを押すと、他のサービスに並んでパスワードが表示されると思います。

では、コード側でも生成されたキーでパスワードを生成するようにしてみます。

require 'rotp'
totp = ROTP::TOTP.new("amxz5qyc54sap3qp")
puts totp.now

これで totp.now を watch -n 1 とかで Google Authenticator といっしょに眺めてみると、 お互い大体同じタイミングで値が切り替わるのがわかるとおもいます。

手元で OTP を生成して AWS 認証してみる

注: 大体どんな感じで MFA が動いてるのか観察するためにやっているので、Web アプリ置いて生成させてこれでデバイス要らず便利〜みたいなことはやらないほうが良いと思います。

IAM で適当なユーザを作って MFA を有効にします。(実際の値は雑に消しました)

f:id:kani_b:20140706173554p:plain

ぱっと見切り替わるように見えないのですが、この画面で "Show secret key for manual configuration" をクリックすると 設定用のキーが出てきます。これを先ほどのコードで使うようにします。

f:id:kani_b:20140706173612p:plain

require 'rotp'
totp = ROTP::TOTP.new("your_mfa_key")
puts totp.now

これで6桁のワンタイムパスワードが出力されるようになったと思います。watch -n 1 ./rotp.rb とかしておくと時間経過とともに変化していくはずです。 出力されたワンタイムパスワード2つ (最初に出力されたものと次に出力されたもの) を入力するとアクティベーションが完了します。

実際にログインしようとしてみると、コード側で生成されたワンタイムパスワードが使えることが確認できます。 面白いですね。

その他

さっきも書いた通り、QR コードは鍵やその他の情報をやりとりするだけのものなので、 同じ鍵を持つデバイスを複数個作ることができます。 つまり同じ QR コードをスキャンしておけば iPhone と併用している Android とかもう使わなくなったスマートフォンなどを MFA デバイスのバックアップとして持っておくことが可能です。 その分鍵がある場所が増えることになるのでユースケースによりますが。

MFA はもはや使わない理由が特に無いので、心当たりのある人は今すぐ有効にしましょう。

AWS Casual Talks#2 で発表してきた

開催からもう一週間経って今更感しかないのですが、 AWS Casual Talks#2 という勉強会で AWS CloudTrail の話をしてきました。

AWS Casual Talks#2 on Zusaar

アレなタイトルですみませんでした。。。

CloudTrail の話と言いつつ、前半1/3くらいを Heartbleed ネタに使ってしまいましたが ちょうどホットな話題だったのと、AWS 周辺でこの話してる人あまりいないなあと思っていたので つい入れてしまいました。

30分もの枠で対外発表するのは初めてだったので正直かなり緊張していました。 終わってみると、喋り方や話のまとめ方など色々反省点が多いなあと思いつつ、楽しかったです。

CloudTrail についてもうちょっと

スライド中に、ログを取るために HTTP Proxy をかますことを考えた、みたいなことを書いてるのだけど、 そうするとその Proxy を通さないリクエストはロギングできなくなる、 つまり例えば IAM でリクエスト元 IP とかを Proxy のものに縛っていたとして、 リクエスト元 IP が違う (= Proxy 使ってない) リクエストは当然ロギングできないわけで、 やっぱり API に対してのログとは言えないなあと思っていました。

AWS の怖いところの一つとして、目に見えているもの以外の部分が見えにくいということを かなり感じていたので、ネタではなく CloudTrail さんには一日も早く太平洋を渡ってきてほしいなあと願っています。

iwas について

iwas という CloudTrail のログをパースして IAM の変更履歴を記録するものを作ってみました。

kanny/iwas · GitHub

CloudTrail のログ通知を SNS 経由で SQS に吐くようにしてあげると使えます。

IAM の変更履歴って、権限変更の記録というセキュリティの面から見ても 個人的にはかなり必要なものだと思っていて、IAM に実装されないのかなーとずっと思っているのですが、 そういう気配がなかったので作りました。

ちなみにネーミングは IAM (I am) の変更履歴を取るので I was ... にしていて、 個人的にはこのネーミングだけで行ける!!!!!とか思っていたのですが、 なんというか、社会は厳しかったです。

同梱している iam-export.rb は IAM のポリシを json ファイルにエクスポートします。 当初は aws-sdk for ruby の current 版を使ってたのですが、IAM Role の扱いに対応していなくて、 開発は aws-sdk-core (v2) にシフトしているようだったので、まだ pre ではありますがこちらを使ってみました。

が、中身を見ればわかるように正直全くプロダクションクオリティではありません。。。 すでにいくつか考慮漏れを見つけているので、近いうちに直して環境構築方法とともにきちんと公開しようと思います。

さいごに

次は EC2/VPC 上のインスタンス運用でのセキュリティとか、そういう話をする機会があればと思います。 というか AWS 系の勉強会は数あれど、その中で運用におけるセキュリティとかに焦点を当てたものって あまりなさそうなので、今度やってみたいですね。

というわけで、主催してくださった @con_mame さん、 会場提供してくださった AWS さん、他の発表者の方々、聞いてくださった方々、ありがとうございました。

AWS Game Day Japan 2014 に参加した

JAWS DAYS 2014 の前日に開かれた、 Game Day Japan 2014 に参加してきました。 AWS Game Day Japan 2014 Spring (Tokyo) - JAWS DAYS 2014 | Doorkeeper

Game Day そのものの詳細はクラスメソッドさんの Blog 記事が詳しいと思います。 すごく大雑把に言うと AWS で構築したシステムを全力で攻撃して全力で修復するというものです。

『JAWS DAYS 2014』開催前告知 #11 対戦型システム信頼性向上策体感イベント『GAME DAY』は前日3/14(金)、4箇所(東京/大阪/名古屋/仙台)同時開催!! #jawsdays #jawsug | Developers.IO

過去にも行われたようですが僕は今回が初参加でした。 Game Day そのものに興味はあったので今年もやるという噂をききつけてエントリー。 全会場で50人いかなかったら中止って書いてあって、平日ということもあり開催されるのかなーとちょっと不安でしたが 無事開催されることになって嬉しかったです。

会場に着いて説明のち、早速チーム分け。 チームメイトは @moomindani さんと @nginks さん。 自己紹介しつつまずはコミュニケーションツールを作る。 Google Docs だけでなんとかなるかと思ったけどチャットが欲しかった(声でバレるから)ので Skype も併用することにしました。

構築と防御

まず最初は構築フェーズ。EC2 と SQS を使ったシステムを手順に沿って作っていきます。 去年と同じだったらしいんだけど、どうせ問題変わるだろうと思って何ら予習しなかったので 2回目でーすって人が手挙げてたりして冷や汗ものでした。 構築はチームのお二人に任せつつ、防御周りのことをしたり構築を手伝ったり。 やったことはこんな感じ

  • CloudTrail を有効化してログを他アカウントの S3 バケットに投げるように
  • SQS の Dead letter queue を有効化して変なキューは自動で流せるように
  • piculet でセキュリティグループの状態をコードとして保持
  • 自作の IAM エクスポートスクリプトで IAM の構造とかを保持 (今回は IAM のみ触れないのであまり意味はないけど、読みやすいように)

などなど。色々考えましたがすっと手が動かないなーという反省。。。

EC2 が実行するワーカーに OS コマンドインジェクションを見つけて (去年も全く同じだったらしいけど) パッチ当てようか迷ったのだけど、 コード読んでたのが終了3分前くらいで間に合いませんでした。。。 あと CloudTrail のログを他アカウントに出すのは反則かなーと思ったけど、実際有効なんじゃないかなーと思ってやってみました。 ほんとは loggly の free account から読めるようにしてたんだけど、インポートがなぜかうまくいってなかったので諦めることに。 ちまちま作っていた自作のパーサと JSONView でなんとかしていました。

攻撃・修復

どんな攻撃があったかは ijin さんの Blog にほとんど記載されてるのでそちらをご参照ください。

AWS Game Day Japan 2014春を開催してきた - @ijin

相手に渡すアカウントは IAM の操作のみができない Power User Template だけを入れたアカウントだったので、 事実上ほとんどなんでもできる状態。 リソース全消しなどではなくバレにくく修復しにくい攻撃が評価されるとのことで、 事前に考えていた攻撃としては S3 の Bucket Policy 周り、Auto Scaling, OS コマンドインジェクション、VPC のネットワーク機能あたりを 攻めようと考えていたのですが、

攻撃用アカウントをもらってざっと目を通すとまさかの VPC 使わない (EC2-Classic) 環境…………

これで考えてた攻撃をかなり潰されてヒーという感じでした。その発想はなかった。。。

修復はだいたいできたものの、AutoScaling の Scheduled Action に仕込まれた攻撃を修復しきれず。 CloudTrail は多くのチームが壊しにかかったようですが、うちのチームは S3 Bucket を外に出していたこともあり無傷。 これについては後述。 1チームが複数チームから攻撃されるというアクシデントなどもありつつも修復フェーズおわり。

結果発表

結果、ほとんどのサービスに加えて Management Console も壊した (表示を触りまくった?) チームが優勝。 うちは厳しいんじゃないかしらと思ってたけどなんと地方賞(仙台賞)をいただきました。 どこ攻撃されたかわからないような攻撃が多かったのが評価対象だったようです。やったー。

感想

限られた時間でシステム作って修復するというのはなかなか難しく、 改めて思ったのは"正しい状態を保持して比較し続ける"ことの重要性でした。 例えばコードにエクスポートしていたセキュリティグループへの攻撃は、変更把握も修復も一発でしたし。

CloudTrail は正直 SQS や AutoScaling 周りへの攻撃がメインだった今回、あまり威力を発揮する場面はなかったかなーという印象。 ただ、リージョンが US だったこともあり、CloudTrail 環境下で作業をしていくとこういうログが取れるのかーというものが 手に入ったのは大きいと思いました。 Management Console も実際は各操作で API を呼んでいるので、相手がどんな順番でシステムの概要を把握していったのかある程度想像できたり。

IAM の Power User template では IAM の変更のみが禁止されてますが、監査という点から考えると CloudTrail への変更も デフォルトで禁止してほしいところです。。。

また、ログの保存場所について自分の考えを確認できたのも良かったです。 CloudTrail しかり ELB しかり、AWS への操作のログが徐々に取得できるようになってきてますが、 確実なログ運用のためには全く違うアカウント管理下にあるバケットへの格納など、どうやっても手がとどかない場所に保持しておくのは 一つの運用として良いのかなーと思いました。

色々と勉強になりました。次回も参加したいです。 運営の皆様、チームメイトの皆様、参加された皆様、ありがとうございました。