CVE-2022-46146 - Prometheus Exporter Toolkit Authentication Cache Poisoning Explained
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