summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-09 14:06:50 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-09 14:06:50 +0000
commit1433d4337cdfa6422d75e83ef63b8f64fc95bf6b (patch)
tree27c33a27c966c8c66727795ee272de9ad5578145
parent842d5cff6a9debcd10398ee1e95b85268620a290 (diff)
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 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_3@59800 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog13
-rw-r--r--ext/openssl/ossl_asn1.c13
-rw-r--r--test/openssl/test_asn1.rb23
-rw-r--r--version.h2
4 files changed, 43 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 6f52c2d098..fb4ba3c204 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Sat Sep 9 23:05:31 2017 Kazuki Yamaguchi <k@rhe.jp>
+
+ 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@ruby-lang.org>
* ext/json: bump to version 1.8.3.1. [Backport #13853]
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index 89da5949b8..444440125c 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -870,19 +870,18 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
{
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, long length, long *offset, int depth,
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 {
diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb
index fd2118d808..109fd95fd4 100644
--- a/test/openssl/test_asn1.rb
+++ b/test/openssl/test_asn1.rb
@@ -596,6 +596,29 @@ rEzBQ0F9dUyqQ9gyRg8KHhDfv9HzT1d/rnUZMkoombwYBRIUChGCYV0GnJcan2Zm
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)
diff --git a/version.h b/version.h
index 949ea42fd0..f67d12fb44 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
#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