パスワード付き ZIP ファイルの話

パスワード付き ZIP ファイルの脆弱性が、といった話が、話題になっていたようです。

2019年5月18〜19日のtwitterセキュリティクラスタ – twitterセキュリティネタまとめ

どうやら、

  • 通称: Traditional PKWARE Encryption の脆弱性の話らしい。
  • もともと、Traditional PKWARE Encryption は、内部状態の 96bit を総当たりすれば解けてしまうもので、これが実質的な鍵長になる。
  • 96bit じゃ、今どきの暗号としては、圧倒的に短い。
  • ということは昔から指摘されていたけど、今回は、そこから、パスワードを生成することに成功したらしい。

のようです。

意外に、この「古い暗号化」を知らない人が多いみたいですが、私は、下記ページを読んだことがあったので、暗号化アルゴリズム自体が、古臭くてイケてない、という認識はありました。

暗号化 ZIP 書庫 の評価 - EverQuestできない日記

これが書かれたのが 11 年前。私自身がこの記事を読んだ知識を元に言及している記事を、2009 年に書いていました。

前にも書いたけど... - JULY’s diary

あれから 10 年。未だに、パスワード付き ZIP ファイルを使う習慣は駆逐されていません。

結局、パスワードをメールで送るんだから、意味がない、という文脈で批判されるのですが、そもそも、古い暗号化方式でのパスワード付き ZIP ファイルは、仮にパスワード運用をきちんとやっていても、既に復号化されやすい、非推奨の形式でした。

 

Office 系のファイルや PDF ファイルなどを、パスワード付き ZIP ファイルにする人を見かけますが、ZIP にしてパスワードを付けるぐらいなら、Office 自体でパスワード付きにする方が遥かにマシで、こっちは、パスワードさえきちんとしていれば復号化される心配は、ほとんどありません。バージョンにもよりますが、暗号化は基本的に、AES を使っています。

 

このパスワード付き ZIP ファイルの問題。Windows での ZIP ファイルの扱いが影を落としています。

 

ZIP ファイルの暗号化方式に関しては、すでに AES で暗号化するオプションが存在します。無料で使用できるソフトウェアとしては、7-zip にもそのオプションがあります。

 

圧縮・解凍ソフト 7-Zip

 

ところが、Windows の圧縮フォルダとして、パスワード付き ZIP ファイルを扱えるのは、先述の「Traditional PKWARE Encryption」だけです。

 

パスワード付き ZIP ファイルが流通している背景には、

  • Windows の標準機能で中身を取り出せる。

というのがあります。その Windows の標準機能では、AES での暗号化をした ZIP ファイルは扱えない。

 

 

まぁ、もともと、パスワード付きファイルをメールに添付して送って、結局、メールでそのパスワードを伝える(しかも、パスワード自体も分かりやすいもの)ということ自体が「気休め」にしかすぎないのだから、いまさら、あれこれ言っても、という面もありますが、社内のガイドラインに「添付ファイルを送る時は、パスワードを設定した ZIP ファイルにして...」と書かれているケースも多いでしょう。

 

せめて、Office 系ファイルは、ZIP ファイルにはせずに、Office でパスワードを設定する、としていれば、「気休め」よりは、ちょっとだけまともになると思いますが...

パスワード防御に対する風評

元記事は、期間限定で無料で読める記事だから、はてブのページを示しておく。

 

はてなブックマーク - 「ハッシュ化したから安全」と主張するのをそろそろやめようか | 日経 xTECH(クロステック)

 

元記事の内容は、パスワードをハッシュ化しているから大丈夫、というのは言いすぎだ、という内容で、それはごもっともなのだが、後半にかけて、いかに危険なのかを煽る内容になっていた。

 

大雑把に言えば、「ハッシュ化していたとしても、パスワードが判明することがある」ということを主張しているのだが、攻撃手法と防衛手法がきちんと整理されていない印象だった。

 

パスワード・クラッキングの手法には、下記のようなものがある。

 

逆引き

ハッシュ化された値が分っている「オフライン・クラッキング」の場合に可能な手法で、平文のパスワードと、ハッシュ化後の値との組み合わせをデータベース化したものを用意し、それを検索することで元のパスワード知る方法。

普通にやると、そのデータベースが簡単に巨大になってしまうので、この目的のための効率的なデータ構造として登場したのが、いわゆる「レインボーテーブル」。

この手法の特徴は、他の手法に比べて圧倒的に短い時間でパスワードが判明すること。ただし、

  • ハッシュ化のアルゴリズム毎にデータを用意する必要がある。
  • レインボーテーブルで容量を小さくできる、と言っても、パスワードが1文字増えれば、用意すべきデータは2桁ぐらい大きくなるので、長いパスワードに対応しようとすると、必要なリソースが簡単に大きくなってしまう。

というのが弱点。

辞書攻撃

人間がつけそうなパスワード文字列を準備・生成し、その文字列に対してハッシュ化の計算をしたり、実際に対象システムに送信する。

いわゆる「脆弱なパスワード」は高確率で元のパスワードを発見することができるが、本気でランダムな長いパスワードは、そもそも試行されないことになるので、発見されることは、基本的には無い。

