Remix.run Logo
undebuggable 4 hours ago

> the portal used incrementing numeric user IDs

> every account was provisioned with a static default password

Hehehe. I failed countless job interviews for mistakes much less serious than that. Yet someone gets the job while making worse mistakes, and there are plenty of such systems on production handling real people's data.

tracker1 3 hours ago | parent | next [-]

Literally found the same issue in a password system, on top of passwords being clear text in the database... cleared all passwords, expanded the db field to hold a longer hash (pw field was like 12 chars), setup "recover password" feature and emailed all users before End of Day.

My own suggestion to anyone reading this... version your password hashing mechanics so you can upgrade hashing methods as needed in the future. I usually use "v{version}.{salt}.{hash}" where salt and the resulting hash are a base64 string of the salt and result. I could use multiple db fields for the same, but would rather not... I could also use JSON or some other wrapper, but feel the dot-separated base64 is good enough.

I have had instances where hashing was indeed upgraded later, and a password was (re)hashed at login with the new encoding if the version changed... after a given time-frame, will notify users and wipe old passwords to require recovery process.

FWIW, I really wish there were better guides for moderately good implementations of login/auth systems out there. Too many applications for things like SSO, etc just become a morass of complexity that isn't always necesssary. I did write a nice system for a former employer that is somewhat widely deployed... I tried to get permission to open-source it, but couldn't get buy in over "security concerns" (the irony). Maybe someday I'll make another one.

alright2565 an hour ago | parent | next [-]

If you are needing to version your password hashes, then you are likely doing them incorrectly and not using a proper computationally-hard hashing algorithm.

For example, with unsuitable algorithms like sha256, you get this, which doesn't have a version field:

    import hashlib; print(f"MD5:      {hashlib.md5(b'password').hexdigest()}")
    print(f"SHA-256:  {hashlib.sha256(b'password').hexdigest()}")


    MD5:      5f4dcc3b5aa765d61d8327deb882cf99
    SHA-256:  5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
But if you use a proper password hash, then your hashing library will automatically take care of versioning your hash, and you can just treat it as an opaque blob:

    import argon2; print(f"Argon2:   {argon2.PasswordHasher().hash('password')}")
    import bcrypt; print(f"bcrypt:   {bcrypt.hashpw(b'password', bcrypt.gensalt()).decode()}")
    from passlib.hash import scrypt; print(f"scrypt:   {scrypt.hash('password')}")


    Argon2:   $argon2id$v=19$m=65536,t=3,p=4$LZ/H9PWV2UV3YTgF3Ixrig$aXEtfkmdCMXX46a0ZiE0XjKABfJSgCHA4HmtlJzautU
    bcrypt:   $2b$12$xqsibRw1wikgk9qhce0CGO9G7k7j2nfpxCmmasmUoGX4Rt0B5umuG
    scrypt:   $scrypt$ln=16,r=8,p=1$/V8rpRTCmDOGcA5hjPFeCw$6N1e9QmxuwqbPJb4NjpGib5FxxILGoXmUX90lCXKXD4
This isn't a new thing, and as far as I'm aware, it's derived from the old apache htpasswd format (although no one else uses the leading colon)

    $ htpasswd -bnBC 10 "" password
    :$2y$10$Bh67PQAd4rqAkbFraTKZ/egfHdN392tyQ3I1U6VnjZhLoQLD3YzRe
chuckadams 2 hours ago | parent | prev [-]

Several web frameworks, including Rails, Laravel, and Symfony, will automatically upgrade password hashes if the algorithm or work factor has changed since the password was last hashed.

makr17 2 hours ago | parent | prev [-]

Years ago I worked for a company that bought another company. Our QA folks were asked to give their site a once-over. What they found is still the butt of jokes in my circle of friends/former coworkers.

* account ids are numeric, and incrementing

* included in the URL after login, e.g. ?account=123456

* no authentication on requests after login

So anybody moderately curious can just increment to account_id=123457 to access another account. And then try 123458. And then enumerate the space to see if there is anything interesting... :face-palm: :cold-sweat:

josephg an hour ago | parent [-]

I did some work ~15 years ago for a consulting company. The company pushes their own custom opensource cms into most projects - built on top of mongodb and written by the ceo. He’s a lovely guy, and good coder. But he’s totally self taught at programming and he has blind spots a mile wide. And he hates having his blind spots pointed out. He came back from a react conference once thinking the react team invented functional programming.

A friend at the company started poking around in the CMS. Turns out the login system worked by giving the user a cookie with the mongodb document id for the user they’re logged in as. Not signed or anything. Just the document id in plain text. Document IDs are (or at least were) mostly sequential, so you could just enumerate document IDs in your cookie to log in as anyone.

The ceo told us it wasn’t actually a security vulnerability. Then insisted we didn’t need to assign a CVE or tell any of our customers and users. He didn’t want to fix the code. Then when pushed he wanted to slip a fix into the next version under the cover of night and not tell anyone. Preferably hidden in a big commit with lots of other stuff.

It’s become a joke between us too. He gives self taught programmers a bad rep. These days whenever I hear a product was architected by someone who’s self taught, I always check how the login system works. It’s often enlightening.