■Debianの修正情報が014/03/07に出ている。 「なるほど、よく分からん。」という印象でしたので、調べてみた。 Debian Security Advisory https://www.debian.org/security/2014/dsa-2896 ■Wheezyである私の環境も対象の「1.0.1e-2+deb7u4」を使用している。 「1.0.1e-2+deb7u5」が修正されたバージョン。 $ sudo strings /usr/bin/openssl | grep libssl libssl.so.1.0.0 $ sudo ldd /usr/bin/openssl | grep "libssl.*1.0.0" libssl.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007f5d544dc000) $ openssl version OpenSSL 1.0.1e 11 Feb 2013 $ dpkg-query -p openssl | grep "Version\|depends" Version: 1.0.1e-2+deb7u4 $ sudo apt-get update $ sudo apt-cache show openssl | grep -i "Version\|depends" Version: 1.0.1e-2+deb7u5 Depends: libc6 (>= 2.7), libssl1.0.0 (>= 1.0.1), zlib1g (>= 1:1.1.4) Version: 1.0.1e-2+deb7u4 Depends: libc6 (>= 2.7), libssl1.0.0 (>= 1.0.1), zlib1g (>= 1:1.1.4) ■対象外のコンパイルオプションとは「-DOPENSSL_NO_HEARTBEATS」。 「HeartBeart」を無効にするようなコンパイルオプションは無いので、 私の環境は対象外には該当しない。 $ sudo openssl version -a | grep compiler | sed s/" \-"/"\n&"/g | column compiler: gcc -DL_ENDIAN -Wl,-z,relro -DSHA256_ASM -fPIC -DTERMIO -Wa,--noexecstack -DSHA512_ASM -DOPENSSL_PIC -g -Wall -DMD5_ASM -DZLIB -O2 -DMD32_REG_T=int -DAES_ASM -DOPENSSL_THREADS -fstack-protector -DOPENSSL_IA32_SSE2 -DVPAES_ASM -D_REENTRANT --param=ssp-buffer-size=4 -DOPENSSL_BN_ASM_MONT -DBSAES_ASM -DDSO_DLFCN -Wformat -DOPENSSL_BN_ASM_MONT5 -DWHIRLPOOL_ASM -DHAVE_DLFCN_H -Werror=format-security -DOPENSSL_BN_ASM_GF2m -DGHASH_ASM -m64 -D_FORTIFY_SOURCE=2 -DSHA1_ASM ■OpenSSLの「heartbeat」 という機能の実装から「Heartbleed」と呼ばれている。 RFCにある「heartbeat_request」と「heartbeat_response」がそれっぽい。 RFC6520 http://www.rfc-editor.org/rfc/rfc6520.txt OpenSSL の脆弱性に関する注意喚起 https://www.jpcert.or.jp/at/2014/at140013.html $ w3m -dump http://www.rfc-editor.org/rfc/rfc6520.txt | grep "heartbeat_re[a-z]*(" heartbeat_request(1), heartbeat_response(2), ■「ssl/d1_both.c」「t1_lib.c」のソースが修正されている。 existential type crisis : Diagnosis of the OpenSSL Heartbleed Bug http://blog.existentialize.com/diagnosis-of-the-openssl-heartbleed-bug.html $ sudo apt-get source --download-only openssl $ tar ztvf openssl_1.0.1e.orig.tar.gz | grep d1_both.c -rw-rw-r-- openssl/openssl 44243 2013-02-12 00:26 openssl-1.0.1e/ssl/d1_both.c $ tar zxvf openssl_1.0.1e.orig.tar.gz openssl-1.0.1e/ssl/d1_both.c openssl-1.0.1e/ssl/d1_both.c $ grep -A 8 "HeartBeat" openssl-1.0.1e/ssl/d1_both.c /* Create HeartBeat message, we just use a sequence number * as payload to distuingish different messages and add * some random stuff. * - Message Type, 1 byte * - Payload Length, 2 bytes (unsigned int) * - Payload, the sequence number (2 bytes uint) * - Payload, random bytes (16 bytes uint) * - Padding */ ■「HeartBeat message」のメモリアドレスの位置が予測可能な実装をしていて、 影響範囲がTLSとDTLSということかな。。。 $ w3m -dump "http://www.rfc-editor.org/rfc/rfc6520.txt" | grep payload_length uint16 payload_length; opaque payload[HeartbeatMessage.payload_length]; payload_length: The length of the payload. payload_length is 2. Therefore, the padding_length is TLSPlaintext.length - payload_length - 3 for TLS and DTLSPlaintext.length - payload_length - 3 for DTLS. The If the payload_length of a received HeartbeatMessage is too large, ■以下を参考に、DTLSは再送タイマーを使ってパケットロスに対処するTLSの拡張と解釈出来る。 RFC 4347 (DTLS) について調べてみた http://mdgw.hateblo.jp/entry/20080217/1203273902 ■「payload」の配列境界のチェックを行うようにしたのが今回のパッチということかな。。。 $ tar ztvf openssl_1.0.1e-2+deb7u5.debian.tar.gz | grep CVE | awk '{print $NF}' debian/patches/CVE-2013-6449.patch debian/patches/CVE-2013-4353.patch debian/patches/CVE-2014-0160.patch debian/patches/CVE-2013-6450.patch $ tar zxvf openssl_1.0.1e-2+deb7u5.debian.tar.gz debian/patches/CVE-2014-0160.patch debian/patches/CVE-2014-0160.patch $ grep -i "^+++\|RFC\|HEARTBEAT" debian/patches/CVE-2014-0160.patch Subject: [PATCH] Add heartbeat extension bounds check. A missing bounds check in the handling of the TLS heartbeat extension +++ b/ssl/d1_both.c @@ -1459,26 +1459,36 @@ dtls1_process_heartbeat(SSL *s) s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, + return 0; /* silently discard per RFC 6520 sec. 4 */ + unsigned int write_length = 1 /* heartbeat type */ + + 2 /* heartbeat length */ + @@ -1489,11 +1499,11 @@ dtls1_process_heartbeat(SSL *s) - r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding); + r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length); s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT, +++ b/ssl/t1_lib.c @@ -2588,16 +2588,20 @@ tls1_process_heartbeat(SSL *s) s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, + return 0; /* silently discard per RFC 6520 sec. 4 */ $ grep -A 12 "Random" debian/patches/CVE-2014-0160.patch /* Random padding */ RAND_pseudo_bytes(bp, padding); - r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding); + r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length); if (r >= 0 && s->msg_callback) s->msg_callback(1, s->version, TLS1_RT_HEARTBEAT, - buffer, 3 + payload + padding, + buffer, write_length, s, s->msg_callback_arg); OPENSSL_free(buffer); ■テストサイトがあって、該当する脆弱性を利用して「YELLOW SUBMARINE」を 書き込めるかどうかを確認出来る。 あるプロセスに限定しているとはいえ、 予測可能であることを確認したのであれば、 例え書き込まなくてもメモリ上のSSL証明書の秘密鍵が 読まれると困ること位は容易に想像出来る。 また、システムのログにも見当たらない。(操作ログは出る) http://filippo.io/Heartbleed/ ([]uint8) { 00000000 02 00 79 68 65 61 72 74 62 6c 65 65 64 2e 66 69 |..yheartbleed.fi| 00000010 6c 69 70 70 6f 2e 69 6f 59 45 4c 4c 4f 57 20 53 |lippo.ioYELLOW S| 00000020 55 42 4d 41 52 49 4e 45 39 c2 b9 0e 5e c3 b6 62 |UBMARINE9...^..b| 00000030 bc 6d fa a6 59 6b 56 9a f2 5c 4b b9 a1 7b 55 77 |.m..YkV..\K..{Uw| 00000040 8b e4 bf 24 11 17 d0 58 ac 08 22 ee db 5a 56 68 |...$...X.."..ZVh| 00000050 bd a9 07 d6 67 88 7f d9 4a c1 06 d3 87 9b c5 23 |....g...J......#| 00000060 90 d3 e7 b0 38 ce ac b4 05 a1 09 d5 20 52 4b 54 |....8....... RKT| 00000070 59 6a 17 4d 24 34 64 30 6a db 4f d9 08 df 39 01 |Yj.M$4d0j.O...9.| 00000080 50 a5 18 8e d9 4c 7e 4f 79 6a 86 3b |P....L~Oyj.;| }
$ sudo find /var/log -type f -exec grep -i "heartbeart\|libssl" {} \; | awk -F\; '{print $(NF-1)}' COMMAND=/usr/bin/find /var/log -type f -exec grep -i "heartbeart\|libssl" {} ■上記の理由から、SSLサーバ証明書の再発行と再設定を行った方が良いので、 「要検証の上~」の但し書きがあるのだと思う。 その他、影響範囲の説明は下記で。 CVE-2014-0160 OpenSSL Heartbleed 脆弱性まとめ http://d.hatena.ne.jp/nekoruri/20140408 OpenSSL 1.0.1に含まれる脆弱性への対応のお願い https://jp.globalsign.com/information/important/detail.php?no=1396947073 CVE-2014-0160 の OpenSSL の脆弱性対応 http://blog.n-z.jp/blog/2014-04-08-cve-2014-0160.html ■目安として、以下のパッチで再起動チェックを行うサービスに関係のあるプロセスは チェックしておく。 $ tar zxvf openssl_1.0.1e-2+deb7u5.debian.tar.gz debian/libssl1.0.0.postinst debian/libssl1.0.0.postinst $ grep check debian/libssl1.0.0.postinst | grep -v "dpkg\|for " check="sendmail openssh-server" check="$check apache2-common ssh-nonfree exim4" check="$check apache-ssl libapache-mod-ssl openvpn spamassassin" check="$check courier-imap-ssl courier-mta-ssl courier-pop-ssl" check="$check postfix cyrus21-imapd cyrus21-pop3d" check="$check postgresql-7.4 postgresql-8.0 postgresql-8.1" check="$check postgresql-8.2" check="$check racoon dovecot-common bind9" check="$check ntp openntpd clamcour nagios-nrpe-server" check="$check clamav-freshclam clamav-daemon" check="$check fetchmail ftpd-ssl slapd" check="$check proftpd proftpd-ldap proftpd-mysql proftpd-pgsql" check="$check partimage-server conserver-server tor" check="$check stunnel4" check=$(echo $check | sed 's/apache2-common/apache2/g') check=$(echo $check | sed 's/libapache-mod-ssl/apache/g') check=$(echo $check | sed 's/proftpd-.*/proftpd/g') check=$(echo $check | sed 's/dovecot-common/dovecot/g') check=$(echo $check | sed 's/openssh-server/ssh/g') ■openssh-serverが影響無しとされているのは、鍵の生成にlibsslを使っていないからだと思う。 $ sudo ldd /usr/bin/ssh-keygen linux-vdso.so.1 => (0x00007ffff05ff000) libcrypto.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007fc6cd58c000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc6cd388000) libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007fc6cd171000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc6ccde6000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fc6ccbcf000) /lib64/ld-linux-x86-64.so.2 (0x00007fc6cdbd3000) ■念の為、checkrestartが使えるようにしてアップデート。 以下に見る通り、ssh/postfix/python2.7の再起動が必要とある。 $ sudo apt-get install -y debian-goodies $ sudo checkrestart Found 0 processes using old versions of upgraded files $ sudo apt-get upgrade -y $ sudo checkrestart Found 7 processes using old versions of upgraded files (7 distinct programs) (4 distinct packages) Of these, 2 seem to contain init scripts which can be used to restart them: The following packages seem to have init scripts that could be used to restart them: openssh-server: 3629 /usr/sbin/sshd postfix: 4390 /usr/lib/postfix/qmgr 6645 /usr/lib/postfix/pickup 4369 /usr/lib/postfix/master These are the init scripts: service ssh restart service postfix restart These processes do not seem to have an associated init script to restart them: python2.7-minimal: 3606 /usr/bin/python2.7 openssh-client: 4564 /usr/bin/ssh-agent ■どうしてもシステムを再起動出来ないならば。。。 $ sudo /etc/init.d/ssh restart $ sudo /etc/init.d/postfix restart $ sudo checkrestart Found 2 processes using old versions of upgraded files (2 distinct programs) (1 distinct packages) These processes do not seem to have an associated init script to restart them: python2.7-minimal: 3606 /usr/bin/python2.7 $ sudo ps aux | grep python | sed s/".*[0-9]\:[0-9]* "//g /usr/bin/python /usr/bin/fail2ban-server -b -s /var/run/fail2ban/fail2ban.sock grep python $ sudo /etc/init.d/fail2ban restart $ sudo checkrestart Found 1 processes using old versions of upgraded files (1 distinct program) (0 distinct packages) No packages seem to need to be restarted. (please read checkrestart(1)) ■出来れば、システムの再起動をお勧めします。 $ sudo shutdown -r now && exit