Hatena::ブログ(Diary)

めもおきば このページをアンテナに追加 RSSフィード

Contact: akitan@gmail.com
noteにて投げ銭受付中 ⇒ 【投げ銭】こたろー写真

2015-02-20

Superfishが危険な理由

Lenovo製のPCの一部にSuperfishというマルウェアが標準でインストールされていることが確認され、大きな問題となっています。

経緯や影響範囲等については、Kangoさんの記事にまとまっているのでそちらをご覧ください。

この記事では、Superfishというマルウェアがなぜ特別に危険かを解説します。

Superfishの目的

このSuperfishの目に見える目的は、ブラウザで表示しているウェブサイトに広告を挿入することです。言い換えれば、ウェブサーバから取得したHTMLを書き換えて勝手なJavaScriptを挿入するすることにあります。

目的だけ見れば一般的なアドウェアの一つとも言えます(もちろんそれだけでevilだと個人的には思います)が、Superfishはさらに踏み込んで、普通のやり方では書き換えができない暗号化されたウェブサイトを書き換えるために特殊な方法を利用していますが、その実装方法に大きな問題があるために、広告が挿入されるというレベルをはるかに超えた脆弱性となっています。

前提として、TLS──いわゆるSSLは、ウェブサイトの通信内容を秘匿するだけで無く、その内容の改竄を防ぐことも目的としています。そのため、SuperfishではMITM攻撃と呼ばれる手法で、このTLSの暗号化通信に「穴」を開けています。

TLS(いわゆるSSL)による安全な通信

まず、通常の暗号化された通信を見てみます。

安全に通信を行うためには、自分(のPCで動いているブラウザ)と、その通信相手のウェブサーバの他に、様々な基準によって信頼されたCA(認証局)を利用します。

ウェブサーバは、暗号化するための「秘密鍵」とウェブサイトドメインネーム(このページで言えば「d.hatena.ne.jp」)が書かれた「証明書」を持っていますが、あらかじめこの証明書に、CAの「お墨付き」の判子を押してもらっておきます(図の1)。

その一方で、ブラウザは自分が信頼できるCAの一覧を持っています。これがルート証明書のリストと呼ばれるものです(図の2)。

f:id:nekoruri:20150220025019p:image

安全な通信がしたいときに(3)、まずブラウザはウェブサーバから証明書を送ってもらい、そこに押された判子を見ます(4)。そして、その判子を押したCAが、自分のルート証明書のリストに含まれていることを確認します(5)。このときに、証明書に書かれたドメインネームや有効期限についてもあわせてチェックします。

ここで何か一つでも問題があれば、赤いバッテンとかで警告されてしまうわけです。

MITM攻撃

それでは、具体的にSuperfishが何をやっているか見てみます。

ざっくり言うと、2つのことをやっています。

  1. ブラウザとウェブサーバの間の通信を乗っ取るプログラムを動かす
  2. ブラウザに、乗っ取り用のルート証明書を追加する

f:id:nekoruri:20150220025020p:image

やはり最初にブラウザがウェブサーバから証明書を送ってもらうのですが(1)、Superfishがその通信を横取りしてしまいます。

Superfishは、そのプログラムの中に小さなCAを持っていて、ブラウザが通信しようとしていたウェブサーバのドメインネームでニセの証明書を作成し、Superfish CAの判子を押してブラウザに返します(2)。本来ならばSuperfish CAなんて得体の知れないCAは信頼されていないので警告が出るのですが、Microsoftの決めた基準に反して、Lenovoが勝手にこのSuperfish CAを信頼するように設定してPCを販売しています。

そのため、ブラウザはSuperfish CAの判子が押された証明書を信じてしまうわけです(3)。

こうなってしまえばもうSuperfishのやりたい放題で、一旦そこで暗号も解かれてしまうので、あらためて本来の通信先ウェブサーバから取得したHTMLJavaScriptを組み込んでブラウザに返すことができるようになります(4)。

このように、ブラウザとサーバの間に入り込んで暗号化を攻撃するため、MITM──すなわち、Man-in-the-Middle 攻撃と呼ばれています。

Superfishの問題点

