Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8-byte Out of Bounds Write onto the Heap #196

Closed
WhatTheFuzz opened this issue Jan 24, 2023 · 9 comments
Closed

8-byte Out of Bounds Write onto the Heap #196

WhatTheFuzz opened this issue Jan 24, 2023 · 9 comments

Comments

@WhatTheFuzz
Copy link

Found a small faulting test case for pcre2test that causes a segmentation fault on some architectures (x86). It looks like the fault is in process_data. The logic for filling ovector may be off by one. Specifically, the offending line is

for (j = 0; j < 2*oveccount; j++) ovector[j] = JUNK_OFFSET;

in the file:line pcre2test.c:7634

# Show compiler and arch. 
$ clang --version
Ubuntu clang version 14.0.0-1ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

# Compile with ASAN to show the bug on amd64 platforms. On x86 (-m32), it crashes.
$ CC=clang CFLAGS="-fsanitize=address -Og -ggdb" LD_FLAGS="-fsanitize=address" ./autogen.sh
$ CC=clang CFLAGS="-fsanitize=address -Og -ggdb" LD_FLAGS="-fsanitize=address" ./configure
$ CC=clang CFLAGS="-fsanitize=address -Og -ggdb" LD_FLAGS="-fsanitize=address" make

# Show exploitation mitigations.
$ checksec .libs/pcre2test 
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled
    ASAN:     Enabled
    UBSAN:    Enabled
    
$  .libs/pcre2test  ./80271ad5c66883facd8415181d5c632ff297b23a45a70760d831d2d8cd4a6ddd /dev/null
=================================================================
==134099==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x612000000180 at pc 0x5619337c3587 bp 0x7ffcc068faf0 sp 0x7ffcc068fae8
WRITE of size 8 at 0x612000000180 thread T0
    #0 0x5619337c3586 in process_data pcre2/src/pcre2test.c:7634:48
    #1 0x5619337b7ec7 in main pcre2/src/pcre2test.c:9441:12
    #2 0x7f548e8e1d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #3 0x7f548e8e1e3f in __libc_start_main csu/../csu/libc-start.c:392:3
    #4 0x5619336f7854 in _start (pcre2/.libs/pcre2test+0x3a854) (BuildId: 65d14eea5ad79438d33864f76304278584ff1b06)

0x612000000180 is located 0 bytes to the right of 320-byte region [0x612000000040,0x612000000180)
allocated by thread T0 here:
    #0 0x56193377a69e in __interceptor_malloc (pcre2/.libs/pcre2test+0xbd69e) (BuildId: 65d14eea5ad79438d33864f76304278584ff1b06)
    #1 0x5619337bc2eb in my_malloc pcre2/src/pcre2test.c:2794:15

SUMMARY: AddressSanitizer: heap-buffer-overflow pcre2/src/pcre2test.c:7634:48 in process_data
Shadow bytes around the buggy address:
  0x0c247fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c247fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c247fff8000: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c247fff8010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c247fff8020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c247fff8030:[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c247fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c247fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c247fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c247fff8070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c247fff8080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  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

==134099==ABORTING

I've attached the faulting test case below. Can anyone confirm they get the same result? Low security implications due to mitigations and the size of the overwrite on the heap.

80271ad5c66883facd8415181d5c632ff297b23a45a70760d831d2d8cd4a6ddd.txt

@PhilipHazel
Copy link
Collaborator

I got a different error when I tried this, but of course it could just be a different manifestation of the same thing. I will post when I've fixed it.

@PhilipHazel
Copy link
Collaborator

I cannot reproduce this. When I tried your test, it showed up a different error in pcre2test when a string repeat [something]{count} had a ridiculously large count. I have fixed this in HEAD - I now get a clean "realloc() failed" error message from your test, with or without ASAN. I've looked at the code related to the line in pcre2test that you quote, but cannot spot any problem. This is all on Arch Linux. Please can you post the output from pcre2test. That will show which input line is causing your issue.

@carenas
Copy link
Contributor

carenas commented Jan 25, 2023

I think ASAN is either a red herring or another bug.

The fix is incomplete though, as HEAD is still crashing in Linux x86, because the underlying problem is an integer overflow in the multiplication to get needlen and that is fixed in the following branch

@PhilipHazel
Copy link
Collaborator

Hmm. I do not get a crash - oh, possibly because this is a 64-bit system. Are you talking about 32-bit? I'm not hugely worried about his because pcre2test is, after all, just a test program. We could just put an upper limit on the repetition count.

@WhatTheFuzz
Copy link
Author

I believe @carenas is correct and the ASAN is either another issue or red herring. I should have compared the backtraces for both x86 and amd64. When compiled with -m32, the backtrace is different from ASAN issue above.

$ git clean -xfd
$ git log --oneline| head -n 1
303e3bc make sure to use either size_t or PCRE2_SIZE correctly (#195)

$ CC=clang CFLAGS="-m32 -fno-omit-frame-pointer -fno-inline-functions -Og -ggdb -Wl,-rpath=$(pwd)/.libs" LDFLAGS="-m32 -Wl,-rpath=$(pwd)/.libs" ./autogen.sh
$ CC=clang CFLAGS="-m32 -fno-omit-frame-pointer -fno-inline-functions -Og -ggdb -Wl,-rpath=$(pwd)/.libs" LDFLAGS="-m32 -Wl,-rpath=$(pwd)/.libs" ./configure
$ CC=clang CFLAGS="-m32 -fno-omit-frame-pointer -fno-inline-functions -Og -ggdb -Wl,-rpath=$(pwd)/.libs" LDFLAGS="-m32 -Wl,-rpath=$(pwd)/.libs" make -j4

$ checksec .libs/pcre2test
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled

$ ./pcre2test ./80271ad5c66883facd8415181d5c632ff297b23a45a70760d831d2d8cd4a6ddd.txt 
PCRE2 version 10.43-DEV 2023-01-15
!\SP�]\�
�P:�PP|P@|��P|P@|a�!
\���d��ɵ����]\�
No match
�P:�P`|PZ|a�!
 0: a\xff
\���d�������
No match
�[dQ[\�]{1666666666666}
No match
�[d\[\�]{1}\���d��ɵ���d]\�
No match
�P:�PT|P@|a�!
 0: P@
\���d�������
No match
�[d\[y�]{1666666666}
[1]    197356 segmentation fault (core dumped)  LD_LIBRARY_PATH="$(pwd)" ./pcre2test

The backtrace:

#0  __memcpy_sse2_unaligned () at ../sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S:656
#1  0x5655c075 in process_data () at src/pcre2test.c:6916
#2  0x56559db9 in main (argc=<optimized out>, argv=0xffffd074) at src/pcre2test.c:9441
#3  0xf7d2f519 in __libc_start_call_main (main=main@entry=0x56558da0 <main>, argc=argc@entry=2, argv=argv@entry=0xffffd074) at ../sysdeps/nptl/libc_start_call_main.h:58
#4  0xf7d2f5f3 in __libc_start_main_impl (main=0x56558da0 <main>, argc=2, argv=0xffffd074, init=0x0, fini=0x0, rtld_fini=0xf7fcaaa0 <_dl_fini>, stack_end=0xffffd06c) at ../csu/libc-start.c:392
#5  0x565587eb in _start ()

Which points to an issues with pcretest.c: 6916 with the following:

memcpy(CAST8VAR(q), start_rep, replen);

I tried out the patch made by @carenas and confirmed the segmentation fault no longer exists on x86.

$ gh pr checkout 198
$ git log --oneline| head -n 1
e44ca41 add a C23 inspired checked integer multiplication helper

< Same autogen/configure/make as before >

$ ./pcre2test ./80271ad5c66883facd8415181d5c632ff297b23a45a70760d831d2d8cd4a6ddd.txt
PCRE2 version 10.43-DEV 2023-01-15
!\SP�]\�
�P:�PP|P@|��P|P@|a�!
\���d��ɵ����]\�
No match
�P:�P`|PZ|a�!
 0: a\xff
