Advanced security questions
Moderator: General Moderators
Re: Advanced security questions
I am using CBC mode encryption with the RIJNDAEL cipher only for the "remember me" feature of the site, where I am encrypting the user's username and password and storing it in a cookie on their machine, along with the iv. If the iv got deleted they would just have to log in again.
The notes in the database are encrypted using MySQL's built in AES encryption algorithm (which I understand uses RIJNDAEL as well, but I don't know much about the implementation). If an iv is generated for this it is abstracted from me and maintained by the DB because MySQL just asks for the text to encrypt/decrypt and the key.
I am starting to wonder if the built-in AES encryption in MySQL might be a potential weak spot. Maybe I should handle the encryption in PHP, or do you think the MySQL encryption is sufficient?
oh, the key for the notes in the database is a hash generated using the user's password and a salt (which is a different salt then the one used for the username and password hashes stored in the user table).
The notes in the database are encrypted using MySQL's built in AES encryption algorithm (which I understand uses RIJNDAEL as well, but I don't know much about the implementation). If an iv is generated for this it is abstracted from me and maintained by the DB because MySQL just asks for the text to encrypt/decrypt and the key.
I am starting to wonder if the built-in AES encryption in MySQL might be a potential weak spot. Maybe I should handle the encryption in PHP, or do you think the MySQL encryption is sufficient?
oh, the key for the notes in the database is a hash generated using the user's password and a salt (which is a different salt then the one used for the username and password hashes stored in the user table).
Re: Advanced security questions
Ah, right. In that case, yes, creating a random IV every time and store it in their cookie would be just fine.examancer wrote:I am using CBC mode encryption with the RIJNDAEL cipher only for the "remember me" feature of the site, where I am encrypting the user's username and password and storing it in a cookie on their machine, along with the iv. If the iv got deleted they would just have to log in again.
MySQL's AES encryption is sufficient as long as your keys are secure, and based on your description I'd say they are.I am starting to wonder if the built-in AES encryption in MySQL might be a potential weak spot. Maybe I should handle the encryption in PHP, or do you think the MySQL encryption is sufficient?
oh, the key for the notes in the database is a hash generated using the user's password and a salt (which is a different salt then the one used for the username and password hashes stored in the user table).
- kaisellgren
- DevNet Resident
- Posts: 1675
- Joined: Sat Jan 07, 2006 5:52 am
- Location: Lahti, Finland.
Re: Advanced security questions
Just to make sure examancer did not get me wrong.
I earlier post that MCRYPT_RAND is not very random. Yes that's true, but it won't affect your security level, because like I also said:
I earlier post that MCRYPT_RAND is not very random. Yes that's true, but it won't affect your security level, because like I also said:
So it does not really matter that much in your case.The Initialization Vector is allowed to be public,
- kaisellgren
- DevNet Resident
- Posts: 1675
- Joined: Sat Jan 07, 2006 5:52 am
- Location: Lahti, Finland.
Re: Advanced security questions
The AES encryption uses RIJNDAEL, right? Then it's not "sufficient", it's as *high* as you can get at the moment. At least on the database side.Apollo wrote:Ah, right. In that case, yes, creating a random IV every time and store it in their cookie would be just fine.examancer wrote:I am using CBC mode encryption with the RIJNDAEL cipher only for the "remember me" feature of the site, where I am encrypting the user's username and password and storing it in a cookie on their machine, along with the iv. If the iv got deleted they would just have to log in again.
MySQL's AES encryption is sufficient as long as your keys are secure, and based on your description I'd say they are.I am starting to wonder if the built-in AES encryption in MySQL might be a potential weak spot. Maybe I should handle the encryption in PHP, or do you think the MySQL encryption is sufficient?
oh, the key for the notes in the database is a hash generated using the user's password and a salt (which is a different salt then the one used for the username and password hashes stored in the user table).
RIJNDAEL was chosen for AES, because it was the strongest cipher. Serpent is also a good choice, yet it's still fast.
Re: Advanced security questions
RIJNDAEL was not the strongest, it is just fast and strong
Re: Advanced security questions
Wow. You guys really know a lot about security. I am glad I stopped by. I think the most important thing I have learned form all this is that I need a way to upgrade or change my encryption schemes without breaking user's accounts. I have some ideas about how to do this.
I'll be back when the code is a little cleaner and I'm ready to show it off
I'll be back when the code is a little cleaner and I'm ready to show it off
- kaisellgren
- DevNet Resident
- Posts: 1675
- Joined: Sat Jan 07, 2006 5:52 am
- Location: Lahti, Finland.
Re: Advanced security questions
Well yea let me rephrase, RIJNDAEL is not the strongest, but most secure yet quick.arjan.top wrote:RIJNDAEL was not the strongest, it is just fast and strong
Re: Advanced security questions
Why are you storing the password (even if it's encrypted) in a cookie? you are sending that data to the client and it could be intercepted. You should just store the authentication result (success) and do it in a session ( => server-side). I hope you are not relying on any cookie information for authorization in your application (user roles).I am encrypting the user's username and password and storing it in a cookie
Re: Advanced security questions
Normally that is how I would do it... store the authentication result and just hand the user a session id. However, that is insufficient for a model in which the user's own password is used to encrypt their notes. I need to have that plain-text password (or a hash based on it) available in the session data on the server. I can't just use the password hash stored in the user table, because then there is no point to encrypting their notes... an attacker could simply take the user's password hash and use it to decrypt their notes, all within the database. I need the password, or yet another hash derived from it (using a different salt+pepper than the one used in the user table's password hash) and I need it to be part of the server side session data so that when the session is over (destroyed) there is no way to decrypt the user's notes. The user is the only one who possesses the information needed to decrypt them. It is never persisted by me, only retained in the server session for convenience so they don't have to send their password on every page view. This works well and this does NOT require me to store the user's username and password in a cookie. However... there is more...pytrin wrote:Why are you storing the password (even if it's encrypted) in a cookie? you are sending that data to the client and it could be intercepted. You should just store the authentication result (success) and do it in a session ( => server-side). I hope you are not relying on any cookie information for authorization in your application (user roles).I am encrypting the user's username and password and storing it in a cookie
I then need a way to remember users for long periods of time. I don't want to maintain that server side session data for the entire 90 days their cookie might be valid. The session contains the user's password, so if someone gets server access any time during that 90-day period they would be able to read the user's password if they can locate the session data. I came up with the solution of storing an encrypted version of the user's username and password in their cookie so that I could expire sessions quickly while still providing an automatic login capability. While not perfect, this means that the server has the information needed to decrypt the user's notes for the duration of the session only. If there is a better way to implement my "remember me" feature without storing an encrypted user/password I am all ears.
While reading your post and writing this reply I did come up with an alternative which MAY be better. I would like your opinion. When a user chooses the "remember me" option, instead of storing the encrypted username and password in the user's cookie, I will store the encrypted username and password in the database and store the user ID and the encryption key in the cookie. When the cookie is used to log the user in I will use the key in the cookie to decrypt the user/pass (confirmed by hashing the decrypted values and making sure they match the user/pass hashes for the user). This will give the app access to the password to decrypt notes only for the duration of the server-side session. Every time the user is logged in by cookie (meaning a new session) their cookie could be updated with a new randomly generated key. I would think this might make session hijacking a little more difficult.
Does this sound reasonable?
Re: Advanced security questions
If someone gets access to your server, then all of your logic and database data will be exposed. That should be your main concern - protect your server!so if someone gets server access any time during that 90-day period
Honestly, I don't think there's much difference between using a session and storing it in the database. Databases do offer an additional authentication mechanism, however they are also accessed from unrelated sources which could compromise it if there is a database vulnerability anywhere else in the system.
There are several things you can do to mitigate session attacks - you can read in much detail on the PHP Security consortium - http://phpsec.org/projects/guide/4.html
- volomike
- Forum Regular
- Posts: 633
- Joined: Wed Jan 16, 2008 9:04 am
- Location: Myrtle Beach, South Carolina, USA
Re: Advanced security questions
Pytrin:
I guess with sessions, you have to think about what happens when you want to scale the app across multiple web nodes using a reverse proxy like tcproxy or Pound. At that point you have to point your session objects at a database because there is no unified shared memory across the web nodes. Or, you configure your reverse proxy to take a given IP address and _always_ send it to the same web node for that day so that session state is maintained. (But happens when they access the site at midnight?)
Another consideration is that if you don't use encrypted, compressed cookies for maintaining state, and using sessions, then, on a site with a lot of simultaneous web connections, you're occupying a very large chunk of tmpfs (virtual memory, which includes the shared memory pool). When you use encrypted, compressed cookies, all that session state space is offloaded to the clients, reducing RAM and disk space necessary for tmpfs. I'm guessing that this is also important on a shared hosting plan solution where tmpfs allocation to a particular PHP process may be limited, right?
Last, if you suddenly realize you need to use database rows for maintaining session state, then you have to think about abandoned sessions. I'm not certain what the $_SESSION object does when a session times out and it's been set to use a database for that session -- does the row get automatically deleted? But anyway, using a database for this kind of data seems like it would be slow.
So, in sum, the reasons why I use encrypted, compressed cookies for session state are:
1. Works in a web farm without having to rewrite the app, and without having to use a database connection to maintain session state, which would slow down the site to a crawl when there are lots of connections.
2. Uses far less virtual memory on the server, which is not only a consideration for the speed of the site, but is also a potential consideration on a throttled shared hosting plan for some site owners.
3. Speed.
The downsides on cookies? Yeah, a little --
{First -- don't get me wrong. I do not mean client-side encryption/decryption or compression/decompression. I _only_ mean handling those algorithms on the server.}
1. You have to encrypt your cookies, so the space in that cookie increases. So, you add compression, but it only decreases slightly.
2. Encryption/decryption creates a slight server processor load and some amount of virtual memory briefly.
3. Compression/decompression -- same as point 2.
4. People can turn them off, so you have to trap that and not let the user use the site without enabling them. (I can't tell you how far you would get on the web if you disabled all cookies all the time. It would be a very limited experience.)
5. Bad guys with a beowulf cluster on a stack of xboxes could perhaps spend 3 months and hack your site cookies, doing havoc. So, to thwart them, you add like 5 random bytes on the start of every string and a crc32() call to check integrity, then hook it up to some email alarms when broken.
I guess with sessions, you have to think about what happens when you want to scale the app across multiple web nodes using a reverse proxy like tcproxy or Pound. At that point you have to point your session objects at a database because there is no unified shared memory across the web nodes. Or, you configure your reverse proxy to take a given IP address and _always_ send it to the same web node for that day so that session state is maintained. (But happens when they access the site at midnight?)
Another consideration is that if you don't use encrypted, compressed cookies for maintaining state, and using sessions, then, on a site with a lot of simultaneous web connections, you're occupying a very large chunk of tmpfs (virtual memory, which includes the shared memory pool). When you use encrypted, compressed cookies, all that session state space is offloaded to the clients, reducing RAM and disk space necessary for tmpfs. I'm guessing that this is also important on a shared hosting plan solution where tmpfs allocation to a particular PHP process may be limited, right?
Last, if you suddenly realize you need to use database rows for maintaining session state, then you have to think about abandoned sessions. I'm not certain what the $_SESSION object does when a session times out and it's been set to use a database for that session -- does the row get automatically deleted? But anyway, using a database for this kind of data seems like it would be slow.
So, in sum, the reasons why I use encrypted, compressed cookies for session state are:
1. Works in a web farm without having to rewrite the app, and without having to use a database connection to maintain session state, which would slow down the site to a crawl when there are lots of connections.
2. Uses far less virtual memory on the server, which is not only a consideration for the speed of the site, but is also a potential consideration on a throttled shared hosting plan for some site owners.
3. Speed.
The downsides on cookies? Yeah, a little --
{First -- don't get me wrong. I do not mean client-side encryption/decryption or compression/decompression. I _only_ mean handling those algorithms on the server.}
1. You have to encrypt your cookies, so the space in that cookie increases. So, you add compression, but it only decreases slightly.
2. Encryption/decryption creates a slight server processor load and some amount of virtual memory briefly.
3. Compression/decompression -- same as point 2.
4. People can turn them off, so you have to trap that and not let the user use the site without enabling them. (I can't tell you how far you would get on the web if you disabled all cookies all the time. It would be a very limited experience.)
5. Bad guys with a beowulf cluster on a stack of xboxes could perhaps spend 3 months and hack your site cookies, doing havoc. So, to thwart them, you add like 5 random bytes on the start of every string and a crc32() call to check integrity, then hook it up to some email alarms when broken.
Re: Advanced security questions
Session clustering is not so difficult, and just a small part of scaling out. Database replication/clustering load balancing and so forth, believe me - sessions will be the least of your worries. And you suggested some very common approaches to deal with that, so I guess you know it's that big of an issue - if you get to the stage that you have to scale, you must be doing something right 
Second, I didn't say store all user information in the session - just the authentication result, role and maybe the username. The rest can definitely go in cookies, where they belong (non-sensitive data).

Second, I didn't say store all user information in the session - just the authentication result, role and maybe the username. The rest can definitely go in cookies, where they belong (non-sensitive data).
would those be xbox 360's?Bad guys with a beowulf cluster on a stack of xboxes...
Re: Advanced security questions
For my application, the performance difference between storing sessions in the filesystem (PHP's default implementation) and storing them in the database is marginal. Either way the app is going to be spending most of its time waiting on the database to encrypt/decrypt notes. This is also why the app may have trouble scaling and second biggest reason I will be releasing the source code (first is transparency) for users to run on their own. In a situation where the site is already under heavy load, the simple act of a user with a few thousand notes doing a text search would likely grind the site to a halt. The only way to accomplish a search is by decrypting all of the notes. MySQL's AES decryption works fast, but searching this way is several orders of magnitude slower than a well indexed full-text search implementation (which I don't believe is possible with encrypted data). I suppose disabling search could allow the app to scale pretty well actually, but this seems like a core feature if someone really plans to use this for regular note taking or journal writing.
In light of this I am far more worried about which session implementation is more secure in a shared hosting environment than which one is faster. Either way, I cannot imagine it being the bottleneck of this application. From what I have read it is looking like storing sessions in the database would be a "little" more secure, so I might take that approach.
Thanks
In light of this I am far more worried about which session implementation is more secure in a shared hosting environment than which one is faster. Either way, I cannot imagine it being the bottleneck of this application. From what I have read it is looking like storing sessions in the database would be a "little" more secure, so I might take that approach.
Thanks
Re: Advanced security questions
Regarding that, you should look into designated indexing engines, such as lucene or sphinx. Sphinx has great integration with PHP and MySQL and is blazingly fast for text searches, while lucene has a pure PHP implementation if you don't have / can't install extensions on your server.a well indexed full-text search implementation (which I don't believe is possible with encrypted data)
Both would be several orders of magnitude faster than MySQL fulltext indexes (especially sphinx). You can use indexes that only tokenize but do not store any information, and link them to the appropriate rows in the database.
Re: Advanced security questions
Interesting. Thank you. Searching may not be such a bottleneck after all.