Project: libsass (sass/libsass), language: c++
Vulnerability instance: libsass.cve-2018-11499
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/sass/libsass/issues/2643
## Description:
Issue: sass/libsass#2643
Title: AddressSanitizer: heap-use-after-free in libsass
State: closed
Created by: glen-mac
Created at: 2018-05-02 00:22:46+00:00
Labels: Bug - Confirmed, Bug - Selectors, selector-validation, Fuzzy

Issue Body:
Hey there, I have discovered a use after free vulnerability in libsass.

Found when fuzzing commit 60f839158eff1f1bb84cb44f0f0c4bce3ed86a6d of libsass, using commit [aa6d5c6](https://github.com/sass/sassc/commit/aa6d5c635ea8faf44d542a23aaf85d27e5777d48) of sassc as a harness.

After testing all releases, it is evident this was introduced in release 3.4.7 of libsass.

Compile flags to reproduce: 
`CC=clang CXX=clang++ CFLAGS='-fsanitize=address -g -O2 -fno-omit-frame-pointer' CXXFLAGS=$CFLAGS make -C sassc -j8`

You can find the case file [here](https://github.com/sass/libsass/files/1965545/case.zip).

ASAN report is as follows:
```
==31334==ERROR: AddressSanitizer: heap-use-after-free on address 0x604000005050 at pc 0x0000005acd0e bp 0x7ffccd9a6550 sp 0x7ffccd9a6548
READ of size 1 at 0x604000005050 thread T0
    #0 0x5acd0d in Sass::handle_error(Sass_Context*) /home/ubuntu/fuzz_proj/libsass/src/sass_context.cpp:79:28
    #1 0x5a0d42 in Sass::handle_errors(Sass_Context*) /home/ubuntu/fuzz_proj/libsass/src/sass_context.cpp:211:18
    #2 0x5a0d42 in Sass::sass_parse_block(Sass_Compiler*) /home/ubuntu/fuzz_proj/libsass/src/sass_context.cpp:257
    #3 0x5a0d42 in sass_compiler_parse /home/ubuntu/fuzz_proj/libsass/src/sass_context.cpp:487
    #4 0x59e9a1 in sass_compile_context(Sass_Context*, Sass::Context*) /home/ubuntu/fuzz_proj/libsass/src/sass_context.cpp:375:7
    #5 0x59e5a7 in sass_compile_data_context /home/ubuntu/fuzz_proj/libsass/src/sass_context.cpp:460:12
    #6 0x58d1e7 in compile_stdin /home/ubuntu/fuzz_proj/sassc/sassc.c:138:5
    #7 0x58e369 in main /home/ubuntu/fuzz_proj/sassc/sassc.c:375:18
    #8 0x7ff874ba782f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291
    #9 0x49aed8 in _start (/home/vagrant/shared/sassc+0x49aed8)

0x604000005050 is located 0 bytes inside of 34-byte region [0x604000005050,0x604000005072)
freed by thread T0 here:
    #0 0x5533a0 in __interceptor_cfree.localalias.0 (/home/vagrant/shared/sassc+0x5533a0)
    #1 0x6af62a in __gnu_cxx::new_allocator<char>::deallocate(char*, unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/ext/new_allocator.h:110:9
    #2 0x6af62a in std::allocator_traits<std::allocator<char> >::deallocate(std::allocator<char>&, char*, unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/alloc_traits.h:517
    #3 0x6af62a in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_destroy(unsigned long) /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/basic_string.h:185
    #4 0x6af62a in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_dispose() /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/basic_string.h:180
    #5 0x6af62a in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/bits/basic_string.h:543
    #6 0x6af62a in Sass::Functions::selector_nest(Sass::Environment<Sass::SharedImpl<Sass::AST_Node> >&, Sass::Environment<Sass::SharedImpl<Sass::AST_Node> >&, Sass::Context&, char const*, Sass::ParserState, Sass::Backtrace*, std::vector<Sass::SharedImpl<Sass::Selector_List>, std::allocator<Sass::SharedImpl<Sass::Selector_List> > >) /home/ubuntu/fuzz_proj/libsass/src/functions.cpp:1982
    #7 0x8fa3e9 in Sass::Eval::operator()(Sass::Function_Call*) /home/ubuntu/fuzz_proj/libsass/src/eval.cpp:1030:18
    #8 0x8d1cb1 in Sass::Eval::operator()(Sass::Binary_Expression*) /home/ubuntu/fuzz_proj/libsass/src/eval.cpp:727:16
    #9 0x8cbe87 in Sass::Eval::operator()(Sass::List*) /home/ubuntu/fuzz_proj/libsass/src/eval.cpp:503:27
    #10 0x8c7df4 in Sass::Eval::operator()(Sass::Debug*) /home/ubuntu/fuzz_proj/libsass/src/eval.cpp:425:42
    #11 0x9416a9 in Sass::Expand::operator()(Sass::Debug*) /home/ubuntu/fuzz_proj/libsass/src/expand.cpp:388:8
    #12 0x92fc6d in Sass::Expand::operator()(Sass::Block*) /home/ubuntu/fuzz_proj/libsass/src/expand.cpp:81:11
    #13 0x600444 in Sass::Context::compile() /home/ubuntu/fuzz_proj/libsass/src/context.cpp:659:12
    #14 0x5fe9a1 in Sass::Data_Context::parse() /home/ubuntu/fuzz_proj/libsass/src/context.cpp:630:12
    #15 0x59fc78 in Sass::sass_parse_block(Sass_Compiler*) /home/ubuntu/fuzz_proj/libsass/src/sass_context.cpp:238:31
    #16 0x59fc78 in sass_compiler_parse /home/ubuntu/fuzz_proj/libsass/src/sass_context.cpp:487
    #17 0x59e9a1 in sass_compile_context(Sass_Context*, Sass::Context*) /home/ubuntu/fuzz_proj/libsass/src/sass_context.cpp:375:7
    #18 0x58e369 in main /home/ubuntu/fuzz_proj/sassc/sassc.c:375:18
    #19 0x7ff874ba782f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291

previously allocated by thread T0 here:
    #0 0x553558 in __interceptor_malloc (/home/vagrant/shared/sassc+0x553558)
    #1 0x7ff875619e77 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x8de77)
    #2 0xbc6723 in Sass::AST_Node::to_string[abi:cxx11](Sass_Inspect_Options) const /home/ubuntu/fuzz_proj/libsass/src/ast.cpp:2067:14
    #3 0x6ad914 in Sass::Functions::selector_nest(Sass::Environment<Sass::SharedImpl<Sass::AST_Node> >&, Sass::Environment<Sass::SharedImpl<Sass::AST_Node> >&, Sass::Context&, char const*, Sass::ParserState, Sass::Backtrace*, std::vector<Sass::SharedImpl<Sass::Selector_List>, std::allocator<Sass::SharedImpl<Sass::Selector_List> > >) /home/ubuntu/fuzz_proj/libsass/src/functions.cpp:1979:36
    #4 0x8fa3e9 in Sass::Eval::operator()(Sass::Function_Call*) /home/ubuntu/fuzz_proj/libsass/src/eval.cpp:1030:18
    #5 0x8d1cb1 in Sass::Eval::operator()(Sass::Binary_Expression*) /home/ubuntu/fuzz_proj/libsass/src/eval.cpp:727:16
    #6 0x8cbe87 in Sass::Eval::operator()(Sass::List*) /home/ubuntu/fuzz_proj/libsass/src/eval.cpp:503:27
    #7 0x8c7df4 in Sass::Eval::operator()(Sass::Debug*) /home/ubuntu/fuzz_proj/libsass/src/eval.cpp:425:42
    #8 0x9416a9 in Sass::Expand::operator()(Sass::Debug*) /home/ubuntu/fuzz_proj/libsass/src/expand.cpp:388:8
    #9 0x92fc6d in Sass::Expand::operator()(Sass::Block*) /home/ubuntu/fuzz_proj/libsass/src/expand.cpp:81:11
    #10 0x600444 in Sass::Context::compile() /home/ubuntu/fuzz_proj/libsass/src/context.cpp:659:12
    #11 0x5fe9a1 in Sass::Data_Context::parse() /home/ubuntu/fuzz_proj/libsass/src/context.cpp:630:12
    #12 0x59fc78 in Sass::sass_parse_block(Sass_Compiler*) /home/ubuntu/fuzz_proj/libsass/src/sass_context.cpp:238:31
    #13 0x59fc78 in sass_compiler_parse /home/ubuntu/fuzz_proj/libsass/src/sass_context.cpp:487
    #14 0x59e9a1 in sass_compile_context(Sass_Context*, Sass::Context*) /home/ubuntu/fuzz_proj/libsass/src/sass_context.cpp:375:7
    #15 0x58e369 in main /home/ubuntu/fuzz_proj/sassc/sassc.c:375:18
    #16 0x7ff874ba782f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291

SUMMARY: AddressSanitizer: heap-use-after-free /home/ubuntu/fuzz_proj/libsass/src/sass_context.cpp:79:28 in Sass::handle_error(Sass_Context*)
Shadow bytes around the buggy address:
  0x0c087fff89b0: fa fa 00 00 00 00 02 fa fa fa fd fd fd fd fd fd
  0x0c087fff89c0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
  0x0c087fff89d0: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fa
  0x0c087fff89e0: fa fa fd fd fd fd fd fa fa fa 00 00 00 00 00 00
  0x0c087fff89f0: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fd
=>0x0c087fff8a00: fa fa fd fd fd fd fd fa fa fa[fd]fd fd fd fd fa
  0x0c087fff8a10: fa fa 00 00 00 00 00 01 fa fa fd fd fd fd fd fd
  0x0c087fff8a20: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fd
  0x0c087fff8a30: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fd
  0x0c087fff8a40: fa fa fd fd fd fd fd fd fa fa fd fd fd fd fd fd
  0x0c087fff8a50: 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
==31334==ABORTING
```


Comments:
Comment by carnil on 2018-05-27 08:46:28+00:00:
This issue was assigned [CVE-2018-11499](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11499)

---

Comment by xzyfer on 2018-05-27 11:01:47+00:00:
Thanks for the report. I'm on vacation. I'll take a look when I'm back.

On Sun., 27 May 2018, 10:46 am carnil, <notifications@github.com> wrote:

> This issue was assigned CVE-2018-11499
> <https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-11499>
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/sass/libsass/issues/2643#issuecomment-392315565>, or mute
> the thread
> <https://github.com/notifications/unsubscribe-auth/AAjZWMaSnz6qhhUgzw76FHVKJ5-4l1FTks5t2mfmgaJpZM4TurzO>
> .
>


---

Comment by xzyfer on 2018-07-04 11:06:16+00:00:
Thanks for the report. 
We confirmed this issue shares a common root cause to other reported issues.
We have assigned the `selector-validation` to the affected issues.

---

Comment by VictorRodriguez on 2018-07-19 14:04:51+00:00:
@xzyfer thanks a lot for the great support, do you have the patch of the common root cause issue?


---

Comment by VictorRodriguez on 2018-08-20 13:23:29+00:00:
Hi, I was trying to fix the issue and find out that the heap-use-after-free  points to the line: 
https://github.com/sass/libsass/blob/master/src/sass_context.cpp#L79
is that correct? if so where is the free before assigning const char* line_end = line_beg ?

Attachments:
https://github.com/sass/libsass/files/1965545/case.zip

Commit References:
60f839158eff1f1bb84cb44f0f0c4bce3ed86a6d
aa6d5c635ea8faf44d542a23aaf85d27e5777d48

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
export BUILD='static'
make -j$(nproc)

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool
RUN git clone https://github.com/sass/libsass libsass
RUN git -C libsass checkout 5b92405db76df2acf620fbaf37e3d1c3662af720
WORKDIR $SRC/libsass
COPY build.sh $SRC/

Additional files:
filename: data_context_fuzzer.cc
content: #include "sass.h"

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  char* sass_data = (char*) malloc(sizeof(char) * size + 1);
  if (sass_data == NULL) return 0;

  memcpy(sass_data, data, size);
  sass_data[size] = '\0';

  struct Sass_Data_Context* ctx = sass_make_data_context(sass_data);
  if (ctx == NULL) {
    free(sass_data);
    return 0;
  }

  struct Sass_Options* options = sass_make_options();
  if (options == NULL) {
    sass_delete_data_context(ctx);
    return 0;
  }

  sass_option_set_output_style(options, SASS_STYLE_NESTED);
  sass_option_set_precision(options, 5);

  sass_data_context_set_options(ctx, options);
  sass_compile_data_context(ctx);

  sass_delete_data_context(ctx);
  sass_delete_options(options);

  return 0;
}