PHP Security Guide: Shared Hosts

Exposed Session Data

When on a shared host, security simply isn’t going to be as strong as when on a dedicated host. This is one of the tradeoffs for the inexpensive fee.

One particularly vulnerable aspect of shared hosting is having a shared session store. By default, PHP stores session data in /tmp, and this is true for everyone. You will find that most people stick with the default behavior for many things, and sessions are no exception. Luckily, not just anyone can read session files, because they are only readable by the web server:

$ ls /tmp
total 12
-rw——- 1 nobody nobody 123 May 21 12:34 sess_dc8417803c0f12c5b2e39477dc371462
-rw——- 1 nobody nobody 123 May 21 12:34 sess_46c83b9ae5e506b8ceb6c37dc9a3f66e
-rw——- 1 nobody nobody 123 May 21 12:34 sess_9c57839c6c7a6ebd1cb45f7569d1ccfc

Unfortunately, it is pretty trivial to write a PHP script to read these files, and because it runs as the user nobody (or whatever user the web server uses), it has the necessary privileges.

The safe_mode directive can prevent this and similar safety concerns, but since it only applies to PHP, it doesn’t address the root cause of the problem. Attackers can simply use other languages.

What’s a better solution? Don’t use the same session store as everyone else. Preferably, store them in a database where the access credentials are unique to your account. To do this, simply use the session_set_save_handler() function to override PHP’s default session handling with your own PHP functions.

The following code shows a simplistic example for storing sessions in a database:

This requires an existing table named sessions, whose format is as follows:

mysql> DESCRIBE sessions;
| Field | Type | Null | Key | Default | Extra |
| id | varchar(32) | | PRI | | |
| access | int(10) unsigned | YES | | NULL | |
| data | text | YES | | NULL | |
This database can be created in MySQL with the following syntax:

id varchar(32) NOT NULL,
access int(10) unsigned,
data text,

Storing your sessions in a database places the trust in the security of your database. Recall the lessons learned when we spoke about databases and SQL, because they are applicable here.

Browsing the Filesystem

Just for fun, let’s look at a script that browses the filesystem:

The safe_mode directive can prevent this particular script, but what about one written in another language?

A good solution is to store sensitive data in a database and use the technique mentioned earlier (where $_SERVER[‘DB_USER’] and $_SERVER[‘DB_PASS’] contain the access credentials) to protect your database access credentials.

The best solution is to use a dedicated host.