openssl: libcrypto: stack-based buffer overflow in ERR_error_string_n (err.c)

Description:
openSSL is an open source project that provides a robust, commercial-grade, and full-featured toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols.

A fuzz of nginx, discovered a stack overflow that resides in libcrypto.

After looked into it with an nginx developer (Sergey Kandaurov), he said:

This is caused by OpenSSL disfunction in ERR_error_string_n() which happens
when the function is used with zero len argument and the string is not null
terminated. In nginx that’s possible when the string had been previously
truncated for some reason.

From ERR_error_string_n documentation:

void ERR_error_string_n(unsigned long e, char *buf, size_t len);

ERR_error_string_n() is a variant of ERR_error_string() that writes at
most len characters (including the terminating 0) and truncates the
string if necessary.

The problem is that ERR_error_string_n() doesn’t cope with zero len parameter.
It uses len-capped BIO_snprintf() to write error string safely, then it checks
buffer truncation for some useless things using strlen() in unsafe manner.
This is where the buffer is overread.

I don’t know if the bug is reachable in another way, but Matt Caswell from OpenSSL does not judge it as a security issue.

The complete ASan output:

# nginx -t -p "" -c $FILE
==24306==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe6cc74f50 at pc 0x00000046f20c bp 0x7ffe6cc749c0 sp 0x7ffe6cc74170
READ of size 7 at 0x7ffe6cc74f50 thread T0
    #0 0x46f20b in strlen /var/tmp/portage/sys-devel/llvm-3.8.1-r2/work/llvm-3.8.1.src/projects/compiler-rt/lib/asan/asan_interceptors.cc:581
    #1 0x7fa541c4a5b4 in ERR_error_string_n /tmp/portage/dev-libs/openssl-1.0.2j/work/openssl-1.0.2j-abi_x86_64.amd64/crypto/err/err.c:888
    #2 0x57e70e in ngx_ssl_error /tmp/portage/www-servers/nginx-1.10.1/work/nginx-1.10.1/src/event/ngx_event_openssl.c:2061:9
    #3 0x57f253 in ngx_ssl_certificate /tmp/portage/www-servers/nginx-1.10.1/work/nginx-1.10.1/src/event/ngx_event_openssl.c:333:9
    #4 0x6791c8 in ngx_http_ssl_merge_srv_conf /tmp/portage/www-servers/nginx-1.10.1/work/nginx-1.10.1/src/http/modules/ngx_http_ssl_module.c:669:9
    #5 0x592f66 in ngx_http_merge_servers /tmp/portage/www-servers/nginx-1.10.1/work/nginx-1.10.1/src/http/ngx_http.c:582:18
    #6 0x592f66 in ngx_http_block /tmp/portage/www-servers/nginx-1.10.1/work/nginx-1.10.1/src/http/ngx_http.c:268
    #7 0x53b264 in ngx_conf_handler /tmp/portage/www-servers/nginx-1.10.1/work/nginx-1.10.1/src/core/ngx_conf_file.c:427:18
    #8 0x53b264 in ngx_conf_parse /tmp/portage/www-servers/nginx-1.10.1/work/nginx-1.10.1/src/core/ngx_conf_file.c:283
    #9 0x533b2a in ngx_init_cycle /tmp/portage/www-servers/nginx-1.10.1/work/nginx-1.10.1/src/core/ngx_cycle.c:274:9
    #10 0x4ff1cc in main /tmp/portage/www-servers/nginx-1.10.1/work/nginx-1.10.1/src/core/nginx.c:276:13
    #11 0x7fa540a6761f in __libc_start_main /var/tmp/portage/sys-libs/glibc-2.22-r4/work/glibc-2.22/csu/libc-start.c:289
    #12 0x425b18 in _start (/usr/sbin/nginx+0x425b18)

Address 0x7ffe6cc74f50 is located in stack of thread T0 at offset 1136 in frame
    #0 0x57e53f in ngx_ssl_error /tmp/portage/www-servers/nginx-1.10.1/work/nginx-1.10.1/src/event/ngx_event_openssl.c:2031

  This frame has 4 object(s):
    [32, 36) 'flags'
    [48, 72) 'args'
    [112, 1136) 'errstr' 0x10004d9869e0: 00 00 00 00 00 00 00 00 00 00[f2]f2 f2 f2 f2 f2
  0x10004d9869f0: f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 00 f3 f3 f3 f3 f3
  0x10004d986a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10004d986a10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10004d986a20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10004d986a30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==24306==ABORTING

Affected version:
1.0.2j and 1.1.0b

Fixed version:
1.1.0c and 1.0.2k (not yet released)

Commit fix:
https://github.com/openssl/openssl/commit/e5c1361580d8de79682958b04a5f0d262e680f8b

Credit:
This bug was discovered by Agostino Sarubbo of Gentoo.

Timeline:
2016-10-11: bug discovered
2016-10-12: bug reported to upstream
2016-10-14: blog post about the issue

Note:
This bug was found with American Fuzzy Lop.

Permalink:

openssl: libcrypto: stack-based buffer overflow in ERR_error_string_n (err.c)

This entry was posted in advisories, security. Bookmark the permalink.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.