ruby-changes:47684
From: usa <ko1@a...>
Date: Sat, 9 Sep 2017 23:06:56 +0900 (JST)
Subject: [ruby-changes:47684] usa:r59800 (ruby_2_3): asn1: fix out-of-bounds read in decoding constructed objects
usa 2017-09-09 23:06:50 +0900 (Sat, 09 Sep 2017) New Revision: 59800 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=59800 Log: asn1: fix out-of-bounds read in decoding constructed objects * OpenSSL::ASN1.{decode,decode_all,traverse}: have a bug of out-of-bounds read. int_ossl_asn1_decode0_cons() does not give the correct available length to ossl_asn1_decode() when decoding the inner components of a constructed object. This can cause out-of-bounds read if a crafted input given. Reference: https://hackerone.com/reports/170316 https://github.com/ruby/openssl/commit/1648afef33c1d97fb203c82291b8a61269e85d3b Modified files: branches/ruby_2_3/ChangeLog branches/ruby_2_3/ext/openssl/ossl_asn1.c branches/ruby_2_3/test/openssl/test_asn1.rb branches/ruby_2_3/version.h Index: ruby_2_3/version.h =================================================================== --- ruby_2_3/version.h (revision 59799) +++ ruby_2_3/version.h (revision 59800) @@ -1,6 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_3/version.h#L1 #define RUBY_VERSION "2.3.5" #define RUBY_RELEASE_DATE "2017-09-09" -#define RUBY_PATCHLEVEL 368 +#define RUBY_PATCHLEVEL 369 #define RUBY_RELEASE_YEAR 2017 #define RUBY_RELEASE_MONTH 9 Index: ruby_2_3/test/openssl/test_asn1.rb =================================================================== --- ruby_2_3/test/openssl/test_asn1.rb (revision 59799) +++ ruby_2_3/test/openssl/test_asn1.rb (revision 59800) @@ -596,6 +596,29 @@ rEzBQ0F9dUyqQ9gyRg8KHhDfv9HzT1d/rnUZMkoo https://github.com/ruby/ruby/blob/trunk/ruby_2_3/test/openssl/test_asn1.rb#L596 assert_equal(false, asn1.value[3].infinite_length) end + def test_decode_constructed_overread + test = %w{ 31 06 31 02 30 02 05 00 } + # ^ <- invalid + raw = [test.join].pack("H*") + ret = [] + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1.traverse(raw) { |x| ret << x } + } + assert_equal 2, ret.size + assert_equal 17, ret[0][6] + assert_equal 17, ret[1][6] + + test = %w{ 31 80 30 03 00 00 } + # ^ <- invalid + raw = [test.join].pack("H*") + ret = [] + assert_raise(OpenSSL::ASN1::ASN1Error) { + OpenSSL::ASN1.traverse(raw) { |x| ret << x } + } + assert_equal 1, ret.size + assert_equal 17, ret[0][6] + end + private def assert_universal(tag, asn1) Index: ruby_2_3/ext/openssl/ossl_asn1.c =================================================================== --- ruby_2_3/ext/openssl/ossl_asn1.c (revision 59799) +++ ruby_2_3/ext/openssl/ossl_asn1.c (revision 59800) @@ -870,19 +870,18 @@ int_ossl_asn1_decode0_cons(unsigned char https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_asn1.c#L870 { VALUE value, asn1data, ary; int infinite; - long off = *offset; + long available_len, off = *offset; infinite = (j == 0x21); ary = rb_ary_new(); - while (length > 0 || infinite) { + available_len = infinite ? max_len : length; + while (available_len > 0) { long inner_read = 0; - value = ossl_asn1_decode0(pp, max_len, &off, depth + 1, yield, &inner_read); + value = ossl_asn1_decode0(pp, available_len, &off, depth + 1, yield, &inner_read); *num_read += inner_read; - max_len -= inner_read; + available_len -= inner_read; rb_ary_push(ary, value); - if (length > 0) - length -= inner_read; if (infinite && NUM2INT(ossl_asn1_get_tag(value)) == V_ASN1_EOC && @@ -973,7 +972,7 @@ ossl_asn1_decode0(unsigned char **pp, lo https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ext/openssl/ossl_asn1.c#L972 if(j & V_ASN1_CONSTRUCTED) { *pp += hlen; off += hlen; - asn1data = int_ossl_asn1_decode0_cons(pp, length, len, &off, depth, yield, j, tag, tag_class, &inner_read); + asn1data = int_ossl_asn1_decode0_cons(pp, length - hlen, len, &off, depth, yield, j, tag, tag_class, &inner_read); inner_read += hlen; } else { Index: ruby_2_3/ChangeLog =================================================================== --- ruby_2_3/ChangeLog (revision 59799) +++ ruby_2_3/ChangeLog (revision 59800) @@ -1,3 +1,16 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_3/ChangeLog#L1 +Sat Sep 9 23:05:31 2017 Kazuki Yamaguchi <k@r...> + + asn1: fix out-of-bounds read in decoding constructed objects + + * OpenSSL::ASN1.{decode,decode_all,traverse}: have a bug of + out-of-bounds read. int_ossl_asn1_decode0_cons() does not give the + correct available length to ossl_asn1_decode() when decoding the + inner components of a constructed object. This can cause + out-of-bounds read if a crafted input given. + + Reference: https://hackerone.com/reports/170316 + https://github.com/ruby/openssl/commit/1648afef33c1d97fb203c82291b8a61269e85d3b + Sat Sep 9 22:57:24 2017 SHIBATA Hiroshi <hsbt@r...> * ext/json: bump to version 1.8.3.1. [Backport #13853] -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/