\���d�������
No match
�[dQ[\�]{1666666666666}
No match
�[d\[\�]{1}\���d��ɵ���d]\�
No match
�P:�PT|P@|a�!
 0: P@
\���d�������
No match
�[d\[y�]{1666666666}
** Expanded content too large
�[d\[\�]{1} 6}\H�6!** Unrecognized escape sequence "\H"

@carenas
Copy link
Contributor

carenas commented Jan 25, 2023

the backtrace is different from ASAN issue above

so, could you reproduce the ASAN issue? and if so, can you validate it has an stacktrace than matches what was originally reported even after applying the current fixes?

@WhatTheFuzz
Copy link
Author

I recompiled with ASAN for x86 and amd64 and the issue seems to be resolved. Without further triaging, ASAN must have just picked up the issue at a different point in time.

$ git log --oneline| head -n 1
e44ca41 add a C23 inspired checked integer multiplication helper

$ checksec .libs/pcre2test
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled
    ASAN:     Enabled
    UBSAN:    Enabled

$ .libs/pcre2test ./80271ad5c66883facd8415181d5c632ff297b23a45a70760d831d2d8cd4a6ddd.txt 
PCRE2 version 10.43-DEV 2023-01-15
!\SP�]\�
�P:�PP|P@|��P|P@|a�!
\���d��ɵ����]\�
No match
�P:�P`|PZ|a�!
 0: a\xff
\���d�������
No match
�[dQ[\�]{1666666666666}
No match
�[d\[\�]{1}\���d��ɵ���d]\�
No match
�P:�PT|P@|a�!
 0: P@
\���d�������
No match
�[d\[y�]{1666666666}
** Expanded content too large
�[d\[\�]{1} 6}\H�6!** Unrecognized escape sequence "\H"

$ checksec .libs/pcre2test 
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled
    ASAN:     Enabled
    UBSAN:    Enabled

$ .libs/pcre2test ./80271ad5c66883facd8415181d5c632ff297b23a45a70760d831d2d8cd4a6ddd.txt   
PCRE2 version 10.43-DEV 2023-01-15
!\SP�]\�
�P:�PP|P@|��P|P@|a�!
\���d��ɵ����]\�
No match
�P:�P`|PZ|a�!
 0: a\xff
\���d�������
No match
�[dQ[\�]{1666666666666}
No match
�[d\[\�]{1}\���d��ɵ���d]\�
No match
�P:�PT|P@|a�!
 0: P@
\���d�������
No match
�[d\[y�]{1666666666}
No match
�[d\[\�]{1} 6}\H�6!** Unrecognized escape sequence "\H"

@carenas
Copy link
Contributor

carenas commented Jan 25, 2023

could you close this issue then?

@WhatTheFuzz
Copy link
Author

Resolved with PR #198.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants