Overview :
In Argo versions prior to v1.5.0-rc1, it was possible for authenticated Argo users to submit API calls to retrieve secrets and other manifests which were stored within git.

The Argo Project is an open source provider of Kubernetes CI/CD workflows, facilitating Infrastructure as Code.

I Identified five security issues in Argo: one sensitive information disclosure vulnerability and four vulnerabilities in the admin authentication system. The severity of each is dependent on how Argo is configured in your environment. The manifest disclosure and user enumeration vulnerabilities have been fixed as of v1.5.1, however the other three issues have not been remediated and require mitigation.

tl;dr: Update to v1.5.1, use SSO with Argo, and disable the admin account. Read on for more information about the vulnerabilities.

 

Sensitive Information Disclosure – CVE-2018-21034

Kubernetes Secret objects contain sensitive information, such as API keys, and should not be accessible to unprivileged users. Secret manifests should not be stored in git.

In Argo versions prior to v1.5.0-rc1, it was possible for authenticated Argo users to submit API calls to retrieve secrets and other manifests which were stored within git.

While I don’t personally consider this a severe vulnerability, as storing Secret objects in git is a bigger issue, the Argo maintainers considered this a severe issue and published an (untagged) fix within thirty minutes!

To remediate this issue, update to v1.5.0, released on April 1, 2020.

Note about CVE date: MITRE decided to assign a 2018 year for this CVE because of this issue from 2018 (at least, I think.)

From MITRE, after I questioned the year:
“https://github.com/argoproj/argo-cd/issues/470 does not spell out an
attack methodology, but it does suggest that it is a vulnerability for
unredacted secrets to be available via any use of any API.”

 

Technical Details

The Argo manifests API endpoint returned raw Kubernetes manifest values, including unredacted Secret objects. Unlike other API endpoints which interact with the current cluster state, this endpoint derived the manifests from the configured git repository.

The following authenticated request and response pair demonstrates the vulnerability:

Request
GET /api/v1/applications/demo-gb/manifests HTTP/1.1
Host: argo-server.example
Cookie: argocd.token=eyJh[REDACTED]seUk

Response

HTTP/1.1 200 OK
Content-Type: application/json

