Dockerfile for RawGit

RawGit落ちてて自前でも欲しいって話が出たので早速作ってみる。


docker run -d -e FQDN=rawgit.example.jp --name rawgit -p 80:80 -p 443:443 nekoruri/rawgit:0.1

Vagrant用にbootstrap.shがあったのでそのままそれを利用してるので、そのままだとオレオレ証明書が勝手に作られてTLSでもサービス上がります。このあたりの整備は後ほど。

あと、12-factor appに従って、docker run -e FQDN=rawgit.example.jp でFQDNを注入できるようにしてみた。

ミニマムなDockerfile for GrowthForecastつくってみた

自分が使いたくてミニマムなGrowthForecastのDockerfileが欲しかったので作ってみた。

とりあえずDocker hubに投げてみたけど、Buildingから進まないので細かいことはあとで書く。

あと、いくつか考えたポイントをGistにぺらぺら書き残してる。

これだけでいける。


mkdir -p $HOME/vol/gf
docker run -d --name growthforecast -v $HOME/vol/gf:/data:rw -p 5125:5125 nekoruri/growthforecast:0.1

残り課題

  • VOLUME書き忘れた
  • [ok] Trusted buildからpullして動かすテスト
  • timezone

ウェブアプリにおけるBash脆弱性の即死条件 #ShellShock

条件2. 動作環境

条件3. プログラム内容

  • Passengerは全死亡 *1
  • systemや `command`、 '| /usr/lib/sendmail' などで外部コマンド実行 *2
  • PHPのmailやmb_send_mail、その他フレームワーク等を介したメール送信 *3
  • 以下は条件1が不要
    • 明示的にbashを呼ぶ
    • 先頭で #!/bin/bash や #!/usr/bin/env bash しているプログラムを実行 (rbenv等)

補足: Passengerについて

Passengerは、デフォルトでRAILS_ROOT/config/environment.rbのファイル所有者の権限で実行されるため、一般的なインストール状況であればpublic以下にファイルを置いたり等なんでもできます。特に、パスワード無しでのsudoが可能なユーザでファイルを置いていた場合には、なんでも、できることを、手元では検証しました。

ワーカプロセスは使い回されるため、百発百中ではありませんが、一定のリクエスト毎にワーカプロセスを捨てて作り直すPassengerMaxRequestsが設定されていたり、アクセス量に応じてワーカプロセス数が変動するデフォルト設定であれば、繰り返しの試行により再現が可能と思われます。

*1:ワーカプロセス生成時に/bin/shを経由するため。参考: Security advisory

*2:PerlRubyでメタ文字を含まないsystemなど直接execvp(3)するものはセーフ

*3:QdmailやSwift mailer等でSMTPサーバを指定して接続している場合はセーフ

投げ銭箱

例によって物は試しということで、話題のnoteに投げ銭箱置いてみました。

OpenSSLの記事が少しでも役に立ったー、とか、note.muの購入機能試してみたい、とかいう奇特な人が居たらどうぞ。売上はご報告の上でラーメン代の足しにします。

ちなみに、私自身は尊敬している結城先生の記事に投げ銭してみました。

OpenSSL #heartbleed 脆弱性の影響とその後を考えるときのメモ

影響を受けたウェブサイトやソフトウェアの対応については、piyologさんの以下の記事に詳しいです。

この記事では、それ以外の動きについてまとめていきます。先週の2つの記事と違い、あくまで個人的興味によるものです。

日本政府およびセキュリティ関連組織による情報公開

ベンダー等による情報公開

今回の脆弱性に関する考察と議論

代替策に向けた議論

より安全なcipher suiteの検討

これまでのHeartbleed以外のSSL実装のバグ

OpenSSLの脆弱性で想定されるリスク

JVNJPCERT/CCの記事があまりにもさらっと書かれていて、具体的なリスクが想像しづらいと思うので説明します。