どのくらいの確率でパスワードが判明するかは、辞書がどれだけ豊富なのか、ということになるが、最近は、すでに漏洩されているアカウント情報が広く流通していることを考えると、人間がつけやすい、だけじゃなく、一度、誰かが設定したパスワードに合致、というケースもあるかもしれない。

総当たり攻撃

この世のすべての文字列を試す、というもの。原理的には、どんなパスワードでも発見できるが、パスワード長がちょっと長くなると、あっという間にこの攻撃は破綻する。ASCII 図形文字と半角スペース合わせて 95 種の文字が使えるとしたら、n 文字のパスワードは 95n通りとなる。実際に計算して見れば分かるが、10 文字でも 59,873,693,923,837,890,625 通りに達する。1文字増えれば、95 倍になる。

一世を風靡した Ophcrack も、基本的にはレインボーテーブルを使うが、4文字までは ASCII 文字の総当たりを行う。

 

オフライン・クラッキングに対して、防御方法としてソルトとストレッチングがあるが、ソルトは上記の攻撃のうち、逆引きに対抗するものであり、辞書攻撃や総当たり攻撃には効果はない。逆に、ストレッチングは、ストレッチングの回数やアルゴリズムが分かっている場合、逆引きには効果は無い*1

  • ソルト ... 逆引き対策
  • ストレッチング ... 辞書攻撃や総当たり攻撃に対する対策

 なので、ソルト付きでストレチング済みであれば、簡単に元のパスワードが判明することはないのだが、元記事で、

ただ両方の工夫を適用しても、解析に時間がかかるようになるだけだ。解析できなくなるわけではない。

と書かれた。

この文章だとまるで、ソルト付きストレッチングが気休めのように読めてしまうが、実際はそんなことはない。きちんとソルトがついていれば逆引きは実質的に不可能だし、ストレッチングをしていれば、仮に、1時間で判明するパスワードが、1,000 回のストレッチングで 42 日後になる。パスワードを変更して漏洩の被害を回避する時間を作ることができる*2。

 元記事で自分が一番気になったのは、上記の文章に続いてこう書かれていたことだった。

例えば、漏洩データの検索サービスを提供していたLeakedSourceが2016年9月、ソルトを採用していたサービスから漏洩した4350万件以上のアカウント情報を2時間で96%解析したとしている。

ソルト付きのパスワードで 4000 万件以上のパスワードが 2 時間で判明、という事に強烈な違和感を感じた。ソルト付きであれば、

  • ソルトがアカウントによらず固定
  • その固定のソルトが付いているケースのテーブルが整備済み

じゃないと、2時間で 4000 万件、毎秒 5,500 件以上のというのは、クラウドのおかげで計算リソースの調達が容易になったご時世でも、現実的な数字とは思えない。

 

記事中には、この LeakedSource の話のソースが示されていないが、おそらくこれではないか、というページを見つけた。

leakedsource.ru

これが正しいとすると、

  • 元記事で 2016 å¹´ 9 月と書いているが、上記ページが書かれたのが 2016 å¹´ 9 月であって、話の内容は 2012 å¹´ 3 月。
  • 「4350 万件」「96%」「2時間」と言っているのは、Last.fm から漏洩したもの。
  • 「Passwords were stored using unsalted MD5 hashing.」と書いているから、ソルトなしの MD5 ハッシュ値。
  • 得られたパスワードを見たら、なんと安易なパスワードの多いこと。

という話になる。

安易なパスワードが多くて、ソルトなしの MD5なら*3、普通にレインボーテーブルで短時間にパスワードが見つかるのは当然である。

元記事では「ソルトを採用していた」と書かれているが、私が見つけたページが正しいとすれば、大きな事実誤認ということになる。故に、この話をもって「ソルト付きストレッチングは気休め」と風潮するのは間違いと言わざるを得ない。

 

ちょっと話は変わるが、この件のブクマコメントで、徳丸さんが

BCryptでもArgon2でも通常Saltはハッシュ値とともに保存するので辞書攻撃には対抗できないでしょ。

と書かれている。辞書攻撃で判明してしまうパスワードは、どんな形式保存しても見つけられてしまう。脆弱なパスワードに対しては、ソルトもストレッチングも気休め言わざるを得ない。

システム側が頑張ったところで、脆弱なパスワードを付けたユーザを守ることはできない。保存形式を適切に保てば、きちんとしたユーザを守ることはできる。

 

ということで、皆さん、

  • 十分に長いパスワードで
  • 使い回しをしない

という原則を守りましょう。

*1:もし、同じストレッチング回数とアルゴリズムのレインボーテーブルが無いなら、それを作らなければいけないし、ストレッチングしていればテーブル作成に時間がかかる、という効果はある。

*2:逆に、漏洩したことをどれだけ迅速に検知できるか、が重要になってくる