{"manifests":["{\"apiVersion\":\"v1\",\"data\":{\"password\":\"MWYyZDFlMmU2N2Rm\",\"username\":\"YWRtaW4=\"},\"kind\":\"Secret\",\"metadata\":{\"labels\":{\"app.kubernetes.io/instance\":\"demo-gb\"},\"name\":\"mysecret\"},\"type\":\"Opaque\"}"

If you are not storing Secret manifests in git (and you shouldn’t be), this issue will present reduced risk.

 

Insecure Default Password – CVE-2020-8828

As of Argo v1.5.0, the default admin password is set to the argocd-server pod name. To determine the impact of this issue, the following questions must be answered:

  • Have you changed the admin password?
  • Does the argocd-server pod name contain sufficient entropy? (see details below)
  • Is the Argo API accessible on the internet? To internal pods?
  • Do unprivileged users in your organization have access to list pods in the argo namespace?
  • Do unprivileged users in your organization have access to logs which list pod names?

Although there is currently no published fix for this issue, it can be mitigated by disabling the admin user or by changing the admin user password. Argo must be updated to v1.5.0 or later to apply this mitigation.

 

Technical Details

As of v1.5.0the default admin password is set to the argocd-server pod name.

For insiders with access to the cluster or logs, this issue could be abused for privilege escalation, as Argo has privileged roles. A malicious insider is the most realistic threat, but pod names are not meant to be kept secret and could wind up just about anywhere.

To understand the risk of a black-box external attacker bruteforcing the password, we must understand the how pods are named. Below is the default naming scheme if you YOLO kubectl apply -f  the installation manifest in GCP:

    argocd-server-55594fbdb9-ptsf5
|    name   ||ReplicaSet||rand|

The name is static, and rand is easily enumerable. However, bruteforcing the ReplicaSet value in addition to rand is not feasible.

The rand value is produced by Kubernetes’ random name generator. The function that generates those characters is a time-seeded PRNG, and not a CSPRNGthe values are predictable and not truly random:

github.com/kubernetes/apimachinery/blob/master/pkg/util/rand/rand.go:26

var rng = struct {
    sync.Mutex
    rand *rand.Rand
}{
    rand: rand.New(rand.NewSource(time.Now().UnixNano())),
}

This presents an interesting attack opportunity if the attacker knows when the k8s server was instantiated. However with rand only being five characters, it’s easier to just bruteforce rand.

 

The ReplicaSet value is deterministically derived from a hash of the PodTemplate, which includes the metadata and the spec. It is unlikely that an attacker has access to the information necessary to determine this value. That said, it’s conceivable that this could be successfully fuzzed to generate the legitimate value in some environments.

Because the value is deterministic, deploying the same manifests into the same environment will result in the same ReplicaSet value. For example, at the time of writing if you deploy the Argo installation manifest from GitHub to a fresh GKE cluster, the ReplicaSet value will be 55594fbdb9.

The variable length of the ReplicaSet value is noteworthy, as characters are removed to prevent “bad words”. While not always easily bruteforceable, pod names should not be used in a security context.

 

Insufficient Anti-Automation – CVE-2020-8827

As of v1.5.0, the Argo API does not implement anti-automation measures such as rate limiting, account lockouts, or other anti-bruteforce measures. Attackers can submit an unlimited number of authentication attempts without consequence.

While Argo has not yet released an official fix for this issue, this can be mitigated by updating to v1.5.0 and disabling the admin user, as described here.

 

Session Fixation – CVE-2020-8826

As of v1.5.0, the Argo web interface authentication system issued immutable tokens. Authentication tokens, once issued, were usable forever without expirationthere was no refresh or forced re-authentication.

At the time of writing, there is no fix available for this issue.

 

User Enumeration – CVE-2020-11576

Fixed in v1.5.1, Argo version v1.5.0 was vulnerable to a user-enumeration vulnerability which allowed attackers to determine the usernames of valid (non-SSO) accounts within Argo.

The issue is demonstrated with the request and response pair below:

Request
POST /api/v1/session HTTP/1.1
Host: argo-server.example
Content-Type: application/json
Content-Length: 65

{"username":"admina","password":"argocd-server-55594fbdb9-bbbbd"}

Response
HTTP/1.1 404 Not Found
Content-Type: application/json
Trailer: Grpc-Trailer-Content-Type
Date: Sat, 04 Apr 2020 05:25:06 GMT
Content-Length: 52

{"error":"account 'admina' does not exist","code":5}

 

As shown above, the application returned a 401 when an account existed and returned a 404 when an account did not exist. This vulnerability was fixed in v1.5.1.

 

Acknowledgements and References

Many thanks to Alexander Matyushentsev from Intuit for his great attitude and assistance in resolving these issues.

Argo GitHub – https://github.com/argoproj

Patch for CVE-2018-21034 – https://github.com/argoproj/argo-cd/pull/3088

PR with documentation of other CVEs: https://github.com/argoproj/argo-cd/pull/3341

Argo documentation for unpatched vulnerabilities: https://argoproj.github.io/argo-cd/security_considerations/

 

Timeline

2/06/2020 – Vulnerabilities reported to Argo team
2/06/2020 – Argo team acknowledges issues, commits fix for sensitive information disclosure within 30 minutes.
3/06/2020 – Argo release delayed for authentication system security improvements.
3/20/2020 – Argo releases v1.5.0-rc1 which included a fix for the sensitive information disclosure issue.
4/02/2020 – Argo releases v1.5.0 and publishes public PR with mitigation recommendations for the other three issues.
4/04/2020 – User Enumeration issue identified in v1.5.0 and reported to Argo team.
4/06/2020 – Argo releases v1.5.1 which fixed the user enumeration issue.
4/06/2020 – Public disclosure

CVE-2018-21034

 

References