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

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/sass/libsass/issues/3177
## Description:
Issue: sass/libsass#3177
Title: A stack-overflow src/ast_selectors.cpp:557 in Sass::CompoundSelector::has_real_parent_ref() const
State: closed
Created by: ex7l0it
Created at: 2022-10-16 02:22:39+00:00
Labels: Dev - PR Ready

Issue Body:

### **1. Description**

A stack-overflow has occurred in `Sass::CompoundSelector::has_real_parent_ref()` of `src/ast_selectors.cpp:557` when running program `./sassc/bin/sassc`, this can reproduce on the lattest commit.

### **2.  Software version info**

```shell
$ git log -1
commit 2102188d21d2b7577c2b3edb12832e90786a2831 (HEAD -> master, origin/master, origin/HEAD)
Merge: 006bbf5c f0605a31
Author: Marcel Greter <doyouspam@ocbnet.ch>
Date:   Fri Sep 9 20:41:03 2022 +0200

    Merge pull request #3176 from LilyWangLL/vcpkg-instructions
    
    Add vcpkg installation instructions
```

```shell
$ ./sassc/bin/sassc --version
sassc: 3.6.2
libsass: 3.6.5-8-g210218
sass2scss: 1.1.1
sass: 3.5
```

### **3. System  version info**

```shell
Ubuntu 20.04.2 LTS
Linux 5.4.0-65-generic
```

### **4. Command**

```shell
./sassc/bin/sassc ./poc2
```

### **5. Result**

```shell
AddressSanitizer:DEADLYSIGNAL
=================================================================
==3151197==ERROR: AddressSanitizer: stack-overflow on address 0x7ffe016a7ff8 (pc 0x000000b9c0f5 bp 0x0c1a00000ab2 sp 0x7ffe016a8000 T0)
    #0 0xb9c0f4 in Sass::CompoundSelector::has_real_parent_ref() const src/ast_selectors.cpp:557
    #1 0xb92ed5 in Sass::ComplexSelector::has_real_parent_ref() const src/ast_selectors.cpp:474
    #2 0xb92ed5 in Sass::SelectorList::has_real_parent_ref() const src/ast_selectors.cpp:365
    #3 0xb929f8 in Sass::PseudoSelector::has_real_parent_ref() const src/ast_selectors.cpp:337
    #4 0xb9c217 in Sass::CompoundSelector::has_real_parent_ref() const src/ast_selectors.cpp:564
    #5 0xb92ed5 in Sass::ComplexSelector::has_real_parent_ref() const src/ast_selectors.cpp:474
    #6 0xb92ed5 in Sass::SelectorList::has_real_parent_ref() const src/ast_selectors.cpp:365
    #7 0xb929f8 in Sass::PseudoSelector::has_real_parent_ref() const src/ast_selectors.cpp:337
    #8 0xb9c217 in Sass::CompoundSelector::has_real_parent_ref() const src/ast_selectors.cpp:564
    #9 0xb92ed5 in Sass::ComplexSelector::has_real_parent_ref() const src/ast_selectors.cpp:474
    #10 0xb92ed5 in Sass::SelectorList::has_real_parent_ref() const src/ast_selectors.cpp:365
    #11 0xb929f8 in Sass::PseudoSelector::has_real_parent_ref() const src/ast_selectors.cpp:337
    #12 0xb9c217 in Sass::CompoundSelector::has_real_parent_ref() const src/ast_selectors.cpp:564
    ...
    #323 0xb929f8 in Sass::PseudoSelector::has_real_parent_ref() const src/ast_selectors.cpp:337
    #324 0xb9c217 in Sass::CompoundSelector::has_real_parent_ref() const src/ast_selectors.cpp:564
    #325 0xb92ed5 in Sass::ComplexSelector::has_real_parent_ref() const src/ast_selectors.cpp:474
    #326 0xb92ed5 in Sass::SelectorList::has_real_parent_ref() const src/ast_selectors.cpp:365
    #327 0xb929f8 in Sass::PseudoSelector::has_real_parent_ref() const src/ast_selectors.cpp:337
    #328 0xb9c217 in Sass::CompoundSelector::has_real_parent_ref() const src/ast_selectors.cpp:564
    #329 0xb92ed5 in Sass::ComplexSelector::has_real_parent_ref() const src/ast_selectors.cpp:474
    #330 0xb92ed5 in Sass::SelectorList::has_real_parent_ref() const src/ast_selectors.cpp:365
    #331 0xb929f8 in Sass::PseudoSelector::has_real_parent_ref() const src/ast_selectors.cpp:337

SUMMARY: AddressSanitizer: stack-overflow src/ast_selectors.cpp:557 in Sass::CompoundSelector::has_real_parent_ref() const
==3151197==ABORTING
```