*3:「MD5なら」というのは、MD5 の衝突耐性の問題ではなく、ビット長が比較的短く、メジャーなハッシュ関数だから、すでにレインボーテーブルが充実している、という理由。任意のハッシュ値に対して、そのハッシュ値を持つビット列を求めるのは、MD5 でも、そこまで容易ではない。MD5 が使えないのは、ハッシュ値は何でも良いから、同じハッシュ値を持つユニークなビット列を見つける、という強衝突耐性の問題。

Path MTU Discovery が原因の通信障害は分りづらい

普通、何らかの通信障害が発生すると、当然、通信の当事者に関する事を調べ出します。

サーバ側に何かログは出ていないか、パケットキャプチャをして相手からどんなパケットが届いているのか、Firewall 等で当該ホストに関するルールが引っかかっていないか....

ところが、Path MTU Discovery に起因する問題が発生すると、通信の当事者では、一見、相手が悪いように見えるし、実際、原因が当事者とは無関係のように見えるところにあります。

通信障害の最終手段として登場*1するパケットキャプチャをしても、単に、相手からのパケットが届かないだけに見えます。

そもそも、Path MTU Discovery とは?

まず、MTU

フレッツ網が出始めた頃、ネットワークスピードの改善方法として MTU のサイズを調整する話で有名になった MTU ですが、Maximum Transmission Unit の略で、1つのフレームで送信できる最大サイズの事を言います。

元々、MTU 自体は回線の種別によって決まるもので、一般的な Ethernet では 1500 バイトで、WAN 回線で使われる PPP の場合は可変ですが、Ethernet と同じ 1500 バイトになる事が多いようです。今はほとんど見かけない FDDI では 4352、IP over ATM で 9180 バイト、といった具合に、本来は様々な MTU を持つ回線があります。

フレッツ網が登場したときに MTU が話題になったのは、PPPoE というカプセル化技術を使ったためで、1500 バイトの Ethernet フレームの中に、ユーザ側の端末と契約先の ISP をつなぐ為の PPP を入れ、さらにその中に IP を入れる、という仕組みです。

そのため、通常の Ehternet に比べて PPP の分だけ、入れられる IP のサイズは小さくなります。

Path MTU とは

「Path」は「経路」を意味します。相手にパケットが届くまで、いくつものルータを渡っていきますが、その間の回線がどんな物が使われているか分りません。

ある相手と通信する時に、その経路全体での MTU が Path MTU です。

つまり、経路全体で、最も小さい MTU が Path MTU です。

Path MTU Discovery は、経路全体で最も小さい MTU をどうやったら分るか? という仕組みです。

ルータによるパケットの分割

ルータが受け取ったパケットを転送する際、転送先となる回線の MTU が受け取ったサイズより小さかった場合、パケットを分割して送ることがあります。

こうすれば、通信当事者は経路上の MTU など意識することなく、パケットを送信できますが、その代わり、ルータに取っては負担になります。

Path MTU Discovery の RFC 1191 が出されたのは 1990 年ですが、1990 年代に入ってから、ISP のルータのような、多くのネットワークとつながって、大量のパケットを裁くルータにかかる負荷が問題になっていました。

時期的に次期 IP(後の IPv6)の策定が行われていて、次期 IP のテーマの一つに、このルータの負荷問題もありました。

経路上の MTU が分ってしまえば、最初っからそれに合わせたサイズでパケットを送り出すことになるので、ルータでの分割は発生しません。

そのため、IPv6 では Path MTU Discovery が使われる事が前提になりました。

Path MTU Discovery の仕組み