今北産業 (今ニュース見て来たから三行で教えて欲しいという人向けのまとめ)

  1. インターネット上の「暗号化」に使われているOpenSSLというソフトウェアが2年間壊れていました。
  2. このソフトウェアは便利なので、FacebookだとかYouTubeだとか、あちこちのウェブサイトで使っていました。
  3. 他の人の入力したIDとかパスワードとかクレカ番号とかを、悪い人が見ることができてしまいます。(実際に漏れてる例)

他にも色々漏れてますが、とりあえずエンジニア以外の人が覚えておくべきはここまででOKです。もう少し分かりやすい情報が以下にあります。

まだ直っていないウェブサイトもあれば、元々壊れていないウェブサイトもあるので、「直したからパスワード変更してね」って言ってきたら変更してください。あと、悪い人が偽メール送ってきているので、メールで連絡してきたとしても、ブラウザのブックマークから開きましょう。

ここからはエンジニア向けの詳細です。

今回の脆弱性の内容

いわゆる「SSL通信」と呼ばれる暗号化通信は、実際にはSSL 3.0とより新しいTLS 1.0〜1.2(互換性のためプロトコル上の番号は3.1〜3.3)というプロトコルで定義されています。これらを使うために、様々なソフトウェアが利用している共通ライブラリが OpenSSL です。今回の脆弱性は、このTLS 1.2に追加されたハートビート拡張*1の実装の不具合によるものです。

SSL通信の最初「ハンドシェーク」段階でSSL証明書の検証などを行いますが、今回の脆弱性はそのハンドシェーク段階の中でも発生する*2ため、正しいSSL証明書を持っていなくても攻撃が成立します。ほとんどの場合にログが残らないのもこのためです。

攻撃者は、通信の相手のメモリ内容を取得することができます。一回で最大64キロバイト、同じプロセス内の情報に限られますが、ログに残らず、めぼしい情報が取得できるまで何度でも繰り返すことができるため(これがメモリガチャと呼ばれる理由)、プロセス内の全ての情報が漏洩したと考えるべきです。

「同じプロセス」というところが問題で、どのプロセスがSSL通信をしたかによってリスクが大きく変わります。

ロードバランサーSSLを提供し、脆弱性があった場合

ロードバランサーSSLのサーバ側として、SSL証明書秘密鍵をメモリ内に保持します。この秘密鍵が攻撃者に漏洩します。

SSL処理をしているところでデータが漏洩した場合のリスクは、大きく三つあります。
(これは、Apache等でSSL処理をしている場合も同様です!)

すぐ直前の通信内容を盗聴されてしまう

空きメモリ内には、直前の通信内容がクリアされず残っている場合があります。SSL処理が終わり復号された平文の通信内容もふくまれるため、以下のような攻撃が成立します。

過去の通信内容を盗聴されてしまう

特に意識せず設定されたSSLサーバの場合、SSL証明書秘密鍵を知っている攻撃者は、暗号化されているはずの通信内容を復号して、内容を見ることができます。

特に、毎年SSL証明書を更新する毎に秘密鍵を作り直していなかった場合、過去の通信内容を保存している組織*3があった場合、過去に遡って全ての通信内容を復号して、そのなかのあらゆる情報を知ることができます。たとえ毎年秘密鍵を生成し直していた場合でも、直近の最大1年間の通信内容は全て筒抜けです。

これに対しては、Forward Secrecyという対策が存在します。

ただし、これまで必要性が重要視されなかった(まさかこれほど大規模に秘密鍵が漏洩する脆弱性が見つかるなんて思われていなかった)、性能が従来のRSAより若干遅い、などの理由があってあまり普及していません。今回を良い機会として、利用している暗号化アルゴリズムを見直し、Forward Secrecyを有効にするのが良いでしょう。Verisignから証明書ビジネスを引き継いだSymantecは以下のように主張しています。

