Posted by usa on 27 Oct 2014
Translated by usa
Ruby 2.1.4、Ruby 2.0.0-p594、Ruby 1.9.3-p550 において、ext/openssl のデフォルト設定が従来のものから変更されています。 今回の変更により、安全でない SSL/TLS オプションがデフォルトで無効化されるようになりましたが、これに伴い、利用状況によっては SSL 接続に際して問題が生じる可能性があります。
詳細
OpenSSL には、現在では安全ではないとみなされるプロトコルや暗号方式などが、歴史的事情により依然として実装されています。 最近話題となった POODLE 脆弱性 (CVE-2014-3566) に見られるように、これらの安全ではない機能を有効にしたままで OpenSSL を利用し続けた場合、攻撃者によって通信を傍受されるおそれがあります。 そこで、Bug #9424 での議論を踏まえ、Ruby では既に安全ではないとわかっている SSL/TLS オプションについては、デフォルトで無効となるよう変更を行いました。 この変更を無効化する必要がある場合は、以下に示す対応する変更を取り消すパッチを各自で適応してください。
ただし、今回の変更を取り消した場合、通信の安全が確保できなくなる可能性があります。 影響を十分理解した上で行ってください。
Ruby の標準添付ライブラリ
今回の変更は、標準添付ライブラリに関しては、net/http、net/imap、net/pop においてデフォルトで反映されます。 DRb および WEBrick については、別途設定を受け付けるようになっているため、今回の変更は直接には反映されません。
直接 ext/openssl を使用している場合
直接 ext/openssl を使用しているスクリプトに関しては、OpenSSL::SSL::SSLContext
オブジェクトを自前で作成し、その set_params
メソッドを呼び出した上で OpenSSL::SSL::SSLSocket.new
の第2引数に渡した場合にのみ、今回の変更が反映されます。
具体的には以下のようなコードになります。
ctx = OpenSSL::SSL::SSLContext.new
ctx.set_params # if you want to change some options, such as cert store, verify mode and so on, you can pass such parameters within a hash
ssl = OpenSSL::SSL::SSLSocket.new(socket, ctx)
なお、Ruby をクライアント側として使用する場合は、今回の変更を反映しても問題が生じるケースはほとんどないと考えられますが、不特定のクライアントからの接続を受け付けるサーバとして使用する場合、上記のコード例のような形で今回の変更を反映してしまうと、古いクライアント (Windows XP 上の Internet Explorer 6 や、古い携帯電話のブラウザなど) から接続できなくなります。 サーバ側で利用する場合は、その旨を考慮した上で反映すべきかどうかを判断してください。
回避策
何らかの事情で Ruby の更新はできないけれども安全でない SSL/TLS オプションへの対処は必要であるという場合は、以下に示すモンキーパッチを適応してください。
module OpenSSL
module SSL
class SSLContext
remove_const(:DEFAULT_PARAMS)
DEFAULT_PARAMS = {
:ssl_version => "SSLv23",
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
:ciphers => %w{
ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES256-GCM-SHA384
DHE-RSA-AES128-GCM-SHA256
DHE-DSS-AES128-GCM-SHA256
DHE-RSA-AES256-GCM-SHA384
DHE-DSS-AES256-GCM-SHA384
ECDHE-ECDSA-AES128-SHA256
ECDHE-RSA-AES128-SHA256
ECDHE-ECDSA-AES128-SHA
ECDHE-RSA-AES128-SHA
ECDHE-ECDSA-AES256-SHA384
ECDHE-RSA-AES256-SHA384
ECDHE-ECDSA-AES256-SHA
ECDHE-RSA-AES256-SHA
DHE-RSA-AES128-SHA256
DHE-RSA-AES256-SHA256
DHE-RSA-AES128-SHA
DHE-RSA-AES256-SHA
DHE-DSS-AES128-SHA256
DHE-DSS-AES256-SHA256
DHE-DSS-AES128-SHA
DHE-DSS-AES256-SHA
AES128-GCM-SHA256
AES256-GCM-SHA384
AES128-SHA256
AES256-SHA256
AES128-SHA
AES256-SHA
ECDHE-ECDSA-RC4-SHA
ECDHE-RSA-RC4-SHA
RC4-SHA
}.join(":"),
:options => -> {
opts = OpenSSL::SSL::OP_ALL
opts &= ~OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS if defined?(OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS)
opts |= OpenSSL::SSL::OP_NO_COMPRESSION if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
opts |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
opts |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
opts
}.call
}
end
end
end
今回の変更の影響を受けるバージョン
- Ruby 1.9.3 patchlevel 550 以降の Ruby 1.9.3
- Ruby 2.0.0 patchlevel 594 以降の Ruby 2.0.0
- Ruby 2.1.4 以降の Ruby 2.1
- revision 48097 以降の開発版 (trunk)
更新履歴
- 2014-10-27 21:00:00 (JST) 初版