Skip to content

Potential API Key security concerns

Moderate
huumn published GHSA-qg4g-m4xq-695p Mar 28, 2024

Package

No package listed

Affected versions

< df7e944b

Patched versions

df7e944b

Description

Hey k00b and ek,

I took a closer look at the implementation of API Keys in #915 and I wanted to share some thoughts/concerns. I am opening a security advisory to follow the responsible disclosure policy, though I have not actually identified an exploit. I thought it would be better to err on the side of caution. If we decide it's appropriate, we can move the discussion to a public GitHub issue or the like.

If I read the PR correctly, when a user generates an API key, the database generates a random string of 32 bytes and stores it in plain text in the database. The API key is then returned to the user. It is also subsequently returned to the user upon request at any point in the future.

In general, I am concerned about storing API Keys in plaintext in the database. As I understand it, this is the first time that any credentials are stored in the stacker.news database. All of the current authentication methods either defer authentication to other identity providers (GitHub, Twitter) via OAuth, or uses asymmetric encryption (a broad generalization) to assert an identity like nostr or LNAuth.

With this approach for API Keys, the stacker.news database now has the potential to become a target for attacks with plaintext API keys. Prior to this point, while there is plenty of interesting info in the database, including funds, gaining access would not grant an attacker the ability to impersonate another user accessing the app externally, since no login credentials are stored in the DB.

I am curious if you considered taking other approaches, or at least approaches that build upon what's already implemented? Based on some quick research, the following seems like a decent approach (sourced from https://security.stackexchange.com/a/180364):

  1. Generate the random bytes as you're doing today
  2. Hash the random bytes and store that as the hashed API key in the DB
  3. Show the API key to the user on screen, but make it clear that it will not ever be retrievable again
  4. When validating a request with an API key, you'd need to hash it with the same hashing algorithm first in order to do the lookup in the DB.

You could also build upon that and sign the generated keys before hashing them, in order to prevent forgery (inspired from https://stackoverflow.com/a/24367962).

I hope I am not overstepping, but I wanted to share my thoughts here and see what you all think.

Looking forward to hearing back from you.

Best,

WeAreAllSatoshi

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Local
Attack complexity
Low
Privileges required
High
User interaction
Required
Scope
Unchanged
Confidentiality
None
Integrity
High
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:L/AC:L/PR:H/UI:R/S:U/C:N/I:H/A:N

CVE ID

No known CVE

Weaknesses

Credits