Stream: wamr

Topic: Buffer Overflow Example


view this post on Zulip Lasse (Jun 22 2024 at 19:04):

Hi, I tried to reproduce the buffer overlow as shown in Everything Old is New Again: Binary Security of WebAssembly Fig. 5 a).

While doing that I ran in two different problems.

Firstly, when looking at the stack the number of characters put into the function vulnerable doesn't correspond to the characters copied.

When putting a string with 5 characters into the function everything seems to work as supposed.
5xC.png

With 12
12xC.png
or 16 characters it seems off.
16xC.png
Also, there will never be more then 12 bytes copied.

void vulnerable(char *input) {
    char same_frame[8] = "BBBBBBBB"; // 8x B
    char buffer[8];
    save_stack("first");
    strcpy(buffer, input);
    save_stack("second");
    printf("buffer: %s\n", buffer);
    printf("same_frame: %s\n", same_frame);
}

void parent() {
    char parent_frame[8] = "AAAAAAAA"; // 8x A
    vulnerable("CCCCCCCCCCCC"); // 12x C
    printf("parent_frame: %s\n", parent_frame);
}

excerpt from save_stack:

    uint32 *bottom = (uint32 *) exec_env->wasm_stack.bottom;
    uint32 *top  = (uint32 *)exec_env->wasm_stack.top;
    printf("Printing:\tBottom %p\tTop %p\n", (size_t *) bottom, (size_t *) top);

    for (uint32* i = bottom; i <  top; i++) {
        fprintf(file, "%p\t\t%08x\n", i, *i);
    }

And secondly, when executing the same example without the save_stack function with 12 characters in vulnerable I get the following output:

buffer: CCCCCCCCCCCC
same_frame: CCCC
parent_frame: AAAAAAA

and with 16 characters.

buffer: CCCCCCCCBBBBBBB
same_frame: BBBBBBB
parent_frame: AAAAAAA

Even though same_frame should just be even more overwritten?!

Does sombody know why these two things occur or has a working Buffer Overflow Example?

view this post on Zulip Wenyong Huang (Jun 25 2024 at 08:46):

@Lasse Krähner Did you find any buffer overflow issue in WAMR? I tried to compile and run the source code with wasi-sdk, but the compiler reported undefined reference error for save_stack, and if I removed calling this function, it generated wasm file successfully and iwasm output the same result with wasmtime, I think it is as expected.

For why it outputs like the above, I think it is somewhat related to wasm spec and the compiler, for example, some data is put in the wasm function's params and locals (like same_frame pointer, buffer pointer), some data is put in the linear memory (like "AAAAAAAAAA", "BBBBBBBB") and some is put in a shadow stack which resides in the linear memory (like struct parameter, and maybe 8 bytes of char buffer[8], not very sure). So maybe you need to look into the details to understand more.

view this post on Zulip Lasse (Jun 26 2024 at 09:44):

@Wenyong Huang Thank you for your answer. I didn't find any new buffer overflows issues, yet.
Do you have further literature on how putting data in linear memory is working exactly and the shadow Stack?

view this post on Zulip Wenyong Huang (Jul 01 2024 at 04:07):

Lasse Krähner said:

Wenyong Huang Thank you for your answer. I didn't find any new buffer overflows issues, yet.
Do you have further literature on how putting data in linear memory is working exactly and the shadow Stack?

Maybe you can refer to:
https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/memory_tune.md
https://bytecodealliance.github.io/wamr.dev/blog/understand-the-wamr-heaps/

And output more details on the compiled wasm, e.g.
(1) Add more flags for wasi-sdk or clang when cimpiling C to wasm, for example:
-Wl,--emit-relocs -Wl,--export=__heap_base -Wl,--export=__data_end -Wl,--export=__stack_pointer
Note that the global __stack_pointer is the stack pointer of the shadow stack.

(2) Dump details of wasm file with wabt objdump:
wasm-objdump -s -x -r -d xxx.wasm > xxx.log

WebAssembly Micro Runtime (WAMR). Contribute to bytecodealliance/wasm-micro-runtime development by creating an account on GitHub.
Linear memory # The linear memory is a contiguous, mutable array of raw bytes. For most compilers, e.g. wasi-sdk, emsdk, rustc or asc, normally it includes three parts, data area, auxiliary stack area and heap area. The initial and maximum sizes of linear memory can be configured through the compilation parameters: For wasi-sdk, the initial/max size can be specified with -Wl,–initial-memory=n1,–max-memory=n2 For emsdk, the initial/max size can be specified with -s INITIAL_MEMORY=n1 -s MAXIMUM_MEMORY=n2 -s ALLOW_MEMORY_GROWTH=1 or -s TOTAL_MEMORY=n For asc, they can be specified with –initialMemory and –maximumMemory flags

Last updated: Dec 23 2024 at 12:05 UTC