結論として、ウェブサイトが RSA から離れて Forward Secrecy を提供するとともに、極めて低速なDHEよりもECDHE 鍵交換を配備することを、我々は強く推奨します。

誰かに偽のSSLサーバを立てられてしまう

たとえば、sns.example.jp というSNSSSL証明書秘密鍵が漏洩したとします。攻撃者はすかさず、その秘密鍵を使って、sns.example.jp の正当なSSL証明書を持った偽サーバを公開できます。公衆Wifiを使っていたり、DNSへの攻撃を併用すれば、その偽サーバにアクセスさせることができます。

アドレスバーを見ろと言ったところで正しいドメインで鍵が表示されているわけですし、たとえEV-SSL証明書を使ってアドレスバーを緑に染め上げていたとしても、全く同じ証明書でサーバを用意されてしまっては無力です。

これが、脆弱性のあるバージョンを使っていた場合に証明書の再発行だけでなく、「失効」が必要となる理由です。

ApacheやnginxでSSLを提供し、脆弱性があった場合 (APサーバ併用)

アプリケーションサーバの前段にApacheやnginxを設置し、そこでSSL処理を行っていた場合です。

ロードバランサーの場合に加えて、以下の情報が漏洩します。

  • httpd.confや.htaccessで設定されている内容の全て
  • Apacheが読み取っていたhtpasswdファイルの内容

ApacheSSLを提供し、脆弱性があった場合 (mod_php5,mod_perl等)

mod_php5やmod_perlなどを利用し、Apacheモジュールとしてウェブアプリケーションを動かしていた場合です。

これまで登場した全ての内容に加えて、以下の内容が漏洩します。

  • 全てのアプリケーションコード
  • 全てのアプリケーション設定
    • データベース等の接続先、ユーザ名、パスワード
    • TwitterFacebook等のconsumer_secret
    • Rails等のCookieベースセッションの暗号化キー(secret_token, secret_key_base)
  • DB等から取得したメモリ上のデータ全般(別リクエストの内容も、場合によって空きメモリに残っている可能性がある)

ここまでくると、想定されるリスクはかなり大きいです。

  • 別ユーザからのリクエストに含まれた、パスワードや個人情報、クレジットカード番号、セキュリティコードなどが空きメモリに残っていた場合、それが漏洩します。
  • Cookieベースセッションは、自由にセッションデータの捏造ができます。
  • インターネットからDBサーバ等に直接接続ができなくとも、別の攻撃を行うための予備情報を攻撃者に与えることになります。

PHPであっても、PHP-FPMを使うなどApacheとプロセスを分けることで、権限ごと分離できるので、今回を期に挑戦すると良いのでは無いでしょうか*4

外部のサーバ等にSSL通信を行っている場合

SSH系を除くほぼ全てのクライアントアプリケーションの暗号化通信が当てはまりますし、サーバ側であっても、外部のAPIサーバへの通信などにはあてはまります。

あくまでこの場合、攻撃者が用意したサーバに接続しない限り安全であると考えられますが、その一方で、DNSキャッシュポイズニングBGPのハイジャックなど、攻撃する側がトラフィックを呼び込むための手法が存在しています。

これをされた場合、そのクライアントが持っている接続先リストやそこに含まれるユーザー・パスワードが漏洩します。

外部に接続するサーバ側アプリであれば、前述の「ApacheSSLを提供し、脆弱性があった場合 (mod_php5,mod_perl等)」と同等です。例えばSSLサーバとしては社内からの接続しか受けていなかったとしても、抜け道があるので、やはり上げておきましょう、ということです。

まとめ

  • 脆弱性の影響を受けていたら、証明書の「失効」までが必要です。
  • Forward Secrecy が無ければ、秘密鍵の漏洩が通信内容の漏洩に直結します。
  • SSL処理とアプリケーションコードはプロセスを分けよう。

補足情報

あまりにも再現が容易であることから、既に脆弱なサーバの探索が増えているようです。