もともと、IP パケットには DF(Don't Fragment)フラグというフラグがあり、このフラグがセットされているパケットは、ルータによる分割をしてはならない、ということになっています。

ルータがより小さい MTU を持つ回線を使ってパケットを転送しようとした時に、「分割できない」という事は、これ以上、パケットを転送する事ができない、という事を意味します。

こういった事態が発生していることを、パケットの送信元に伝えるために ICMP が使われます。

Type 3(Destination Unreachable Message)の Code 4(fragmentation needed and DF set)という ICMP がルータから送信元に送られ、この中に「○○○バイトだったら転送できるんだけど...」という情報が入っています。

送信元がこれを受け取ったら、そのサイズに合わせて IP パケットを再送します。

最終的に相手にパケットが届くまで、ICMP の情報に合わせて小さくしていけば、経路上の最小 MTU が見つかる、という仕組みです。

ICMP がフィルタされると Path MTU Discovery が成立しない

Path MTU Discovery は、パケットが分割できないときにルータが返す ICMP を利用して実現しています。ということは、もし ICMP がフィルタされている*2と、

  • ルータはこれ以上転送できないから、受け取ったパケットを捨てて ICMP を返す。
  • 送信元から見ると、送ったパケットに対して、相手から一切応答がない状態。

ということになります。

IPv6 では Path MTU Discovery が使われるので、ICMP をバッサリと Firewall 等で落としてしまうと、通信できない事態が発生する可能性があります。そのため、わざわざ RFC で、ICMPv6 のフィルタリングに関する文章が出されています。

RFC 4890: Recommendations for Filtering ICMPv6 Messages in Firewalls

考えなしにまるごとフィルタリングをしてはいけません。

実は IPv4 でも同じことが...

IPv6 の話だと思って、「そんなの使っていないし」と思っていると落とし穴があります。Path MTU Discovery 自体は IPv4 でも使える仕組みなので、原理的には同じことが発生しうることになります。

実は、割と以前から Linux では IPv4 でも Path MTU Discovery が有効になっていて、そのことに私が気がついたのは5年ほど前の CentOS Ver.6 系でした。CentOS 上で Squid を動かした HTTP Proxy を経由すると、繋がったり繋がらなかったり、みたいなことがあって、そのときにパケットキャプチャをして DF フラグが立っていることに気が付きました。

Linux で IPv4 の Path MTU Discovery が有効になっているかは sysctl コマンドで分ります。

$ sysctl net.ipv4.ip_no_pmtu_disc
net.ipv4.ip_no_pmtu_disc = 0

ちょっと分りづらいですが、ip_no_pmtu_disc なので、値が 0 なら有効です。

Linux で IPv4 の Path MTU Discovery が有効ということは...

今や Linux はサーバ以外にもいろいろなところで使われています。という事は、明確に「Linux」と認識していないものでも、Path MTU Discovery が有効になっている、ということになります。ネットワーク機器や IoT デバイスにも Linux は使われています。

私が実際に経験したのは、AWS のロードバランサである ELB です。

ELB に対する接続が VPN 経由だと NG、という事があったのですが、「ELB の実体って、Amazon Linux のインスタンスとかじゃないかなぁ」と思って、ICMP をブロックしていた Network ACL の設定を変更したら解消した、という事がありました。

IPv6 に限らず IPv4 に関しても、いたずらに「ICMP を丸ごとブロック」をするべきではありません。

Ping of Death*3 や Smurf 攻撃*4は、正直、過去の物です。ICMP に対して過大な恐怖心を持たず、フィルタするなら ICMP の「中身」も意識したいものです。

*1:個人的には、レイヤー 3 以下が原因になりそうな症状で、当事者が Linux だったら、最初っから tcpdump の登場させますが。

*2:Firewall 製品だと、意図的にブロックしない限り、許可している通信に対して発生した ICMP は適切に転送してくれる事が多いです。L3 スイッチの ACL のように、ステートレスにパケットを判断する場合、フィルタされてしまいがちです。

*3:Windows 95 が登場した頃、UNIX 系 OS がサイズの大きい ICMP Echo Request を送りつけられると、カーネルパニックに陥る欠陥があった。

*4:宛先がブロードキャストアドレスとなっている ICMP Echo Request に対して、該当するホストが応答する動作利用し、送信元アドレスを攻撃対象のアドレスに偽装してパケットを送りつけると、その何倍ものパケットが攻撃対象に向かう、という DDoS 攻撃の一種

せきゅぽろ 22

今回は、立命館大学の上原哲太郎先生による、マイナンバーのお話でした。

マイナンバーの話となると、

  • マイナンバーを管理するはめになった企業向けの話。
  • プライバシーに関するマイナンバー制度の問題。

といった2つのパターンのが多いと思いますが、もちろん上記の点も含め、非常に広範囲の話を聞くことが出来ました。

Slideshare で今日の資料が公開されています。

今さら聞けないマイナンバー

詳細は上記の資料に譲るとして、印象に残った話を少し書きます。

「国民総背番号制」はすでに実施済み

厳密に言うと、住基ネットに参加しなかった一つの自治体を除けば、ですが、住民票があれば、住基ネットで使われている住民票コードが付与されているので、「国民総背番号制」という意味では、マイナンバーで導入されるものではないです。

言われてみれば、そうだよなぁ、という話なのですが、逆に、住基ネットがうまく活用出来なかったことを示唆している感じがします。

チェックデジットがダサい

マイナンバーの最後の数字はチェックデジットなのですが、計算式で得られる計算結果は 1 〜 11 の整数。チェックデジットは一桁の数字。で、どうしているかというと、

「計算結果が 10 以上の時は 0」

だそうです。つまり、末尾が 0 の人は、他の数字に比べて2倍の確率で存在することになります。

ちなみに、この計算式は官報にも載っていて、で、官報は縦書き、ということで、計算式がどう書かれているのか、気になる人はチェックしてみましょう*1。

システムの仕組みは結構複雑

Slideshare 資料にもありますが、単純に中央のデータベースがあって、そこにアクセスするような仕組みではなく、基本的には、各自治体が組織ごとにデータベースがあって、中央では必要に応じてひも付けをするような仕組みだそうです。

なので、マイナンバーのシステムによって、現状の住基ネットよりセキュリティリスクが特に高くなるようなことはない感じです。

マイナンバーによるプラバシー問題の本質は「名寄せコストの減少」

個人情報の漏洩、ということがニュースで大きく取り扱われるご時世ですが、本当に問題なのは、各種のプライバシー情報が「名寄せ」されることによって、芋づる式に個人関する情報が取得できてしまうことで、マイナンバーは、その「名寄せ」のコストを劇的に下げる効果があります。

故に、マイナンバーの民間利用に関しては慎重になる必要があり、民間が使いたいと言っている「目的」に対しては、フェデレーションのような別の「手段」が適当ではないか、といったお話がありました。

マイナンバーは「アカウント」

マイナンバーはあくまで「識別」するための番号であって、「認証」に利用するものではなく、いわば「アカウント」のようなもの、という説明は分かりやすかったです。アカウントだけでは本人かどうかは判断できないのと同様に、マイナンバーの番号だけで本人性を確認できるわけはない、ということになります。


全体的に、メディアが煽るようなリスク拡大はないように思えます。ただ、上原先生もおっしゃっていましたが、今後、民間活用を含めた利用拡大が検討されているので、その部分で注視していく必要はありそうです。

*1:私も後で探してみます ... ありました! http://www.soumu.go.jp/main_content/000327387.pdf

AWS Cloudformation と IAM Policy での IP アドレス制限

AWS で、マネージメントコンソールや API 等で AWS 上のリソースの操作を特定の IP アドレスからしか実行できないようにするために、IAM ポリシーの aws:SourceIp を使って制限する、というのは常套手段として知られていると思います。

AWS管理コンソールへのアクセスをIPアドレスで制限したい | Developers.IO

このページの最後でも書かれていますが、この常套句の設定は CloudFormation を使ったスタックの生成、更新、削除といった時に問題になります。

AWS Identity and Access Management によるアクセスの制御 - AWS CloudFormation

aws:SourceIp 条件を使用しないでください。AWS CloudFormation はリクエストの送信元 IP アドレスではなく、独自の IP アドレスを使用してリソースをプロビジョニングします。たとえば、スタックを作成する際、Amazon EC2 インスタンスを起動したり Amazon S3 バケットを作成したりするために、CreateStack 呼び出しや aws cloudformation create-stack コマンドによって得られる IP アドレスではなく、スタックの IP アドレスからリクエストを行います。

(2015 年 3 月現在)

「独自の IP アドレスを使用してリソースをプロビジョニングします」といっている「独自の IP アドレス」というのが分かれば、それを許可してやれば、などと思ったのですが、公開されている AWS の IP アドレスの範囲*1を試したり、プライベートアドレスの範囲を指定したりして見ましたが、うまくいきませんでした。

Cloud Trail で見ても、Source IP は cloudformation.amazonaws.com となっていて、この名前で DNS に問い合わせても A レコードは持っていません。

AWS で su

UNIX 系 OS であれば、ホストのファイヤーウォール設定や、/etc/hosts.allow, /etc/hosts.deny を使って、特定の IP アドレスから接続を許可し、/etc/ssh/sshd_config で root でのログインを拒否して、一般ユーザでログインするようにしておいて、特権が必要な時には su で root になるか、sudo を使う、という運用をしているケースが多いと思います。

これと同じように、「通常は、制限されたアクセス権で、必要に応じて大きな権利を取得する」という手段が AWS に用意されています。それが「AssumeRole」です。

AssumeRole は、他の AWS アカウントを操作する為の権限を設定させたり、外部の認証基盤を使った認証処理を行う、という文脈で説明されることが多いです。

しかし、別の AWS アカウントじゃなくて、自分自身の AWS アカウントを指定しても OK?、と思ったきっかけがありました。

AWS CLIがAssumeRoleによる自動クレデンシャル取得とMFAに対応しました! | Developers.IO

作成した IAM アカウントに MFA を設定して、マネージメントコンソールに対しては MFA 無しでは利用できないことは確認したのですが、AWS CLI の時にはどうなるんだ? と思ってたどり着いたのが上記の記事です。

これを読むと、あるバージョンの AWS CLI からは、MFA が必要な時にはそのトークンを要求する、といった動きができるようになったことが分かります。

よく読むと、信頼ポリシー(trust plolicy)で「MFA での認証に成功している場合に AssumeRole を許可」としています。じゃぁ、この条件を「特定の IP アドレスからの場合だったら」としてみたら...

ということで、思いついたシナリオは以下の通りです。

  • IAM ユーザに、AssumeRole を許可したポリシーを割り当てる。
  • 信頼ポリシーで、先の「MFA での認証が〜」の条件の所を、「特定の IP アドレスだったら〜」に変えたものを設定する。

実際にやってみる

まず、IAM ロールを作成します。ロール名を入力して、ロールタイプを選択する画面が出たら、「Role for Cross-Account Access」の「Provide access between AWS accounts you own」を選択します。元々は「あなたが持っている AWS アカウント間でのアクセスを提供」という意味ですが、持っているアカウントが1つでもこれを選択します*2。

次に、「どのアカウントに対してアクセスを提供するか?」を指定するのですが、本来のクロスアカウントでの利用であれば、アクセスを付与する先の AWS アカウント番号を入れる所に、自分自身のアカウント番号を入力します。

上記画面の「Require MFA」をチェックすれば、前述の「AWS CLI で MFA を使う」ための信頼ポリシーが生成されます。

後は、付与したい権利の内容を選択すれば、ロールの作成はひとまず完了です。

作成したロールの内容を確認すると、画面の下の方にある「Trust Relationship」で生成された信頼ポリシーが確認できます。

実際に生成されたポリシーは、こんな感じになります。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::自分の AWS Account ID:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

これを編集して、Condition 句で IP アドレスを指定します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::自分の AWS Account ID:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "xxx.xxx.xxx.xxx/xx"
        }
      }
    }
  ]
}

