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

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/sass/libsass/issues/2661
## Description:
Issue: sass/libsass#2661
Title: AddressSanitizer: heap-buffer-overflow (OOB read) in Sass::Prelexer::skip_over_scopes (libsass/src/prelexer.hpp:69:14)
State: closed
Created by: glen-mac
Created at: 2018-06-03 01:41:59+00:00
Labels: Bug - Confirmed, Dev - PR Ready, Back port to 3.4 stable, Fuzzy

Issue Body:
Hey there, I have discovered a single byte out-of-bands read (OOB) in libsass at: [prelexer.hpp:69:14](https://github.com/sass/libsass/blob/60f839158eff1f1bb84cb44f0f0c4bce3ed86a6d/src/prelexer.hpp#L69)

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

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

System information:
```
$ uname -a
Linux s127422 3.13.0-137-generic #186-Ubuntu SMP Mon Dec 4 19:09:19 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
```

This bug was found to be in libsass releases from [3.2.0](https://github.com/sass/libsass/tree/3.2.0) until the commit listed above.

You can find a collection of PoC files that trigger the bug [here](https://github.com/sass/libsass/files/2065550/prelexer_pocs.zip).

The full ASAN report is shown below:
```
↳ sassc/bin/sassc < crash.file
=================================================================
==12294==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60700000dffc at pc 0x000000804138 bp 0x7ffd55ba7d20 sp 0x7ffd55ba7d18
READ of size 1 at 0x60700000dffc thread T0
    #0 0x804137 in char const* Sass::Prelexer::skip_over_scopes<&(char const* Sass::Prelexer::exactly<&Sass::Constants::hash_lbrace>(char const*)), &(char const* Sass::Prelexer::exactly<&Sass::Constants::rbrace>(char const*))>(char const*, char const*) /home/glenn/temp/findsass/libsass/prelexer.hpp:68:14
    #1 0x78ca33 in char const* Sass::Parser::peek<&Sass::Prelexer::interpolant>(char const*) /home/glenn/temp/findsass/libsass/parser.hpp:114:14
    #2 0x78ca33 in Sass::Parser::lookahead_for_selector(char const*) /home/glenn/temp/findsass/libsass/parser.cpp:2025
    #3 0x76c877 in Sass::Parser::parse() /home/glenn/temp/findsass/libsass/parser.cpp:152:36
    #4 0x5271a0 in Sass::Context::parse_file() /home/glenn/temp/findsass/libsass/context.cpp:323:20
    #5 0x52b276 in Sass::Context::parse_string() /home/glenn/temp/findsass/libsass/context.cpp:363:14
    #6 0x4fbfad in sass_parse_block(Sass_Compiler*) /home/glenn/temp/findsass/libsass/sass_context.cpp:505:16
    #7 0x4fbfad in sass_compiler_parse /home/glenn/temp/findsass/libsass/sass_context.cpp:652
    #8 0x4fae24 in sass_compile_context(Sass_Context*, Sass::Context::Data) /home/glenn/temp/findsass/libsass/sass_context.cpp:536:7
    #9 0x4faa3c in sass_compile_data_context /home/glenn/temp/findsass/libsass/sass_context.cpp:623:12
    #10 0x4effcf in compile_stdin /home/glenn/temp/findsass/sassc/sassc.c:86:5
    #11 0x4f132f in main /home/glenn/temp/findsass/sassc/sassc.c:282:18
    #12 0x7f5eddf8e82f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291
    #13 0x41e4a8 in _start (/home/glenn/temp/findsass/sassc/bin/sassc+0x41e4a8)

0x60700000dffc is located 0 bytes to the right of 76-byte region [0x60700000dfb0,0x60700000dffc)
allocated by thread T0 here:
    #0 0x4be958 in realloc (/home/glenn/temp/findsass/sassc/bin/sassc+0x4be958)
    #1 0x4efed2 in compile_stdin /home/glenn/temp/findsass/sassc/sassc.c:68:25
    #2 0x4f132f in main /home/glenn/temp/findsass/sassc/sassc.c:282:18
    #3 0x7f5eddf8e82f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/glenn/temp/findsass/libsass/prelexer.hpp:68:14 in char const* Sass::Prelexer::skip_over_scopes<&(char const* Sass::Prelexer::exactly<&Sass::Constants::hash_lbrace>(char const*)), &(char const* Sass::Prelexer::exactly<&Sass::Constants::rbrace>(char const*))>(char const*, char const*)
Shadow bytes around the buggy address:
  0x0c0e7fff9ba0: fa fa 00 00 00 00 00 00 00 00 00 fa fa fa fa fa
  0x0c0e7fff9bb0: 00 00 00 00 00 00 00 00 00 fa fa fa fa fa 00 00
  0x0c0e7fff9bc0: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
  0x0c0e7fff9bd0: 00 00 00 00 00 fa fa fa fa fa 00 00 00 00 00 00
  0x0c0e7fff9be0: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 00
=>0x0c0e7fff9bf0: 00 fa fa fa fa fa 00 00 00 00 00 00 00 00 00[04]
  0x0c0e7fff9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0e7fff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0e7fff9c20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0e7fff9c30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c0e7fff9c40: 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
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  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
==12294==ABORTING
```


Comments:
Comment by xzyfer on 2018-06-21 11:22:51+00:00:
Thanks @glen-mac .
I've confirmed the issue with test_s102.txt.
A fix has been provided in #2676.

---

Comment by xi on 2019-06-05 05:33:03+00:00:
Assigned CVE-2018-11693

Attachments:
https://github.com/sass/libsass/files/2065550/prelexer_pocs.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 1e52b74306b7d73a617396c912ca436dc55fd4d8
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;
}