There is a public application that has terrible security practices. When performing an API call to such application, and succesfully logging in, it will return a "user" JSON that includes the MD5 hash of their password, and the MD5 hash of their administrator's password.

The thing is, the user interface inside the application is able to show the plain-text password of every user, which leads me to believe the password is stored in plain-text or encrypted, and only MD5 hashed when returning them through the API call.

I have been performing some tests with known passwords, and they don't match the MD5 hash. Here's the thing.

When User1 sets their password as "test", the resulting MD5 is different than when the User2 sets their password as "test", meaning they are, at least, salted.

Salt is related to user data (I have tried concatenating their UserId, email, identifiers to the password before MD5 with no luck).

I know salt is related to user data because no matter how many times User1 changes their password, their hash will always be the same when the password is "test", its not a random salt generated each time.

How could I continue investigating this case? I want to know how it works internally. Test data could be shared in private.

  • Is the interface inside the application show the plain-text password of every user or of the current user? It the later, it might be caching the password used to log into the app (albeit probably not what they're doing).
    – Ángel
    Mar 8, 2023 at 20:21
  • I thought of that as well, and that's why I looked in the browser's localstorage, sessionstorage and even switched computers just in case there was some cached file. An administrator can see the password of every user he has control over. Mar 9, 2023 at 6:28

1 Answer 1


There is an infinite number of ways to calculate a hash, even if the final method is MD5. It's common to have multiple hashing rounds, there might be another (hopefully much stronger, like Argon2) hashing method involved, and/or there may be a pepper.


  • MD5(salt+password)
  • MD5(salt+MD5(password))
  • MD5(Argon2(salt+password))
  • MD5(pepper+MD5(salt+password))

Given MD5's weakness and the need for a KDF or other password-specific hash, I'd hope it's secure and just happens to look like MD5, maybe something like substr(sha256(Argon2(salt+password)), 32)

Still, if they can reference the real password, they're storing it unhashed (hopefully encrypted). This is not a good practice, but at least they're not sharing it with you directly. Given this bad practice, they're probably just doing something like MD5(salt+MD5(password)). Once an attacker breaks that scheme, they're hosed.

  • Thing is I need to officially prove how and why their practices are unsafe, meaning I need to actually break the password or connect to the db and get the plaintext from there. Mar 8, 2023 at 17:01
  • 3
    I think you have what you need: they're storing the password unhashed. The fact that they call it "MD5" should be sufficient to demonstrate that they don't know how to hash anyways. I see no reason to spin up hashcat on each of a dozen hashing schemes in order to tease out the exact scheme, salt, and (optional) pepper.
    – Adam Katz
    Mar 8, 2023 at 17:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .