1

Say that I have a user account system on my website. When I enter a username and password, it just checks it against a database using prepared statements. If the user tries to login more than once per 10 seconds, they are locked out for 10 minutes.

Most (even the simplest) login scripts I've seen feature more security than this, though I haven't looked at it in detail. What else would be necessary for a secure system? I've got brute force and SQL injection covered, what else is there?

Sorry for such a naive question, I'm new in the web development/security field.

3

Secure auth is harder than you think!

  • Your anti-brute force system is exploitable by a malicious user who wants to lock out specific other users (not always relevant, but imagine something like an auction site where you know somebody else is trying to get the same thing and you want to prevent them from logging in and driving up the price...). To do it correctly, either use a CAPTCHA (or other way to slow down repeated/automated attacks) rather than just locking the account, or send the locked-out user an email containing a link that they can use to log in (either directly, in which case the link should expire quickly, or simply giving the user a shot to enter their password, which if they get it right lets them in even if they are locked out). You can also do IP-based blocks, but those offer additional attacks for troublemakers (for example, prevent everybody behind a particular NAT-ing router from logging in, or use proxies or botnets to attack their target from lots of IPs).
  • If the wrong password is entered but the site takes you back to the same login screen with the username/email/whatever ("ID") pre-populated, make sure that the ID is not a vector for reflected XSS.
  • If the login screen has a "return to" function that takes you directly to a page within the site - and most do - make sure that this isn't an open redirect and also that it isn't vulnerable to reflected XSS.
  • For some sites, login CSRF is a risk; an attacker CSRFs you to log you into their account (which looks exactly the same as your own) instead of your own account, and when you go to the vulnerable site and then do something like upload a file or enter payment info or whatever, the attacker can log in as well (after all, it's actually their account, even though it looks like yours) and steal whatever info, etc. you entered.
  • Conventional cryptographic hashes, even salted and iterated, do not make for a proper password hashing function. Use argon2 or scrypt (or bcrypt or PBKDF2, if you have nothing better available).
  • Include support for upgrading your password hashing (at a minimum, for increasing the "work factor" such as iterations) so that you can move to more secure algorithms as old ones get broken and/or computers get faster.
  • As deviantfan mentioned, session fixation is also a big risk.
  • Pages that let you change credentials (login ID and/or password) are basically login pages as well - or at least, should be - and need similar levels of security even though they require auth just to get to them.
  • Account registration is also usually part of an authentication package, and needs to be handled carefully (lots of opportunities for SQLi, XSS, session fixation if it logs you in directly, and of course the need to handle the user-supplied passwords and optionally multi-factor auth tokens securely), including email verification.
  • Password reset (for forgotten passwords) is a big deal, and often implemented poorly. It is, for example, vital that attackers neither be able to predict nor brute-force the reset link, and the reset link should expire quickly to help protect the account even if an attacker later gains some access to the user's inbox.
  • Any decent auth system should support some degree of multi-factor authentication today. Serious sites should support good MFA methods, such as FIDO2. You can also use mutual TLS (client certificates), although that's uncommon for consumer-oriented sites.
  • Credential stuffing (attackers using other peoples' credentials taken from unrelated sites and trying them on your site, because most people re-use credentials a lot) is a risk that should be mitigated via things like checking for 'pwned passwords' and requiring MFA or at least requiring email re-verification again for login attempts that are unusual in some way.
  • Logging needs to record login attempts - ideally both successful and failed - but needs to not capture passwords or other credentials, and logs should be secure against tampering, log injection attacks, indirect XSS (attacking the log viewer), and denial-of-service.
  • Session token generation needs to be handled securely. Some token types (like JWT) scale better, but are hard to revoke and must be configured with secure (and securely stored) keys and parsed carefully; others (like just using a random string) need to be generated using a cryptographically secure generator and the list of valid tokens and their associated sessions needs to be kept in sync across your cluster if you move to using multiple servers. Generally you shouldn't store data such as the user's access level in their own token, and if you do, the token must be cryptographically signed and ideally also encrypted.
  • Session tokens need to be stored securely client-side. That usually means a cookie with the Secure, flag. HttpOnly, and ideally also the new SameSite flag, can add additional protection.
  • Users should be able to revoke all active sessions (often this is done when changing the password, for example). Ideally, users can also see their own login history, and what devices have accessed their accounts from how long ago, and whether those sessions are still live.

I could probably think of more, if I gave myself more time. These are not ordered, and some of them may not be applicable to all sites, but all of them do have security implications. I say again, secure authentication is harder than you think!

  • Imho most of your points were either mentioned already or are not specific to authentication pages (and related features). ... (still some new points are here, and of course +1) – deviantfan Dec 7 '18 at 15:46
  • @deviantfan Sure, some of it (like the XSS stuff) is standard webapp security, but I was envisioning somebody writing an auth package that could be dropped into a PHP app, and was making a list of additional concerns I'd want the author to address beyond the OPs list of brute-force (badly) and SQLi in the actual login page. Things like open redirect may be a general security risk, but in practice are usually found on login pages, and XSS on a login page is especially bad because it lets you steal creds, not just hijack the current session. – CBHacking Dec 10 '18 at 1:59
5

You forgot at least:

  • Hashes (+ Salts, enough rounds, ...)
  • Password reset functionality
  • HTTPS (ok, not really a problem of PHP code)
  • Always changing the session ID on login and logout

and depending on the use case things like

  • 2factor auth
  • Single login for multiple sites
  • ...

Also see eg. https://www.owasp.org/index.php/Authentication_Cheat_Sheet

But yes, it doesn't have to be hard.

Are you wondering why there still are errors found, in (relatively) simple logins of some websites? Well, because even "simple" logins are too much for the vast majority of people. And even if we only consider people who can program enough to be able to do it, there are still enough just too lazy to properly do it because they can't be convinced that leaving part X out will be a problem. Or they know, but don't want to think about it because it's easier to be lazy.

  • Oops, left out the hasing/salts/HTTPS parts in my list of what I knew a login needed. Great answer, really helpful! – Redwolf Programs Dec 7 '18 at 4:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.