TLSの暗号化は、以下のような前提があって初めて機能します。

  1. ブラウザは、信頼できるCAのルート証明書の一覧を持っている
  2. CAの判子(署名)は、第三者が勝手に押せないよう「CAの秘密鍵」を秘密にしなければいけない
  3. サーバは、その秘密鍵を秘密にしている (CAですら各ウェブサーバの秘密鍵のデータは知らない!)

ところが、ブラウザに勝手に追加されてしまったSuperfish CAは、その秘密鍵を適切に管理していません。具体的には、なんとそのPC上に組み込まれたSuperfishのプログラム内にあります!これは、通信時にリアルタイムでニセの証明書を作って判子を押すために仕方無いことではあります。さらに、このSuperfish CAの秘密鍵や証明書はあらかじめ用意されたもので、全世界すべてのSuperfishで共通のものが使われていました。

となれば、あとは様々なソフトウェアのクラック技術を使えば、誰かのPC上に保存されたプログラムを調べるだけでSuperfish CAの秘密鍵を取得することができます。

恐ろしいことに、Lenovoが紹介している対応方法(電子証明書を利用したWEBサイトにログインできないについてのお知らせ)では、Superfishの通信を書き換えてMITM攻撃をしているプログラムは停止、削除しますが、ブラウザに登録されたSuperfish CAのルート証明書は削除をしません。


これが最悪です。

何が起こるか

ブラウザにはSuperfish CAとやらのルート証明書が信頼できるCAとして登録され、このCAの秘密鍵は誰もが知ることができます。

何が起こるかと言えば、誰でも勝手にウェブサーバの証明書を作成して判子を押して、ブラウザに信頼してもらうことができます。

さらに言えば、Windowsではソフトウェアにも判子による作成者チェックがありますが、それすらもすり抜けることができ、たとえば別の手段を併用してWindows Updateに紛れ込ませることで、OSコンポーネントを差し替えることすら可能かもしれません(あくまで可能性レベルで未検証です)。

こうなってしまえば暗号化も電子署名も何もあったものでは無く、TLSとかSSLとか無かった1990年代初頭に逆戻りです。Heartbleedも裸足で逃げ出すレベル。

そのほかのリスク

また、SuperfishプログラムによるMITM攻撃そのものにも問題があります。本来はウェブサーバの証明書に押された判子の確認(サーバ証明書の検証)をSuperfishプログラムがやっているわけですから、ウェブサーバが送ってきているはずの正しい証明書をブラウザは知ることができません。

そのため、例えば様々な追加情報を表示してくれるはずのEV証明書(いわゆるアドレスバーが緑に染まる奴)も機能しませんし、Superfishの実装が手抜きをしていれば、本来期限切れや、さらに別の第四者による攻撃など別の理由でエラーとなるはずの誤った証明書を知らずに受け付けてしまう可能性もあります。

あとは、Superfishが本来のウェブサーバにアクセスしている暗号化通信に関しても、適切な設定が行われていれば同等ですが、もしブラウザよりも実装の品質が低い場合、暗号化通信の内容自体が解読されやすくなっている可能性もあります(例: DHEにブラウザは対応していたはずなのにSuperfishが非対応のためPFS性が無くなっていた、など)。これはあくまで未検証ですので可能性の話にすぎません。このあたりは、続報が出てくるまで冷静に注視が必要と思います。

どうすれば「まだまし」だったのか

例えばウィルス対策ソフトなど、使用者の適切な同意があったうえでどうしても通信内容を見たいのであれば、ウェブサーバ側から来た証明書のチェックをブラウザと同じように適切に行った上で、Superfish CAのような全世界で共通なんて手抜きをせず、PC別ユーザ別に秘密鍵を生成するのであれば、あきらかな脆弱性ではなくなります。また、EV証明書なども、動的に作るニセ証明書をうまく作り込むことで「それっぽく」見せることは可能かもしれません。

とはいえ、それでもセキュリティ上のリスクが大きく拡大するのは確かなので、MITMなんて手法に頼るのは可能な限り避けるべきだと個人的には考えます。

どうすれば良いか

既にチェックサイトが用意されているので、まずは確認しましょう。

自分のブラウザにSuperfish CAが登録されていなければ、「Good, Superfish is probably not intercepting your connections.」など安全そうな表示が出ることでしょう。表示内容は執筆時点のものなので今後変わる可能性があるのでちゃんと文章を読んでください。