警察庁の定点観測システムにおいても、9日以降、当該攻撃コードに実装されている
Client Hello パケットと、完全に一致するパケットを多数観測しています。このことから、同攻撃コードを使用して、脆弱性が存在するサーバ等の探索が実施されているものと考えられます。

*1:2012年2月にRFC6520として公開され、PMTU discoveryなどを想定しているようです。

*2:なお、RFC6520としては、ハンドシェーク中のHeartbeatRequestは捨てるべき(SHOULD)となっています。

*3:某国のNなんちゃらとか

*4:実際、OpenSSHにはそうやって権限分離が実装されたという歴史があります。

CVE-2014-0160 OpenSSL Heartbleed 脆弱性まとめ

必要な情報は http://heartbleed.com/ にまとまっているのですが、英語だし長いしって人のために手短にまとめておきます。

どうすればいいのか

  1. OpenSSL 1.0.1〜1.0.1fを使っていなければセーフ
  2. あてはまる場合には、一刻も早くバージョンアップして、サーバごと再起動(わかるひとはサービス単位でもOK、ただしreloadではだめなことも)
  3. SSL証明書でサーバを公開しているなら、秘密鍵から作り直して証明書を再発行し、過去の証明書を失効させる(末尾に関連リンクあり)。
  4. サーバを公開していない場合も、外部へのSSL通信があれば影響を受けるので、詳しく精査する。
  5. PFS(perfect forward secrecy)を利用していない場合、過去の通信内容も復号される可能性があるため、詳しく精査する。

漏洩する情報の具体例は、OpenSSLの脆弱性で想定されるリスクとして別の記事に書きましたのでそちらをご覧くださいまし。

影響を受けるディストリビューション

基本的には、パッケージ更新などでOpenSSLをバージョンアップして、そのあとOpenSSLを読んでいるサービスを再起動します。外部サーバへの接続なども含めるとOpenSSLを利用するサービスが多いので、よく分からない人はサーバごと再起動がおすすめ。

1.0.1からの新機能による脆弱性なので、1.0.0とそれ未満であれば問題ありません。逆に、1.0.1eやそれ以前のバージョン番号のまま脆弱性のみ修正される場合もあるので、OpenSSLのバージョンだけでなく、パッケージのバージョンを確認してください。

