[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]