もしSuperfish CAが登録されてしまっていた場合には、ルート証明書を削除する必要があります。

手順についてはたぶん明日になればどっかから出てくと思うのでそれを見てください……。

(2015-02-20 11:22追記) 英語サイトではWindows 8でのルート証明書削除方法が載ったようです。

細かい補足

  • 実際には、今回ターゲットとされているWindowsでは、IEChromeブラウザ個別ではなく、Windowsが提供しているルート証明書のストアを共用しています。Windows Updateなども対象となる可能性があるのはこのためです。その一方でFirefoxOSに依存せず個別に持っています。
  • 「判子」まわりは当然ながら公開鍵と電子署名のメタファですが、細かく厳密に書くと一冊の本ができあがるので、今回をきっかけに興味を持った方には以下の本を紹介します。
  • 基本的に、開発者のデバッグ用途を超えるような、特に一般利用者向けのMITMは腹を切って死ぬべきだという立場です。なぜならそのリスクを利用者に十分に説明することが現実的では無いからです。
  • MITM攻撃は、日本語としては中間者攻撃とも呼ばれます。ただでさえ簡略化した説明なので、先入観が無い方が良いという考えから敢えてこちらで表記しています。

Changelogs

2015-02-06

[] InfluxDB のダウンサンプリングの両端

  • N分間隔のダウンサンプリングすると、過去方向のタイムスタンプで丸め込まれる。
    • したがって、5分間隔の取得なら5mで集計しておけば5分間隔の過去側の時刻に正規化できる。
  • time > N や time < N には N が含まれる
    • 不等号は≧≦として扱う。
    • きっかり両端の時刻のデータがあると含まれてしまうので、ダウンサンプリング済みのデータを扱う場合に考慮する。

テストデータ

  • 00:00:00 と 00:30:00 に 0
  • 00:00:10 から5分おきに1から徐々に増える
  • うっかりJSTでやっちゃったので、クエリでは9時間引いているので注意
時刻timev
2015-01-01 00:00:00 JST14200380100000
2015-01-01 00:00:10 JST14200380100001
2015-01-01 00:05:10 JST14200383100002
2015-01-01 00:10:10 JST14200386100003
2015-01-01 00:15:10 JST14200389100004
2015-01-01 00:20:10 JST14200392100005
2015-01-01 00:25:10 JST14200395100006
2015-01-01 00:30:00 JST14200398000000
2015-01-01 00:30:10 JST14200398100007
2015-01-01 00:35:10 JST14200401100008
2015-01-01 00:40:10 JST14200401100009

検証

SELECT time,mean(v),min(v),max(v) FROM a where time > '2014-12-31 15:00:00.000' and time < '2014-12-31 15:30:00.00' group by time(5m);

時刻timemeanminmax
00:00:0014200380000000.5 0 1
00:05:0014200383000002 2 2
00:10:0014200386000003 3 3
00:15:0014200389000004 4 4
00:20:0014200392000005 5 5
00:25:0014200395000006 6 6
00:30:0014200398000000 0 0

00:30:00として、00:30:00のポイントを含む集計値が含まれている。

SELECT time,mean(v),min(v),max(v) FROM a where time > '2014-12-31 15:00:00.000' and time < '2014-12-31 15:35:00.00' group by time(5m);

時刻timemeanminmax
00:00:0014200380000000.5 0 1
00:05:0014200383000002 2 2
00:10:0014200386000003 3 3
00:15:0014200389000004 4 4
00:20:0014200392000005 5 5
00:25:0014200395000006 6 6
00:30:0014200398000003.5 0 7

SELECT time,mean(v),min(v),max(v) FROM a where time > '2014-12-31 15:00:00.000' and time < '2014-12-31 15:30:00.00' group by time(15m);

時刻timemeanminmax
00:00:0014200380000001.5 0 3
00:15:0014200389000005 4 6
00:30:0014200398000000 0 0

SELECT time,mean(v),min(v),max(v) FROM a where time > '2014-12-31 15:00:00.000' and time < '2014-12-31 15:35:00.00' group by time(15m);

時刻timemeanminmax
00:00:0014200380000001.5 0 3
00:15:0014200389000005 4 6
00:30:0014200398000003.5 0 7

2015-01-30

glibcを更新しても大丈夫な「正しい」タイムゾーンの設定方法 (2/3追記あり)