これで、ロールの準備は OK です。

次に、IAM ユーザに割り当てる為のポリシーを用意します。任意のロールに切り替えられるのを過剰な権利なので、Resource に先に作ったロールを指定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole"
            ],
            "Resource": "arn:aws:iam::自分の AWS Account ID:role/先に作ったロール名"
        }
    ]
}

後は、このポリシーをユーザに適用すれば OK です。

使ってみる

分かりやすいように、前述の AssumeRole を許可したポリシーだけをユーザに付与した状態にしてみます。AssumeRole が許可されているだけなので、信頼ポリシーで許可されているアドレスか否かにかかわらず、AWS 上のリソースに対する一切の操作、一切の情報取得ができない状態になっています。

で、許可された IP アドレスからアクセスすると、ロールを切り替えることができます。

マネージメントコンソールでロールを切り替えるのは、画面右上のログイン中のアカウント情報を表示している所からメニューを表示させて、「Switch Role」を選択します。

ロールの切り替え画面では、切り替え先の AWS アカウントと、先に作ったロールの名称を入力します。

*3

「表示名」の欄は、アカウントとロールを入力すれば「ロール@アカウント」の形式になります。

で、実際に切り替わると、下図のように、それまで「IAM ユーザ名@アカウント」だったのが、「ロール名@アカウント」になっています*4。実際に、ロールを切り替える前にでは軒並み「権利がない」と言われていたのが、切り替え後はきちんと表示されています。

  • ロール切り替え前:
  • ロール切り替え後:

信頼ポリシーで指定した IP アドレスとは違うところからログインしてロールを切り替えると、下図のように切り替えに失敗します。

ロールを切り替えられれば、そのロールで付与されているポリシーが適用されます。この時、ロールに付与したポリシーに aws:SourceIp を使わなければ、CloudFormation でスタック生成も問題なく実行できます。

AWS CLI での利用

先に紹介した、AWS CLI で MFA を使うケースに似ています。

AWS CLI のプロファイルで

  • 元になるプロファイル(source_profile)
  • 切り替え先のロール(role_arn)

を指定した物を作成し、実際の処理の際に「--profile プロファイル名」を付けて実行する事になります。MFA との例の違いは MFA デバイスを指定する「mfa_serial」の有無だけです。

直接、ファイルを編集しても良いですが、AWS CLI を使って必要な設定を書き込む事もできます。

今、AssumeRole が許可されたユーザのアクセスキー、シークレットキーがデフォルトで使われるように設定されているとします。

ここに「admin」というプロファイルを追加して、AdministrationRole という名前のロールへ切り替えるようにするには、下記のように AWS CLI を実行します。なお、AWS Account ID が 111122223333 だったとします。

aws configure set profile.admin.region ap-northeast-1
aws configure set profile.admin.role_arn arn:aws:iam::111122223333:role/AdministrationRole
aws configure set profile.admin.source_profile default

これで、config ファイルの中身は下記のようになります。

[default]
region = ap-northeast-1
[profile admin]
region = ap-northeast-1
source_profile = default
role_arn = arn:aws:iam::111122223333:role/AdminRole

この状態で「aws cloudformation --profile admin create-stack --stack-name ......」とすれば、スタックの生成ができます。

注意点

AssumeRole で切り替えた後の権限は、切り替え先のロールに全面的に切り替わります。

aws:SourceIp を使ったポリシーを設定する際、「このアドレスに合致したら許可する」ではなく「このアドレスに合致しなかったら、全てを拒否する」というポリシーを適用するのが良い、と言われます。複数のポリシーが割り当てられている場合、先に「拒否」のポリシーを評価するので、「このアドレスに合致しなかったらすべてを拒否する」というポリシーがあれば、他のポリシーで IP アドレス制限がなくても、確実に制限できます。

故に、CloudFormation の実行の際に問題になった訳ですが、切り替え先のロールに全面的に切り替わるからこそ、元々のポリシーに制限があっても、CloudFormation のスタック操作に成功する事になります。

ですので、切替後の操作に制限を加えたければ、あくまでも、ロールの中身で制限する必要があります。切替前のポリシーは切替後には反映されない事を十分に注意する必要があります。

*1:AWS IP アドレスの範囲 - アマゾン ウェブ サービス

*2:実はドキュメントにこのケースがきちんと書かれていました。IAM ユーザーにアクセス権限を委任するロールの作成 - AWS Identity and Access Management「このオプションは、ユーザー、ロール、アクセスされるリソースがすべて同じアカウントに属している場合にも選択します。」

*3:なぜかこの画面は日本語...

*4:切り替え先のロールを指定する画面で「表示名」に設定したものになる、はずです(試してない)。

せきゅぽろ 19

久しぶりに参加したせきゅぽろの勉強会は、Google に名前を入れると、広島出身のテクノポップアイドルの名前がサジェスチョンされる、辻 伸弘さんでした。辻さんは何度かせきゅぽろにいらっしゃっているはずですが、私個人は初めてでした。

