4

EDIT: Please view the revised question instead


The admin area has special access to the database (modifying orders, etc).

To help explain, I drew a diagram, so here is my process:

PHP Login System Diagram

Notes:

  • I left out having a timed session from the diagram for sake of simplicity of the diagram, but I will actually set a last_login date in the database so that inactive sessions can be logged out automatically.
  • Passwords are stored with AES encryption
  • The secret key or "salt" is hard-coded out of the web root folder
  • All database queries are parameterized.

But what are your thoughts about this process? Am I missing anything out?

  • 3
    Using AES for encrypting password [isn't a good idea](http://security.stackexchange.com/a/10496/5501) – Andrei Botalov Apr 25 '12 at 21:14
  • @AndreyBotalov According to the MySQL docs, AES is currently the most secure way of storing a password. I disagree with the answer you linked, because a dictionary attack as the answerer suggested wouldn't be feasible since the salt would need to be guessed in combination with the password. (Unless you have a Supercomputer at your hand, forget about it) –  Apr 25 '12 at 21:16
  • @Ozzy If your server is compromised, the attacker will know the salt. – CodesInChaos Apr 25 '12 at 21:21
  • @CodeInChaos But if the server is compromised, they have access to the database already? –  Apr 25 '12 at 21:23
  • Encrypting passwords used to log into your service is simply wrong. Hashing is a must. | There are some situations where you can't hash, for example if your server needs to use the password to log into something else(i.e. your server functions as user/client concerning that password), but unless there is such a requirement, you should hash. – CodesInChaos Apr 25 '12 at 21:24
  • 1
    @Ozzy The purpose of password hashing is to protect the passwords even if your database gets hacked. – CodesInChaos Apr 25 '12 at 21:25
  • 1
    @Ozzy, where have you seen in MySQL docs recommendation to use AES_ENCRYPT for encrypting password? I see recommendation to use MD5 or SHA2 [here](http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html#function_password) – Andrei Botalov Apr 25 '12 at 21:32
  • @CodeInChaos Note that this is an admin login, not a member login. There will be 1 or 2 admin accounts, password leakage isn't a problem because admin details/addresses aren't stored, and the admin will be wise enough to use a strong password that isn't used elsewhere. –  Apr 25 '12 at 21:32
  • @CodeInChaos BTW, is it really that easy to hack the database server (its on a shared-hosting) when all SQL inputs are parameterized? –  Apr 25 '12 at 21:33
  • @AndreyBotalov http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html `AES_ENCRYPT() and AES_DECRYPT() can be considered the most cryptographically secure encryption functions currently available in MySQL.` –  Apr 25 '12 at 21:39
  • @Ozzy Even if they are the securest encryption functions, that's irrelevant here, since you should not encrypt passwords. – CodesInChaos Apr 25 '12 at 21:41
  • @CodeInChaos the problem is, things like this: http://md5crack.com/, http://www.md5decrypter.co.uk/sha1-decrypt.aspx, thats why I'm using AES with a secret key :S. I still don't see how anyone would hack the server and obtain the key which is offline, they would have to hack the host account - how would they find out the host login details? –  Apr 25 '12 at 21:44
  • 2
    @Ozzy Nobody said that you should use md5. We typically recommend `bcrypt` or `PBKDF2`. You can keep part of the salt in a separate location(the config file) as a defense-in-depth measure. Such a scheme offers several advantages, and no disadvantage over encryption. So there is simply no reason to use encryption. – CodesInChaos Apr 25 '12 at 21:46
  • 1
    @CodeInChaos Okay so I'll have to change the members table to store a hash, and I'll look into bcrypt and PBKDF2, so thanks. How about the authentication of the session (see diagram)? Am I doing it right? –  Apr 25 '12 at 21:49
  • 1
    @Rook lol, which is why I'm here and asking, because yes, I'm clueless. I will read the OWASP top 10 now. Care to add an actual answer to enlighten me on the truck driving thing? –  Apr 25 '12 at 23:50
  • Every question I answer is worth a +1, I don't think that George's answer was sufficient. – rook Apr 26 '12 at 00:38

3 Answers3

9

Don't implement your own session handler. Use $_SESSION, it was written and audited by people who very good understanding security. I don't even know the intricacies of how your session handler works, but based on the little information you have given us its insecure.

SQL Injection is useful to obtain data from the database. We HASH passwords because in the event of an attacker obtaining this data, they will be forced to crack the hash before its useful. However, in your case, it doesn't matter that you are vulnerable to CWE-257, the attacker can just pull the session id out of the database, and use that to authenticate.

I could also gain admin access because you have made no mention of OWASP a9 - Insufficient Transport Layer Protection. You are also vulnerable to Clickjacking, every web app is by default. CSRF or "session riding" was already mentioned.

Enable the security flags "httponly", "secure". You can do this for $_SESSION by configuring PHP.

A defense in depth strategy is to plan on failure and limit the access your administrator has. Don't allow file upload or code execution. This is the number 1 reason why Wordpress instances get hacked, once you have admin on a Wordpress site, you have remote code execution on the server. Wordpress also implemented their own session handler at one point, and you guessed it, it was very insecure.

rook
  • 46,916
  • 10
  • 92
  • 181
  • Okay, you have given me a lot to think about, so big thanks! I suppose it's silly me trying to cover all of these aspects I have so little knowledge of myself - so I suppose it is best to use a package library for security? –  Apr 26 '12 at 00:44
  • @Ozzy probably, but you can't address everything with a library. Never re-invent the wheel, use whats given to you by the platform. That's not a security principle, that's true for all engineering problems. – rook Apr 26 '12 at 00:48
  • +1 @Rook! I totally forgot about session management. – 700 Software Apr 26 '12 at 14:01
  • @Ozzy, Maybe you should just post a separate question and use the comments for linking to that question? – 700 Software Apr 26 '12 at 14:18
  • @GeorgeBailey It's up here: http://security.stackexchange.com/questions/14215/is-this-admin-area-secure-enough-v2 –  Apr 26 '12 at 21:33
3
  1. Passwords should be hashed, not encrypted. The most preferable routine would probably be bcrypt. The repetition parameter should be adjusted so hashing of the passwords takes... say... 200 milliseconds, to slow down offline brute force of the password. (offline meaning your system was compromised and the hash was obtained) (200 milliseconds means your hardware, rented clouds or clusters could run the hashes much faster)

  2. The diagram looks reasonable to me.

Additional suggestions

  • Prevent online brute force. (online meaning using your php programs, only would be used they don't have a copy of the hash (as in, if they couldn't use offline brute force))

  • Prevent CSRF attacks: any call to your program that has side effects should require a special random key that came from an earlier request with the same cookie, this is to prevent you from visiting a web page that has an invisible form with an action pointing to your website's delete command, that is executed immediately by javascript. Or in the case of get requests that cause side effects, you may only need to be viewing an email that has an image tag to be attacked in this way.

  • Prevent XSS attacks: Someone might inject JavaScript or HTML into some columns that causes external JavaScript to execute, possibly sending off cookies, current page content, or any other content on your site using your session, and it is possible stuff could be modified/deleted.

  • The Session Management described has shortcomings. See Rook's answer.

This is not an exhaustive list.

I recommend looking around in this IT Security website. It really expands your knowledge of security.

Disclaimer: I am a programmer in multiple languages, but not PHP. I am a security enthusiast, but not necessarily an expert.

700 Software
  • 13,807
  • 3
  • 52
  • 82
  • Thanks for your answer. To prevent online brute force is simply setting a number of failed-login attemps which temporarily blocks an account right? –  Apr 25 '12 at 23:29
  • Oh and thanks for the mention of the CSRF attacks, thats the main thing I was worried about which I didn't know... a vulnerability of trusting a user from their cookie data, other than XSS attacks which I already read about. –  Apr 25 '12 at 23:40
  • 1
    Sounds reasonable. There are many ways to prevent online brute force. You may want to block the IP first, and only block the whole account if there are limits reached on several IPs. You may also want to do a silent block, so they keep trying, without knowing they reached a limit. That can be really annoying to legit users so unless you wait until ~10 failures. **Suggested Countermeasures to Online Brute Force** is not a question I have found yet. I did find [this](http://security.stackexchange.com/questions/14179). Maybe you should ask your own, as that only touches on it. – 700 Software Apr 26 '12 at 13:58
  • Haha thanks @George, I actually already read that question and all of the answers :). I think most people use captchas after 2 or 3 failed log-in attempts - probably the most effective way of stopping brute force attacks. –  Apr 26 '12 at 14:11
1

Don't forget to include non-technical controls as well, such as segregation of duties (requiring more than one admin's approval to make critical changes) and having an audit trail for accountability.

Graham Hill
  • 15,394
  • 37
  • 62