RHEL, CentOS, Amazon Linux (6以前)

/etc/localtime を /usr/share/zoneinfo 以下から上書きしたりシンボリックリンク張ったりという手法が横行していますが、 /etc/localtime は glibc パッケージに含まれるためパッケージを更新すると上書きされてESTとかに戻ってしまうわけです。

当然ながら、ディストリビューションとして正しい設定方法が用意されているので、こちらを使います。

  1. /etc/sysconfig/clock にタイムゾーンを書きます。*1
    sudo sed -i -e "s/^ZONE/#ZONE/g" -e "1i ZONE=\"Asia/Tokyo\"" /etc/sysconfig/clock
  2. tzdata-update を実行します。
    sudo /usr/sbin/tzdata-update


これだけです。glibcのパッケージをアップデートした時にも、glibc-commonのトリガスクリプトとしてtzdata-updateが自動で呼ばれます。sysconfigで設定してコマンドで現状に反映させるという普通のRHELの世界観そのままですね。

ちなみに、よりRHELの世界観に沿うために、CUIのグラフィカルインターフェースとして system-config-date が用意されていますが、忘れて良さそうな気がします。

(補足) EL7以降というかsystemd系ディストリビューションはtimedatectl(man)使うとのこと。

Ubuntu, Debian GNU/Linux

Debian系というぐらいでdebconf ベースですが、 /etc/timezone を参照してdebconfのデータベースに反映してくれるようになっています。Debianは使っていないので未確認ですが、同じで良いとのこと。

  1. /etc/timezone にタイムゾーンをベタで書きます。
    echo "Asia/Tokyo" | sudo tee /etc/timezone
  2. dpkg-reconfigureでdebconfの設定処理を走らせます。
    dpkg-reconfigure --frontend noninteractive tzdata

CUIでカーソル選択とかしたくない人がほとんどだと思うので、 noninteractive 積極的に使っていきましょう。

ディストリの世界観

今回の「glibc更新するとタイムゾーンがリセットされる!?」とかそうですが、普通に作業して明らかに面倒とか不便とか問題があったら、そのまま回避策を採るのでは無く、まずその設定方法がディストリビューションの世界観に沿っているかを疑ったほうが「急がば回れ」になります。

というか、こういうの探すときに、「ディストリビューションが提供しようとしている世界観」を意識するかどうかで探し方全然変わるので、誰かまとめて欲しい。

超ざっくりこれ:

  • EL系: 設定は/etc/sysconfig 以下に書く。反映方法は割と適当。
  • Debian系: 設定は debconf のデータベースに登録し、dpkg-reconfigureで反映
  • systemd系: なんちゃらctl
  • Gentoo: emergeがなんとかしてくれる

追記: 2015-01-31 01:21

/etc/sysconfig/clock の既存設定を残すよう、tee -a に変更しました。

「正しい」とか煽りながら非互換だしていてすみませんorz

さらに追記 2015-02-03 17:12

tzdata-update は、/bin/sh等に依存しないようにC言語で書かれた小さなプログラムなのですが、最初のZONE指定が有効になるようです*2。安易にtee -aで追記にしたら反映されないというご指摘を頂きました。

sysconfig 以下のファイルは通常はシェルスクリプトとして解釈されるという思い込みがあったのですが、記事修正するときに検証を怠った結果がこれです。

ざっと確認した範囲では見つけられなかったのですが、自前で /etc/sysconfig/clock を呼んでいるシェルスクリプトがあると危険なので、記事無いの置換コマンドは、単純な追記で無く既存のZONE行を潰してから先頭に追記するようにしました。

というわけで、/etc/sysconfig の一般的な文法(これも「世界観」の一部)から外れることもあるので、盲信せずきちんと検証しましょうという良い教訓でした。記事書いて良かった……。

*1:tzdata-update は最初の記述が有効になりますが、シェルスクリプトとして他のソフトウェアから読まれる可能性があるため、他のZONE行は消して置いた方が良いと思います。

*2:たぶんこの辺。見つかったら即breakしてる。 https://www.sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=fedora/tzdata-update.c;h=33bb8c67e379c88dc4af0fcbf5dc33c55973302f;hb=9da0dd7c81b1cedd383e0eba09c9452d2874f862

2015-01-01

