Your message dated Mon, 27 Apr 2015 13:29:01 -0300 with message-id <20150427162901.GA18490@debian.org> and subject line Re: Bug#782775: unblock: ruby2.1/2.1.5-3 has caused the Debian Bug report #782775, regarding pu: package ruby2/2.1.5-3 to be marked as done. This means that you claim that the problem has been dealt with. If this is not the case it is now your responsibility to reopen the Bug report if necessary, and/or fix the problem forthwith. (NB: If you are a system administrator and have no idea what this message is talking about, this may indicate a serious mail system misconfiguration somewhere. Please contact owner@bugs.debian.org immediately.) -- 782775: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=782775 Debian Bug Tracking System Contact owner@bugs.debian.org with problems
--- Begin Message ---
- To: Debian Bug Tracking System <submit@bugs.debian.org>
- Subject: unblock: ruby2.1/2.1.5-3
- From: Antonio Terceiro <terceiro@debian.org>
- Date: Fri, 17 Apr 2015 13:56:25 -0300
- Message-id: <[🔎] 20150417165625.GA31171@debian.org>
Package: release.debian.org Severity: normal User: release.debian.org@packages.debian.org Usertags: unblock Please unblock package ruby2.1 2.1.5-3 containts the fix for the recently announced CVE-2015-1855: Ruby OpenSSL Hostname Verification https://www.ruby-lang.org/en/news/2015/04/13/ruby-openssl-hostname-matching-vulnerability/ Follows the diff from the git repository wrt the version in testing. The actual debdiff will contain a diff-in-a-diff and will be less convenient to read. unblock ruby2.1/2.1.5-3 -- System Information: Debian Release: 8.0 APT prefers buildd-unstable APT policy: (500, 'buildd-unstable'), (500, 'unstable'), (500, 'testing'), (1, 'experimental') Architecture: amd64 (x86_64) Kernel: Linux 3.16.0-4-amd64 (SMP w/4 CPU cores) Locale: LANG=pt_BR.UTF-8, LC_CTYPE=pt_BR.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) -- Antonio Terceiro <terceiro@debian.org>diff --git a/debian/changelog b/debian/changelog index eb1753e..d8eac2e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +ruby2.1 (2.1.5-3) unstable; urgency=high + + * Fix vulnerabiity with overly permissive matching of hostnames in OpenSSL + extension [CVE-2015-1855] + - applied revision 50296 of upstream svn repository. + + -- Antonio Terceiro <terceiro@debian.org> Fri, 17 Apr 2015 09:26:57 -0300 + ruby2.1 (2.1.5-2) unstable; urgency=medium * Fix Segmentation fault after pack & ioctl & unpack (Closes: #781504) diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb index 43025e7..b91dce3 100644 --- a/ext/openssl/lib/openssl/ssl.rb +++ b/ext/openssl/lib/openssl/ssl.rb @@ -143,8 +143,7 @@ module OpenSSL case san.tag when 2 # dNSName in GeneralName (RFC5280) should_verify_common_name = false - reg = Regexp.escape(san.value).gsub(/\\\*/, "[^.]+") - return true if /\A#{reg}\z/i =~ hostname + return true if verify_hostname(hostname, san.value) when 7 # iPAddress in GeneralName (RFC5280) should_verify_common_name = false # follows GENERAL_NAME_print() in x509v3/v3_alt.c @@ -159,8 +158,7 @@ module OpenSSL if should_verify_common_name cert.subject.to_a.each{|oid, value| if oid == "CN" - reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+") - return true if /\A#{reg}\z/i =~ hostname + return true if verify_hostname(hostname, value) end } end @@ -168,11 +166,67 @@ module OpenSSL end module_function :verify_certificate_identity + def verify_hostname(hostname, san) # :nodoc: + # RFC 5280, IA5String is limited to the set of ASCII characters + return false unless san.ascii_only? + return false unless hostname.ascii_only? + + # See RFC 6125, section 6.4.1 + # Matching is case-insensitive. + san_parts = san.downcase.split(".") + + # TODO: this behavior should probably be more strict + return san == hostname if san_parts.size < 2 + + # Matching is case-insensitive. + host_parts = hostname.downcase.split(".") + + # RFC 6125, section 6.4.3, subitem 2. + # If the wildcard character is the only character of the left-most + # label in the presented identifier, the client SHOULD NOT compare + # against anything but the left-most label of the reference + # identifier (e.g., *.example.com would match foo.example.com but + # not bar.foo.example.com or example.com). + return false unless san_parts.size == host_parts.size + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in + # which the wildcard character comprises a label other than the + # left-most label (e.g., do not match bar.*.example.net). + return false unless verify_wildcard(host_parts.shift, san_parts.shift) + + san_parts.join(".") == host_parts.join(".") + end + module_function :verify_hostname + + def verify_wildcard(domain_component, san_component) # :nodoc: + parts = san_component.split("*", -1) + + return false if parts.size > 2 + return san_component == domain_component if parts.size == 1 + + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + return false if domain_component.start_with?("xn--") && san_component != "*" + + parts[0].length + parts[1].length < domain_component.length && + domain_component.start_with?(parts[0]) && + domain_component.end_with?(parts[1]) + end + module_function :verify_wildcard + class SSLSocket include Buffering include SocketForwarder include Nonblock + ## + # Perform hostname verification after an SSL connection is established + # + # This method MUST be called after calling #connect to ensure that the + # hostname of a remote peer has been verified. def post_connection_check(hostname) unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname) raise SSLError, "hostname \"#{hostname}\" does not match the server certificate" diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb index b743819..68a2543 100644 --- a/test/openssl/test_ssl.rb +++ b/test/openssl/test_ssl.rb @@ -359,6 +359,156 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase end end + def test_verify_hostname + assert_equal(true, OpenSSL::SSL.verify_hostname("www.example.com", "*.example.com")) + assert_equal(false, OpenSSL::SSL.verify_hostname("www.subdomain.example.com", "*.example.com")) + end + + def test_verify_wildcard + assert_equal(false, OpenSSL::SSL.verify_wildcard("foo", "x*")) + assert_equal(true, OpenSSL::SSL.verify_wildcard("foo", "foo")) + assert_equal(true, OpenSSL::SSL.verify_wildcard("foo", "f*")) + assert_equal(true, OpenSSL::SSL.verify_wildcard("foo", "*")) + assert_equal(false, OpenSSL::SSL.verify_wildcard("abc*bcd", "abcd")) + assert_equal(false, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "x*")) + assert_equal(false, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "*--qdk4b9b")) + assert_equal(true, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "xn--qdk4b9b")) + end + + # Comments in this test is excerpted from http://tools.ietf.org/html/rfc6125#page-27 + def test_post_connection_check_wildcard_san + # case-insensitive ASCII comparison + # RFC 6125, section 6.4.1 + # + # "..matching of the reference identifier against the presented identifier + # is performed by comparing the set of domain name labels using a + # case-insensitive ASCII comparison, as clarified by [DNS-CASE] (e.g., + # "WWW.Example.Com" would be lower-cased to "www.example.com" for + # comparison purposes) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:*.example.com'), 'www.example.com')) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:*.Example.COM'), 'www.example.com')) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:*.example.com'), 'WWW.Example.COM')) + # 1. The client SHOULD NOT attempt to match a presented identifier in + # which the wildcard character comprises a label other than the + # left-most label (e.g., do not match bar.*.example.net). + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:www.*.com'), 'www.example.com')) + # 2. If the wildcard character is the only character of the left-most + # label in the presented identifier, the client SHOULD NOT compare + # against anything but the left-most label of the reference + # identifier (e.g., *.example.com would match foo.example.com but + # not bar.foo.example.com or example.com). + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:*.example.com'), 'foo.example.com')) + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:*.example.com'), 'bar.foo.example.com')) + # 3. The client MAY match a presented identifier in which the wildcard + # character is not the only character of the label (e.g., + # baz*.example.net and *baz.example.net and b*z.example.net would + # be taken to match baz1.example.net and foobaz.example.net and + # buzz.example.net, respectively). ... + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:baz*.example.com'), 'baz1.example.com')) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:*baz.example.com'), 'foobaz.example.com')) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:b*z.example.com'), 'buzz.example.com')) + # Section 6.4.3 of RFC6125 states that client should NOT match identifier + # where wildcard is other than left-most label. + # + # Also implicitly mentions the wildcard character only in singular form, + # and discourages matching against more than one wildcard. + # + # See RFC 6125, section 7.2, subitem 2. + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:*b*.example.com'), 'abc.example.com')) + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:*b*.example.com'), 'ab.example.com')) + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:*b*.example.com'), 'bc.example.com')) + # ... However, the client SHOULD NOT + # attempt to match a presented identifier where the wildcard + # character is embedded within an A-label or U-label [IDNA-DEFS] of + # an internationalized domain name [IDNA-PROTO]. + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:xn*.example.com'), 'xn1ca.example.com')) + # part of A-label + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:xn--*.example.com'), 'xn--1ca.example.com')) + # part of U-label + # dNSName in RFC5280 is an IA5String so U-label should NOT be allowed + # regardless of wildcard. + # + # See Section 7.2 of RFC 5280: + # IA5String is limited to the set of ASCII characters. + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_san('DNS:á*.example.com'), 'á1.example.com')) + end + + def test_post_connection_check_wildcard_cn + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('*.example.com'), 'www.example.com')) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('*.Example.COM'), 'www.example.com')) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('*.example.com'), 'WWW.Example.COM')) + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('www.*.com'), 'www.example.com')) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('*.example.com'), 'foo.example.com')) + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('*.example.com'), 'bar.foo.example.com')) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('baz*.example.com'), 'baz1.example.com')) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('*baz.example.com'), 'foobaz.example.com')) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('b*z.example.com'), 'buzz.example.com')) + # Section 6.4.3 of RFC6125 states that client should NOT match identifier + # where wildcard is other than left-most label. + # + # Also implicitly mentions the wildcard character only in singular form, + # and discourages matching against more than one wildcard. + # + # See RFC 6125, section 7.2, subitem 2. + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('*b*.example.com'), 'abc.example.com')) + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('*b*.example.com'), 'ab.example.com')) + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('*b*.example.com'), 'bc.example.com')) + assert_equal(true, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('xn*.example.com'), 'xn1ca.example.com')) + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('xn--*.example.com'), 'xn--1ca.example.com')) + # part of U-label + # Subject in RFC5280 states case-insensitive ASCII comparison. + # + # See Section 7.2 of RFC 5280: + # IA5String is limited to the set of ASCII characters. + assert_equal(false, OpenSSL::SSL.verify_certificate_identity( + create_cert_with_name('á*.example.com'), 'á1.example.com')) + end + + def create_cert_with_san(san) + ef = OpenSSL::X509::ExtensionFactory.new + cert = OpenSSL::X509::Certificate.new + cert.subject = OpenSSL::X509::Name.parse("/DC=some/DC=site/CN=Some Site") + ext = ef.create_ext('subjectAltName', san) + cert.add_extension(ext) + cert + end + + def create_cert_with_name(name) + cert = OpenSSL::X509::Certificate.new + cert.subject = OpenSSL::X509::Name.new([['DC', 'some'], ['DC', 'site'], ['CN', name]]) + cert + end + + # Create NULL byte SAN certificate def create_null_byte_SAN_certificate(critical = false) ef = OpenSSL::X509::ExtensionFactory.newAttachment: signature.asc
Description: Digital signature
--- End Message ---
--- Begin Message ---
- To: Jonathan Wiltshire <jmw@debian.org>
- Cc: 782775-done@bugs.debian.org
- Subject: Re: Bug#782775: unblock: ruby2.1/2.1.5-3
- From: Antonio Terceiro <terceiro@debian.org>
- Date: Mon, 27 Apr 2015 13:29:01 -0300
- Message-id: <20150427162901.GA18490@debian.org>
- In-reply-to: <[🔎] 20150423210026.GC22595@lupin.home.powdarrmonkey.net>
- References: <[🔎] 20150417165625.GA31171@debian.org> <[🔎] 20150423210026.GC22595@lupin.home.powdarrmonkey.net>
Hi, On Thu, Apr 23, 2015 at 10:00:26PM +0100, Jonathan Wiltshire wrote: > Control: retitle -1 pu: package ruby2/2.1.5-3 > Control: tag -1 jessie moreinfo > > On Fri, Apr 17, 2015 at 01:56:25PM -0300, Antonio Terceiro wrote: > > 2.1.5-3 containts the fix for the recently announced CVE-2015-1855: Ruby > > OpenSSL Hostname Verification > > https://www.ruby-lang.org/en/news/2015/04/13/ruby-openssl-hostname-matching-vulnerability/ > > Deferring to 8.1; please check with the security team if they want this for > a DSA, otherwise we'll ask for an upload to proposed-updates after the > release. There will be a DSA, so closing this bug. -- Antonio Terceiro <terceiro@debian.org>Attachment: signature.asc
Description: Digital signature
--- End Message ---