### **6. Impact**

This vulnerability is capable of crashing software, Bypass Protection Mechanism, Modify Memory, and possible remote execution.

### **7. POC**

Download: [poc2](https://drive.google.com/file/d/1aC5q3czen0atI91fuBIoCBFkS30_OSWX/)


**Report of the Information Security Laboratory of Ocean University of China @OUC_ISLOUC @OUC_Blue_Whale** 



Comments:
Comment by AMoo-Miki on 2023-08-31 16:10:08+00:00:
Since this is now a [CVE](https://nvd.nist.gov/vuln/detail/CVE-2022-43358), is there any chance to have it addressed?

---

Comment by bradleyd on 2023-10-20 16:15:29+00:00:
Any ETA on patch?

---

Comment by risicle on 2023-10-29 14:28:54+00:00:
I'm not too optimistic given that the readme states that libsass is now deprecated. Similar story I guess for #3178 & #3174 which are very similar bugs.

---

Comment by jubalh on 2023-12-13 17:50:08+00:00:
I was looking into fixing this issue but since both the code is new to me and I don't know too much about sass it is not so easy :)

The above provided backtrace isn't much helpful either since it only shows the recursive calling of `has_real_parent_ref()`.

When running the POC, which is `+{:not(&){_:(&)}_:0}`, I see:
```
#0  0x00007ffff7c73ba0 in Sass::ComplexSelector::has_real_parent_ref() const@plt () from /lib64/libsass-3.6.5.so.1
#1  0x00007ffff7d5f33a in Sass::Parser::parseComplexSelector(bool) () from /lib64/libsass-3.6.5.so.1
#2  0x00007ffff7d5f957 in Sass::Parser::parseSelectorList(bool) () from /lib64/libsass-3.6.5.so.1
#3  0x00007ffff7d36213 in Sass::Parser::parse_ruleset(Lookahead) () from /lib64/libsass-3.6.5.so.1
#4  0x00007ffff7d2f81e in Sass::Parser::parse_block_node(bool) () from /lib64/libsass-3.6.5.so.1
#5  0x00007ffff7d30215 in Sass::Parser::parse_block_nodes(bool) () from /lib64/libsass-3.6.5.so.1
#6  0x00007ffff7d30807 in Sass::Parser::parse() () from /lib64/libsass-3.6.5.so.1
#7  0x00007ffff7ceebe1 in Sass::Context::register_resource(Sass::Include const&, Sass::Resource const&) () from /lib64/libsass-3.6.5.so.1
```

So I looked into the mentioned functions, specifically `parse_ruleset()` and `parseSelectorList()` but knowing so little about the code it is hard to find the cause.

> I'm not too optimistic given that the readme states that libsass is now deprecated.

The readme also states `While it will continue to receive maintenance releases indefinitely, there are no plans to add additional features or compatibility with any new CSS or Sass features`.
I believe CVEs fall into the maintenance category :)

@mgreter @xzyfer : Does one of you maybe have some spare time to help us figure this out? That would be great! 🙏

---

Comment by mgreter on 2023-12-15 02:43:27+00:00:
I may have a fix at https://github.com/mgreter/libsass/tree/bugfix/x-mas-2023 (please test it), but that may be the last fix I will do for LibSass. As I never was part or had any say in the development of Sass, and also no longer working in fronted, this is merely a bugfix out of good will. You will need to move to dart sass, as that is the future, as the people involved in Sass put it.
PR: https://github.com/sass/libsass/pull/3184

---

Comment by mgreter on 2023-12-15 03:52:15+00:00:
Addressed via https://github.com/sass/libsass/pull/3184

---

Comment by jubalh on 2023-12-15 09:36:37+00:00:
Thanks a lot @mgreter !
I ran your PR against all three POCs and all of them are fixed.

Commit References:
2102188d21d2b7577c2b3edb12832e90786a2831

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 4da7c4bd13b8e9e5cd034f358dceda0bbba917d2
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;
}