テーマはまず最初に、昨今の不正ログインに関する話でした。

かつては総当たりや辞書攻撃、その応用のリバース・ブルートフォース(パスワードを固定にして ID の方を次々にかえる)が主流だったと思いますが、この1、2年で急速に脚光を浴びたのが、あらかじめ入手されているアカウントとパスワードの組み合わせのリストを利用したリスト型攻撃です。

ブルートフォース型の攻撃だと、パスワードが十分な長さで複雑であれば、現実的な時間で突破される事はない、という「時間軸」での問題だったのに対し、リスト型攻撃の場合、あるサイトで使っていたパスワードを使い回していると、他のサイトで突破される、いわば「横展開」の問題に変化したのが特徴だと思います。

辻さんがある人から持ちかけられた相談で、1000 万件のリストを 400 万円で買わないか? という話があったそうです。ただ、そのリストのサンプルを辻さんが眺めていて、似たようなパスワードがあったり、いわゆる脆弱なパスワードが見当たらない、など、本物かどうか怪しい感じ、そのリストにあるメールアドレスで検索したら、パスワードはハッシュ化されているけど、同じメールアドレスの一覧が見つかって、リストのパスワードと、検索して見つかったパスワードのハッシュ値を突き合わせたら、どうやらそのリストは偽物だった、ということがあったそうです。

2つめのテーマは、Phishing に関して。実際に Phishing サイトを作るツールを使って作られた、全く同じ画面のサイトにアカウント・パスワードを入力すると、その Phishing サイトのログにパスワードが記録されるところを、実際のデモで見せてもらえました。

辻さんは最近、Phishing サイトに引っかかるのが趣味で、下記のページで、その様子が読めます。

(n) – life is penetration. geeks cheer. geeks be ambitious.

Phishing は、特定の組織を狙えば標的型攻撃になる訳ですが、そういった標的型攻撃メールの対応訓練に関して、間違った訓練になっている、という指摘がありました。単純に開封率やクリック率を見て一喜一憂するのは無駄で、誰が開いたかが重要だし、そもそも、開いてしまった時にどうするのか、という訓練にならないと意味がない、というお話はその通りだと思いました。

3つめは、自分自身のプライバシーを守るために、利用できるツールの紹介でした。匿名化や暗号化ツールは、他方で犯罪者に使われるのでダーティなイメージがあるけど、包丁と同じでツール自体はどっちにも使える、というお話がありました。

最後に、実際に自分のセキュリティを守るために、専門家だけが啓蒙活動するだけはなく、草の根的な広がりが大切、という事を話されていました。自分もその端くれになっていれば良いなぁ、という思いを強くしました。

余談:
最後の質疑応答のところで、「徳丸本」が意外に知られていない事が判明。徳丸さん、せきゅぽろに来ませんか?
ハッシュ値、ソルト、ストレッチングに関する話題の場面でしたが、手前味噌で良ければ、私も書いたことがあるので、参考になれば幸いです。

塩加減は重要? - JULYの日記
調べてみると、結構複雑 - JULYの日記

IPv6 ネタの落ち穂拾い

IPv4 と IPv6 の用語の違い

IPv6 に慣れてしまえば、IPv6 用語を使った方がより正しい表現になるのは分かっていても、IPv4 で慣れ親しんだ用語を使わないと、なかなかイメージしづらい事が多いです。今回、意図的に IPv6 用語を最小限にした書き方にしたのも、自分自身で IPv6 用語が身についていない、というのもあります。

ということで、ちょっと用語を比較してみます。

グローバルアドレス、プライベートアドレス

IPv4 のプライベートアドレスに関しては、ULA*1が該当します。これは今回書いた内容にも多用しています。

若干違うのは、ULA は最初から、「保証はできないけど Unique であるように」という事を意識して、アドレスの決め方を用意している点です。IPv4 のプライベートアドレスで、「192.168.1.0/24」とかが選ばれがちで、そういうときに企業合併などで内部ネットワークをマージしなきゃいけなくなった時に面倒な事になる、という話があったのですが、ULA をきちんと計算して決めると、アドレスが衝突する事はほとんど無くなります。

一方、グローバルアドレスに関しては、GUA(Global Unicast Address)という用語が使われます。

アドレスのネットワーク部、ホスト部

アドレスでネットワークを表す部分とホストを表す部分は、IPv6 ではプレフィックスとインタフェース ID になります。ただし、プレフィックスが必ずしもネットワークという概念と結びつかないケースもあります。

例えば、サイトプレフィックスと呼ばれる 48bit 長のプレフィックスがあって、これは組織単位に割り当てられる、という意味合いになっています。ULA のプレフィックスの決め方も、このサイトプレフィックスの 48bit を決めるもので、このプレフィクスを分割して、通常は 64 bit のプレフィックス長でネットワークアドレスを作る、ということになります。

一方、ホスト部はインタフェース ID と呼ばれ、通常は下位 64 bit のアドレスの事を言います。正直、この「インタフェース ID」という用語は、なかなか身につかないです。

