Tutorials

PHP Security

by Daniel Egeberg on Jun 30, 2008 12:40:06 PM

7. Session security

Sessions and cookies are also two things where you have to watch out. Although they cannot breach your application's security they can be used to compromise user accounts.

When you are using sessions, PHP will most often store a cookie on the client computer called PHPSESSID (can be changed by you). This cookie will hold a value, a session identifier, which is associated with some sort of data on the server. If the user has a valid session ID then the data associated with the session will get into the $_SESSION super-global array. Sessions can also be transferred via the URL. In that case it would be something like ?PHPSESSID=id_here.

7.1. Stealing the cookies

Imagine that you have a key for a vault in your bank. If you have the key then you can get whatever is in the vault. The session ID works a bit like that. However, your key for your vault can be stolen and similarly can the session ID of your users (including you) be stolen or intercepted.

For the record, just because I used a vault/key analogy then it does not mean that you should put secret or important data of some sort in your sessions.

Earlier we talked about XSS and I mentioned briefly that it could be used to steal people's cookies. That is the most common way cookies are stolen. This cookie could be PHPSESSID (or whatever you may have renamed it to. When you steal a session ID and try to use it again it is called session fixation. So... if you can get a valid session ID and that session is used for something like authentication then you will essentially be logged in as that user. Obviously that is not a good thing - especially not if the user is high ranking with administrative privileges.

7.2. Issues with shared hosting

Most people host their website on what is called shared hosting. It is basically when there are multiple people having their websites hosted on a single server. On a server with a Linux operating system session data will by default be stored in the /tmp directory. It is a directory that stores temporary data and it will obviously have to be readable and writable by everyone. Therefore, if your session data is stored in there, which it is by default, then the other users can find it if they look hard enough. This poses the same security issues as with cookies being stolen using XSS.

7.3. Preventing session fixation

Now that we have talked a bit about how the session ID can be stolen then let us talk a bit about how we can minimize the risk session fixation.

One thing we can do is to change the session ID often. If we do that then the chance that the intercepted session ID will be valid will be greatly minimized if that ID changes often. We can use one of PHP' built-in functions called session_regenerate_id(). When we call this function the session ID will be, no surprise, regenerated. The client will simply be informed that the ID has changed via an HTTP response header called Set-Cookie.

If you are using PHP 5.2+ then you can tell the browser that Javascript should not be given access to the cookie using a flag called httponly. You can set this flag using the php.ini directive called session.cookie_httponly or you can use the session_set_cookie_params() function.

Regarding the issue with the shared hosts, the fix is simple: store the data where only you have access. You can use the directive called session.save_path to set another path for storing them. You can also store them in a database, but then you will have to write your own handler using the function called session_set_save_handler().

Comments

You wrote a very nice tutorial here. I'm going to keep all these security advices in mind.

1. John McKenzie on Jun 30, 2008 4:07:27 PM

a great article,
definitely bookmarked.

2. HoTDaWg on Jul 1, 2008 9:46:22 PM

I actually created a post in the Forums asking where to find a good tutorial on PHP security: it was right here on the home page!

3. rupertrealbear on Jul 2, 2008 6:40:55 PM

Great tutorial - explains alot of technical stuff definately recommended

4. Wasim Ilyas on Jul 11, 2008 8:36:42 AM

about the mysql injection, how would such a user find out the name of the table/structure of the table so they could put something to damage the database?

is there a way of stopping them finding out the database/table structure?

5. Flames on Jul 24, 2008 8:36:44 AM

Flames: It could be guesswork, but there are also queries that will allow you to see how the tables are laid out. It could also be an open source app, and it that case it would be as simple as checking the source.

6. Daniel Egeberg on Jul 24, 2008 10:00:29 AM

k, i've been trying to stop mysql injection and although its taken time i finally got it to work without random apostrophes being put in places :D.

7. Flames on Jul 24, 2008 11:07:42 AM

Views: 17435 lol

8. dezkit on Jul 26, 2008 9:14:19 PM

One part is missing, security problems related to emails.

9. Hervé Thouzard on Jul 27, 2008 3:11:32 AM

good stuff!

10. libertyct on Jul 28, 2008 10:44:46 AM

Im happy I found this tutorial - dont understand lots of stuff but will re-read so that it sits.

11. Dorothy Wegmueller on Aug 5, 2008 6:14:18 PM

Well, feel free to ask in the forums if there is anything specific in the tutorial you need help with :)

12. Daniel Egeberg on Aug 5, 2008 7:53:32 PM

Very nice tutorial indeed. It is very helpful for newbie's like me.

13. cyberbuff on Aug 11, 2008 4:57:40 AM

Excellent tutorial. I've had experience with other scripting languages and decided to try PHP. This is really a great start what to look out for and how to design with these dangers in mind.

One question about the include(), mostly for db access. Some showed using a config.pm that would contain passwords to the db.

Would you consider this secure?

mkdir public_html/secure
chmod 711 public_html/secure
create the config.pm containing the db access

in the php script, I add
include('../secure/config.pm');

Would it be better to not be in the document root at all?
I notice in the tree, the config dir is in the system root, not doc root.

Thanks

14. budman85 on Aug 12, 2008 8:11:32 PM

The safest way would be to not place it within document root at all.

15. Daniel Egeberg on Aug 13, 2008 11:10:32 AM

Daniel, great article, was a good read and learned a lot (implementing some of this stuff as I'm writing this.) In doing so, I've noticed that the error_reporting and error_log statements in .htaccess files seem to not work unless they are preceeded by php_value, and not php_flag as stated in the article. Feel free to correct me if I'm wrong, I just thought I'd point it out in case anyone else ran into the issue.

Thanks again :)

16. vnums on Aug 15, 2008 11:15:05 AM

the pdf article for download just gets a 404

17. Brad Floyd on Sep 17, 2008 11:13:51 PM

Ooops... sorry about that. It's back up now.

18. Daniel Egeberg on Sep 18, 2008 1:25:08 PM

cool :-) Just thought I'd point it out since security is one aspect people need to pay more attention to I agree

19. Brad Floyd on Sep 18, 2008 7:34:22 PM

However, wouldn't RFI only be an issue if PHP - Register globals is turned on?

Note some shared hosts has it disabled by default.

20. BlueBoden on Nov 11, 2008 4:20:41 AM
Login or register to post a comment.