yaml / libyaml

Canonical source repository for LibYAML
http://pyyaml.org/wiki/LibYAML
MIT License
951 stars 316 forks source link

heap-buffer-overflow in yaml_emitter_emit_flow_mapping_key function of emitter.c:810:27 #268

Closed HotSpurzzZ closed 4 months ago

HotSpurzzZ commented 1 year ago

When using libfuzzer to fuzz the dumper, a heap overflow was found, this can reproduce on the lattest commit. When trying to dereference a pointer: (*(--(stack).top)), , the status of the stack is not checked, resulting in an overflow.

Version

git log
commit f8f760f7387d2cc56a2fc7b1be313a3bf3f7f58c (HEAD -> master, origin/master, origin/HEAD)
Author: Tina Müller (tinita) <cpan2@tinita.de>
Date:   Wed Nov 10 18:03:02 2021 +0100

POC file

https://github.com/HotSpurzzZ/testcases/blob/main/libyaml/libyaml_heap_overflow

Verification steps

Compile and run the following file https://github.com/google/oss-fuzz/blob/master/projects/libyaml/libyaml_dumper_fuzzer.c clang -g -fsanitize=address,fuzzer -O0 -I ./src/ -Iinclude -c libyaml_dumper_fuzzer.c -o dumper_fuzzer.o clang++ -g -fsanitize=address,fuzzer -O0 dumper_fuzzer.o -o dumper_fuzzer src/.libs/libyaml.a

AddressSanitizer output


./dumper_fuzzer ./libyaml_heap_overflow                                                                                                                                                           =================================================================
==3430052==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6060000001fc at pc 0x00000057c637 bp 0x7fffffffd030 sp 0x7fffffffd028
READ of size 4 at 0x6060000001fc thread T0                                                                 
    #0 0x57c636 in yaml_emitter_emit_flow_mapping_key /home/libyaml_issue/libyaml/src/emitter.c:810:27
    #1 0x57a43b in yaml_emitter_state_machine /home/libyaml_issue/libyaml/src/emitter.c:453:20
    #2 0x579790 in yaml_emitter_emit /home/libyaml_issue/libyaml/src/emitter.c:291:14      
    #3 0x566877 in yaml_emitter_close /home/libyaml_issue/libyaml/src/dumper.c:98:10
    #4 0x553671 in LLVMFuzzerTestOneInput /home/libyaml_issue/libyaml/dumper_fuzzer.c:268:3
    #5 0x4586a1 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/libyaml_issue/libyaml/dumper_fuzzer+0x4586a1)
    #6 0x443e12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/home/libyaml_issue/libyaml/dumper_fuzzer+0x443e12)
    #7 0x4498c6 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/libyaml_issue/libyaml/dumper_fuzzer+0x4498c6)
    #8 0x472582 in main (/home/libyaml_issue/libyaml/dumper_fuzzer+0x472582)
    #9 0x7ffff7a6f082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
    #10 0x41e4dd in _start (/home/libyaml_issue/libyaml/dumper_fuzzer+0x41e4dd)

0x6060000001fc is located 4 bytes to the left of 64-byte region [0x606000000200,0x606000000240)
allocated by thread T0 here:
    #0 0x51e20d in malloc (/home/libyaml_issue/libyaml/dumper_fuzzer+0x51e20d)
    #1 0x553ef9 in yaml_malloc /home/libyaml_issue/libyaml/src/api.c:33:12
    #2 0x557132 in yaml_emitter_initialize /home/libyaml_issue/libyaml/src/api.c:368:10
    #3 0x553353 in LLVMFuzzerTestOneInput /home/libyaml_issue/libyaml/dumper_fuzzer.c:226:8
    #4 0x4586a1 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/libyaml_issue/libyaml/dumper_fuzzer+0x4586a1)
    #5 0x443e12 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/home/libyaml_issue/libyaml/dumper_fuzzer+0x443e12)
    #6 0x4498c6 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/libyaml_issue/libyaml/dumper_fuzzer+0x4498c6)
    #7 0x472582 in main (/home/libyaml_issue/libyaml/dumper_fuzzer+0x472582)
    #8 0x7ffff7a6f082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/libyaml_issue/libyaml/src/emitter.c:810:27 in yaml_emitter_emit_flow_mapping_key
Shadow bytes around the buggy address:
  0x0c0c7fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c0c7fff8000: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa
  0x0c0c7fff8010: 00 00 00 00 00 00 02 fa fa fa fa fa fd fd fd fd
  0x0c0c7fff8020: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd
=>0x0c0c7fff8030: fa fa fa fa 00 00 00 00 00 00 00 00 fa fa fa[fa]
  0x0c0c7fff8040: 00 00 00 00 00 00 00 00 fa fa fa fa fd fd fd fd
  0x0c0c7fff8050: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd
  0x0c0c7fff8060: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
  0x0c0c7fff8070: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
  0x0c0c7fff8080: fd fd fd fd fa fa fa fa 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
==3430052==ABORTING```
perlpunk commented 5 months ago

I assume this is the same as #258 I couldn't find an input file to reproduce in this issue.

perlpunk commented 4 months ago

Closing as a duplicate of #258 and caused by a problem in the fuzztesting code, fixed here: https://github.com/google/oss-fuzz/pull/11818