あけましておめでとうございます

今年で35歳を迎えるので、引き続きフルスタックエンジニア目指して頑張ります*1

今年の抱負

「明確な成果を出す」

細かい目標はあとで決めます。

読書目標

昨年は無事500冊の目標を505冊で達成できた*2ので、今年も500冊目指して読みます。

ただラノベに偏りすぎたので、サブKPIをいっこ追加で。

  • 月40冊
  • 追加: 技術書(雑誌除く) 10%

ブクログだけだと達成管理できないのどうしようかなあ。

2014-12-31

2014年に読んだ本

2014年は505冊読みました。

技術書 24冊 (5.0%)

nekoruri bookshelf - 2014年01月〜2014年12月 (24作品)
テスタブルJavaScript開眼!  JavaScript ―言語仕様から学ぶJavaScriptの本質説得とヤル気の科学 ―最新心理学研究が解き明かす「その気にさせる」メカニズムITロードマップ2014年版: 情報通信技術は5年後こう変わる!Webアプリエンジニア養成読本[しくみ、開発、環境構築・運用…全体像を最新知識で最初から! ] (Software Design plus)【改訂新版】 サーバ/インフラエンジニア養成読本 [現場で役立つ知恵と知識が満載!] (Software Design plus)【改訂新版】 サーバ/インフラエンジニア養成読本 管理/監視編 [24時間365日稼働を支える知恵と知識が満載!] (Software Design plus)【改訂新版】 サーバ/インフラエンジニア養成読本 仮想化活用編 [クラウドな現場で役立つ知恵と知識が満載!] (Software Design plus)フロントエンド開発徹底攻略 (WEB+DB PRESS plus)Ruby徹底攻略 (WEB+DB PRESS plus)フロントエンドエンジニア養成読本 [HTML、CSS、JavaScriptの基本から現場で役立つ技術まで満載! ] (Software Design plus)Chef実践入門 ~コードによるインフラ構成の自動化 (WEB+DB PRESS plus)Amazon Web Services 基礎からのネットワーク&サーバー構築すべてわかる4G大全 (日経BPムック)ITナビゲーター2014年版パターンによるソフトウェア構成管理 (IT Architects’ Archive―ソフトウェア開発の課題)パーフェクトPython (PERFECT SERIES 5)AngularJSリファレンスAngularJSアプリケーション開発ガイドクラウドデザインパターン Azureを例としたクラウドアフリケーション設計の手引きOpenStack Swift: Using, Administering, and Developing for Swift Object StorageImplementing Cloud Storage with OpenStack SwiftSoftware Defined Storage with OpenStack Swiftインフラエンジニア教本 ~ネットワーク構築技術解説 (Software Design 別冊)
powered by booklog

技術書(雑誌) 21冊 (4.2%)

nekoruri bookshelf - 2014年01月〜2014年12月 (21作品)
週刊 アスキー 2014年 3/11号 [雑誌]Software Design (ソフトウェア デザイン) 2014年 03月号 [雑誌]週刊 アスキー 2014年 3/18号 [雑誌]WEB+DB PRESS Vol.78週刊アスキー 4/29増刊号日経 Linux (リナックス) 2014年 05月号Software Design (ソフトウェア デザイン) 2014年 05月号 [雑誌]Software Design (ソフトウェア デザイン) 2014年 04月号 [雑誌]Software Design (ソフトウェア デザイン) 2014年 06月号 [雑誌]WEB+DB PRESS Vol.81Software Design (ソフトウェア デザイン) 2014年 07月号 [雑誌]週刊 アスキー 2014年 7/22号 [雑誌]Software Design (ソフトウェア デザイン) 2014年 08月号 [雑誌]週刊アスキー 2014年 8/12増刊号WEB+DB PRESS Vol.82Software Design (ソフトウェア デザイン) 2014年 10月号 [雑誌]Software Design (ソフトウェア デザイン) 2014年 11月号 [雑誌]WEB+DB PRESS Vol.83Software Design (ソフトウェア デザイン) 2014年 12月号 [雑誌]Software Design (ソフトウェア デザイン) 2015年 01月号 [雑誌]WEB+DB PRESS Vol.84
powered by booklog


ライトノベル 424冊 (84.0%)

nekoruri bookshelf - 2014年01月〜2014年12月 (424作品)