ARP と ND

用語、というよりは、仕組みそのものが違うのですが、イーサネット上の IPv4 で、MAC アドレスと IP アドレスの関係を解決するために ARP というプロトコルがありましたが、IPv6 では ARP は使いません。その代わり、ICMPv6 の一つとして実装される、ND(Neighbor Discovery: 近隣探索)という仕組みを使います。

なので、IP アドレスと MAC アドレスの関係を確認するために「arp -a」などとコマンドを打っても、IPv6 アドレスは出てきません。Windows では netsh で、Linux では ip コマンドで、ND キャッシュの状態を表示する事ができます*2。

IPv4 IPv6
Windows arp -a netsh interface ipv6 show neighbors
Linux arp -a ip -6 neigh

Linux の ip コマンドの場合、「-6」を付けずに「ip neigh」とすれば、IPv4 に関しては ARP キャッシュ、IPv6 に関しては ND キャッシュの両方が表示されます。

IPv6 には無いもの

NAT

NAT が無いのは最初にも書きました。原理的にできないことはないですが、CentOS Ver.6 の ip6tables では nat テーブルが使えません*3。NAPT、いわゆる、IP マスカレードも使えません*4。ルータでも IPv6 の NAT をサポートしているものは少ないでしょう。現時点では NAT は無いと考えた方がよいです。

IPv4 では当たり前のように NAPT をしていて、それが結果的に「意図的な設定をしなければ、インターネット側からはアクセスできない」という状態を作りだし、セキュリティに貢献していた事は事実です*5。

NAT / NAPT が無いということは、普通にルータに繋いだパソコンもグローバルアドレスを持ち、インターネット側からアクセスできる事を意味します。実際、その2で紹介しているフレッツ光ネクストでの接続設定だと、インターネット側からアクセス可能です*6。なので、一般的な IPv6 対応ルータの場合、インターネット側から内部への接続は落とすようなフィルタをデフォルトで有効になっている、という事になっています。

個人で ISP と契約して、64 bit のプレフィックスが与えられることから、「少ないアドレスを分け合うための NAPT」という役割は終わったと言えます。あるとすれば、セキュリティ面からの要望で、IPv4 の時のように、ULA のみ端末からインターネットを利用できるようにしたい、ということはあるかもしれません。その場合の NAT は NAPT のような「1 対 N」ではなく、「N 対 M」で、動的に GUA と ULA をマッピングするようなものになるかもしれません。

ただ、実際につながる環境ができてしまうと、グローバルなアドレスが直接ホストに割り当てられるのは、シンプルで良い感じがします。端末側から見ると、私みたいに ULA を使おうとすると、一つのインタフェースに複数のアドレスが付与されて、なんだか面倒な感じになりますが、インターネット側からアクセスできるかどうかは、純粋にルータフィルタで穴が空いているかどうか、になり、IPv4 の NAPT を使っている環境で、「このプロトコルは大丈夫だけど、これはダメで...」みたいな事はずっと少なくなるはずです。

ブロードキャストアドレス

IPv4 アドレスで、ホスト部が All 1 のアドレスはブロードキャストアドレス、という決まりがありましたが、IPv6 アドレスにブロードキャストアドレスはありません。

ただ、ブロードキャストと同じ役割をするマルチキャストアドレス、というのがあって、ff02::1 というアドレスを使うと、同一セグメントの全てのノード宛、という意味になります。これを「オールノードマルチキャストアドレス」(もしくは「全ノードマルチキャストアドレス」)といいます。

もっとも、使う場面は、何かプロトコルを実装でもしない限り、ほとんど無いと思いますが...。

まとめ

我が家の IPv6 導入顛末は、これでひとまず終わりです。まぁ、IPv6 が使えるようになったと言っても、「おぉ、Google に IPv6 でつながっている!。気持ち、レスポンス良いかも」という程度で、実益は何もありませんが、でも、こうして実際に苦労してみると、「勘所」が IPv4 と IPv6 で違うのを実感しました。

もっとも、「おうち LAN に IPv6」なんて事をしなければ、今以上に「ルータを繋ぐだけ」ですが(^^;。

*1:Unique Local Address かと思うと、RFC 的には Unique Local IPv6 Unicast Address

*2:厳密には、キャッシュだけじゃなくて、固定でマッピングしているものがあれば、それらも表示されます。

*3:kernel 3.7.0 から使えるようになったらしいです。

*4:少なくとも kernel 3.9.0 からは使えるらしいです。

*5:それが油断を生んでいた側面もあるとは思いますが、一般の人が電気屋さんで買ってきたルータを使うことで、直接攻撃から回避できる、というのは、セキュリティ的には都合が良かったと思います。

*6:Web インタフェースで IPv6 の設定をすると、フィルタを使う/使わないの設定があって、簡単に「外からはつながらない」フィルタを設定する事が可能です。もっとも、それに気づかずに半月ぐらい放置していても、IPv6 での SSH に対するブルートフォースアタックはゼロでした。IPv6 アドレスのアドレス空間が広大なので、仮にプローブしても、相手となるホストがほとんど見つからなくて、効率が悪そうですが。