A recent retweet by Jeremiah Grossman got me thinking. Why doesn’t WordPress implement privilege separation in their blog engine? After all it is fairly simple and can be implemented in a few lines of code.
I don’t know the reason to be honest, as this is one of the basic rules of security. Few months ago I did it for my blog, since I don’t see a valid reason why anyone coming across the Internet needs to have “drop table” privilege or similar on my blog’s database. I looked around for a convenient mailing list to post my idea to and unfortunately I couldn’t find one, so I gave up on trying to message the idea directly to WordPress developers, but now I’ve decided to at least post it for people to take advantage of it.
Here is what I have done that should give you basic level of privilege separation with just a simple WordPress tweak.
First, you need to have the two separate database users - admin and public. We also need to assign the proper privileges/permissions (after all this is the main idea):
public -> db: [SELECT,INSERT]
admin -> db: [SELECT,INSERT,UPDATE,CREATE,DELETE,ALTER,DROP,INDEX,CREATE TEMPORARY TABLES,LOCK TABLES,CREATE VIEW,SHOW VIEW]
Since I have comments enabled, I had to give the public user the INSERT privilege, but at least I have taken away the 10 extra privs away from it. If you don’t allow comments on the blog, you can even remove the INSERT functionality, though I haven’t tested this one and don’t know if anything else would break.
The only other thing left to do is configure WordPress to pick the right database user. This is accomplished easily through wp-config.php:
if ( defined('WP_ADMIN') || defined('DOING_CRON') ) { define('DB_USER', 'admin'); define('DB_PASSWORD', 'admin_password'); } else { define('DB_USER', 'public'); define('DB_PASSWORD', 'public_password'); }
I’ve only had this customization interfere once in my almost half year since I’ve implemented it. It was during WordPress upgrade, which required a change to the database schema. In such cases, it is trivial to restore back to the default behavior for the duration of the upgrade and then go back to separate users.
I hope this helps people reduce some of the attack surface on their blogs and ideally WordPress will do this natively in the future.