ディストリ どうすればいいか
Debian Wheezy (stable)以降 DSA-2896-1
stable: libssl1.0.0 1.0.1e-2+deb7u5 で修正
testing/unstable: libssl1.0.0 1.0.1g-1 で修正
Ubuntu 12.04.4 LTS以降 [USN-2165-1]
12.04: libssl1.0.0 1.0.1-4ubuntu5.12 で修正
12.10 libssl1.0.0 1.0.1c-3ubuntu2.7 で修正
13.10 libssl1.0.0 1.0.1e-3ubuntu1.2 で修正
RHEL 6.5 [RHSA-2014:0376-1]
openssl-1.0.1e-16.el6_5.7で修正
CentOS 6.5 [CESA-2014:0376]
openssl-1.0.1e-16.el6_5.7 で修正
Scientific Linux 6.5 openssl-1.0.1e-16.el6_5.7 で修正
Fedora 18以降 [Bug 1085065]
Fedora 19: openssl-1.0.1e-37.fc19.1 で修正
Fedora 20: openssl-1.0.1e-37.fc20.1 で修正
(Fedora 18はサポート切れのため公式パッケージ無し)
OpenBSD 5.3以降 [Patches for OpenSSL bounds checking bug]
パッチあり: 5.3 / 5.4 / 5.5
FreeBSD ports [[ports] Revision 350548]
security/openssl 1.0.1_10 で修正
FreeBSD 10.0 [FreeBSD-SA-14:06.openssl]
freebsd-updateでバイナリ更新するかpatchあててbuildworld/installworld/reboot
NetBSD pkgsrc [NetBSD Security Advisory 2014-004]
openssl-1.0.1gで修正
NetBSD 6.0以降 [NetBSD Security Advisory 2014-004]
各arch向けにビルド済みバイナリが配布されている。
OpenSUSE 12.2 [openSUSE:Maintenance:2718]
Amazon Linux 2013.03以降 [Thread: openssl heartbleed]
ALAS-2014-320: openssl Security Update - Information Disclosure Vulnerability]
2013.09: openssl-1.0.1e-4.58.amzn1 で対応
2014.03: openssl-1.0.1e-37.66.amzn1.x86_64 で対応
Amazon ELB [HeartBleed Bug Concern]
[AWS Services Updated to Address OpenSSL Vulnerability / 参考和訳]
全てのRegionで対応済み、ただし証明書の更新を推奨
(リスクの度合いは不明)
Amazon CloudFront [AWS Services Updated to Address OpenSSL Vulnerability / 参考和訳]
対応済み、ただし証明書の更新を推奨
(リスクの度合いは不明)
Homebrew [openssl 1.0.1g]
brew update
brew upgrade openssl
brew link openssl --force
(コメ欄にて詳しい手順有り)
Gentoo Linux [GLSA 201404-07 / openssl]
dev-libs/openssl-1.0.1g で修正
BIG-IP [SOL15159: OpenSSL vulnerability CVE-2014-0160]
11.5.0以降が影響を受ける模様
「Use only Native SSL stack ciphers」に設定していれば回避可能
Google Compute Engine [Security Bulletins]
各ディストリの v20140408 以降のイメージで作り直すか、yum/aptでパッケージ更新
Android 4.1.1 [Google Services Updated to Address OpenSSL CVE-2014-0160 (the Heartbleed bug)]
Android 4.1.1のみ影響
ChromeはOpenSSLを使わない(NSS)のため影響外

自前で入れたり、バージョンアップがすぐにできない場合は、「-DOPENSSL_NO_HEARTBEATS」を設定し、OpenSSLをコンパイルしてもよい。

  • 影響を受けない主要ディストリ:
  • 個別のベンダー製品については、各社のURLが以下の記事に集約されているのでこちらを探してください。

その他影響を受けるソフトウェア群

