CWE-522 is a product that transmits or stores authentication credentials using an insecure method that is open to interception or retrieval. MITRE lists web based systems and ICS and OT among the platforms, and says it is not specific to a language.
Credentials are passwords, tokens, keys and anything else that proves identity. If an attacker gets them, they do not need to break anything else.
How it happens
There are two halves: in transit and at rest.
In transit, credentials are sent without protection, so anyone on the path can read them. At rest, they are stored in a form that can be read or easily reversed: plaintext, a trivial encoding, or a file anyone can open.
The record lists four cases that show the range.
- CVE-2022-29519: a programmable logic controller sends sensitive information in plaintext, including passwords and session tokens.
- CVE-2022-29959: an initialization file contains credentials that can be decoded with a simple string transformation. Encoding is not protection.
- CVE-2022-30018: a messaging platform serializes all elements of user and group objects, making private information available to adversaries.
- CVE-2022-35411: a Python based RPC framework enables pickle functionality by default, letting clients unpickle untrusted data.
The last two are indirect. Credentials leak because of how objects are serialized, or how data is parsed, not because someone wrote a password to disk.
# Vulnerable: reversible "protection" in a config file
import base64
password_field = base64.b64encode(b"s3cret").decode() # anyone can decode this
# Vulnerable: sending credentials over plain HTTP
requests.post("http://example.com/login", data={"user": u, "pw": p})
What an attacker gains
MITRE says an attacker could gain access to user accounts and to sensitive data used by those accounts. The listed impact is gaining privileges or assuming an identity.
Because credentials are reusable, the harm often spreads. People reuse passwords, and tokens may work on many services.
How to find it
Automated static analysis can find some instances by following credentials from where they are read to where they are stored or sent. Also check by hand:
- Search code and configuration for passwords, tokens and keys held as plain strings, or in base64 or other simple encodings.
- Look at every login and API call to confirm it uses an encrypted channel.
- Review which fields get serialized into responses, logs and exports. Make sure password hashes and tokens are not among them.
- Check for secrets in repositories, images and build output.
A secrets check in your pipeline catches many of these before release.
How to fix it
MITRE lists three design and implementation steps.
- Use an appropriate security mechanism to protect the credentials.
- Make appropriate use of cryptography to protect them.
- Use industry standards to protect them, for example LDAP or a keystore.
In practice:
- Send credentials only over TLS.
- Store passwords as salted hashes made with a slow password hashing function, never as plaintext or reversible values.
- Keep API keys and tokens in a secrets manager or keystore, not in files in the repository.
- Exclude secrets from serialization with explicit field lists, so new fields are not exposed by default.
- Do not enable object deserialization of untrusted data. Use a data only format.
import bcrypt
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt()) # store this
ok = bcrypt.checkpw(attempt.encode(), hashed)
Try it yourself
Click through it at your own pace, or open it full screen.
Quick check
Is base64 a way to protect a password in a config file?
No. It is an encoding that anyone can reverse. The record includes a CVE where credentials could be decoded with a simple string transformation.
Can serialization expose credentials?
Yes. Serializing whole user objects can include private data. Use explicit allow lists of fields.