ソフトウェア 対応
Cygwin [Updated: openssl-1.0.1g-1]
openssl-1.0.1g-1 で対応
TeraTerm(TTProxy) 影響無し
当初「SSH部分に影響無し、TTProxyでSSL利用時のみ影響を受ける可能性」と書いていましたが、今のところSSL通信をしないとのこと[出典]
Apache mod_spdy 独自OpenSSLを内部で持つのでv0.9.4.2に上げる(出典)
Phusion Passenger [Phusion Passenger 4.0.41 released, OpenSSL Heartbleed security update]
OpenSSLを静的リンクしており4.0.41未満で影響あり
Ruby RVM [rvm/config/db]
rvm管理下で別にopensslを入れた場合は対応が必要
Ruby rbenv/ruby-build [OpenSSL library updated to 1.0.1g #547]
ruby-buildプラグインで別にopensslを入れた場合は対応が必要
plugins/ruby-build下でgit pullしてrbenv installしなおす
OpenVPN [OpenVPN 2.3.2 Windows build I004 リリース]
[OpenSSLの脆弱性 – Heartbleed について]
Windows版バイナリにOpenSSLが含まれるため、OpenVPN側のバージョンアップも必要。
Android版クライアントもAndroid 4.1(.0)と4.1.1は影響を受けるのでAndroid対応待ち
TLS-Authを使っていなければ影響は無い。TLS-Authを使っていれば影響は無い。
修正(2014/04/10 18:24)
TLS-Authの記述が逆になっていました。TLSハンドシェークの前にHMACによるチェックを挟む機能で、有効にしていれば影響を受けません。こちらの記事に詳しく書かれています。
FFFTP [臨時版 1.98g1 - FFFTP]
FTPS(FTP over TLS/SSL)のみ影響、1.98g1 で対応
WinSCP [OpenSSL vulnerability CVE-2014-0160]
5.5.3で対応予定
通常のSCP/SFTPには無関係、FTP over TLS/SSLを使っている場合のみ影響

関係しそうなサービス

  • HTTPSサーバ (上記mod_spdyにも注意)
  • メールサーバ SMTP(STARTTLS, SMTP over SSL), POP3/IMAP (STARTSSL, POP3/IMAP over SSL)
  • そのほかのSSL/TLSを提供するサーバ
  • 外部HTTPSサイト(外部APIサーバ等)への接続するクライアント、バッチ処理等のプログラム全般
  • FTPSサーバ、クライアント
  • LDAPSで認証もらってる
  • MySQLPostgreSQLへの接続を暗号化

何が起きているの

OpenSSLに脆弱性があり、SSLで通信している相手のメモリを閲覧できます*1
具体的には、以下のようなシナリオが考えられます。

  • 攻撃者がクライアント側の場合、 HTTPSサーバのSSL証明書秘密鍵が漏洩する。
  • 攻撃者がクライアント側の場合、 HTTPSサーバのプロセス内にあるユーザー情報が漏洩する。特にApache+mod_php5のコンボでは、ウェブアプリ内の全ての情報が見られる可能性がある。
  • 攻撃者がサーバ側の場合、HTTPSで外部のAPIサーバ等に接続したアプリケーションが、メモリ内にあるユーザー情報等が漏洩する。
    • これが危険になるケース: HTTPSのCommonNameの検証をきちんと行っていない場合や、審査が緩いCAが同じ名前でSSL証明書を発行した場合、外部APIサーバのSSL証明書秘密鍵が奪取された場合など
    • 04/08 22:34追記: そもそもハンドシェークフェーズなので証明書の検証は無関係でした。DNS毒入れ等の併用で攻撃者のSSLサーバに接続させられてしまえば無条件でやられます。
  • 攻撃された記録は一切残らない。安全側に倒すならば、脆弱性のあるバージョンをインターネットに公開していたら攻略されたとみなす方が良い。

SSL証明書等の扱い

脆弱性のあるバージョンを使っていた場合、最悪でSSL証明書秘密鍵が奪取されている可能性があります。この場合、現在使っているSSL証明書を失効(revoke)させ、再発行する必要があります。

証明書の失効方法については、SSL証明書を発行したCAに問い合わせてください。CA側で管理する証明書失効リストに掲載され、漏洩した秘密鍵によるSSL証明書が使えないようになります。例えばSymantec(旧Verisign)であればストアフロントから失効申請ができるようです。

直接の関係が無いもの

  • あくまでSSL通信(TLSプロトコル)上の脆弱性のため、OpenSSLライブラリを使っていても、OpenSSHやGnuPG(PGP)などには直接は関係しません。ただし、OpenSSHがLDAP等で外部へのSSL通信を行う場合、そこから攻撃される可能性が残ってはいます。
  • 読み取られるのは、SSL通信を行っているプロセスのメモリ内容のため、ロードバランサや前段のApache等でSSL処理を行っている場合は、別プロセスのアプリケーションサーバ内のメモリ内容は漏洩しません。ただし、前述の通り外部へのSSL通信を行っている場合は別です。
    • curlコマンドを別プロセスで起動している場合*2や、OpenSSL以外のライブラリを使っている場合も無関係です。
  • そのプロセスが読んでいない無関係なファイル等は、たとえそのプロセスの実行ユーザにパーミッションが開かれていても漏洩しません。あくまでプロセスのメモリ内容のみです。

関連URL

*1:64KB単位で何度でも繰り返せる。要するにSR双葉杏が引けるまで何度でも引けるガチャ。

*2:RHEL6/CentOS6系のcurlはOpenSSLのかわりにNSSを使っているため影響を受けないようです。