{"id":458,"date":"2011-08-25T19:47:29","date_gmt":"2011-08-26T02:47:29","guid":{"rendered":"http:\/\/www.analogrithems.com\/rant\/?p=458"},"modified":"2011-08-29T15:10:13","modified_gmt":"2011-08-29T22:10:13","slug":"wordpress-security-tips-and-tricks","status":"publish","type":"post","link":"https:\/\/www.analogrithems.com\/rant\/wordpress-security-tips-and-tricks\/","title":{"rendered":"WordPress Security Tips and Tricks"},"content":{"rendered":"<h1 style=\"text-align: center;\">Everybody Plays Guitar, few play well!<\/h1>\n<p>WordPress or WP as I call it went viral long ago, with 54% or all CMS systems using WP\u00c2\u00a0it&#8217;s obvious it&#8217;s not a fad. \u00c2\u00a0But with that many people using the code, you also have lots of people now vulnerable to a whole slew of attacks. \u00c2\u00a0Because WordPress is so easy to use, many people create quick blogs without putting very much time into thinking about security.<\/p>\n<p>This is true not only of the people setting up the WP sites but also the people creating plugins and themes. \u00c2\u00a0As I look through WP plugins I see more than 50% of the code had no security accounted for. \u00c2\u00a0 I hope to point out several of those security issues as well as better prepare you for deploying your own WP site.<\/p>\n<h2>Server Setup Tips<\/h2>\n<p>First off before you can even think about setting up a secure WP Site, you have to have a secure webserver. Believe it or not it really doesn&#8217;t matter all that much if you use Apache or IIS7.0. \u00c2\u00a0I hate to say it, but don&#8217;t\u00c2\u00a0congratulate\u00c2\u00a0Microsoft on this\u00c2\u00a0accomplishment. \u00c2\u00a0It&#8217;s really the PHP dev team who made PHP a solid product on IIS. \u00c2\u00a0For this article though we will be focusing on Apache + PHP.<\/p>\n<p>If you are going to be running multiple WP instances controlled by different people then you really want to look into using something like suExec or suPHP. \u00c2\u00a0These modules allow you to run the php script as the user who owns the file. \u00c2\u00a0This is a big security feature as typically any script that is run is run as the webserver. \u00c2\u00a0This means any script could in theory hurt any other script that is running since their is no seperation (aside from processes). \u00c2\u00a0Also in order to make it accessible by Apache and your customers the script would have to have more relaxed file permissions.<\/p>\n<p><a href=\"http:\/\/httpd.apache.org\/docs\/2.0\/suexec.html\">suExec<\/a> and <a href=\"http:\/\/www.suphp.org\/\">suPHP<\/a> fix this by running your script as the person who owns the script. \u00c2\u00a0Think of this as a little sandbox to separate your various WordPress Instances. \u00c2\u00a0When a user ftp\/sftp into your server to upload files to your server, those files will run as the user who uploads them. \u00c2\u00a0It also makes it perfectly acceptable to tell your ssh &amp; sftp server to lock the users into their home directories to prevent them from playing dangerous on your server.<\/p>\n<p>Note though, this doesn&#8217;t really work for you if you are using <a href=\"http:\/\/codex.wordpress.org\/Create_A_Network\">WordPress Multiuser<\/a>. \u00c2\u00a0This is because WordPress Multi-User all runs as a single WP instance (everything as one user). \u00c2\u00a0When deciding if you want to run WP Multiuser or multiple instances of WP you should think about the logical separation of who it&#8217;s for. \u00c2\u00a0If you need multiple sites for the same company, then use WP Multiuser. \u00c2\u00a0If you are looking to go more of a shared hosting route then you should really use multiple instances of WP as this is safer for your customers.<\/p>\n<h2>php.ini<\/h2>\n<p>The php.ini holds a lot of power in PHP. \u00c2\u00a0It also hold the most power when it comes to security. \u00c2\u00a0This is the place where you should make the big changes. \u00c2\u00a0 Such as&#8230;.<\/p>\n<ul>\n<li>Disable register_globals! \u00c2\u00a0This is a nightmare waiting to happen. \u00c2\u00a0Register globals means that anything that comes in via GET or POST (or any other method) become global variables. \u00c2\u00a0Hackers could use this to overwrite your program logic. \u00c2\u00a0It&#8217;s a very bad option.<\/li>\n<li>Enable safe_mode. \u00c2\u00a0 This setting tells php to restrict access to non webserver files.<\/li>\n<li>Disable display_errors. \u00c2\u00a0This prevents would be attackers from gathering information about your system if a coding error arises.<\/li>\n<\/ul>\n<h2>.htaccess<\/h2>\n<p>.htaccess is an amazing little feature of apache that allows you to control several apache runtime configurations. \u00c2\u00a0This is a great way to restrict access to certain folders in your site. \u00c2\u00a0For example you can lock your wp-admin directory to only be accessed by specific ip address with something like the following.<\/p>\n<pre>order deny,allow\r\ndeny from all\r\nallow from xxx.xx.xx.xxx<\/pre>\n<p>You can also use the .htaccess to disable register_globals if you dont have control over the php.ini file by placing\u00c2\u00a0<em>php_flag register_globals off<\/em>\u00c2\u00a0 in your .htaccess file<\/p>\n<h2>File Permissions<\/h2>\n<p>Many people have asked me what the file permissions are supposed to be for WP. \u00c2\u00a0Before I give my recommendation I want to explain some things you need to consider. \u00c2\u00a0Unless you are using suExec or suPHP \u00c2\u00a0your WP is running as the webserver user. \u00c2\u00a0This means that if you have a script that uploads files for edits files (like WP) then the webserver needs to have access to write to your files. \u00c2\u00a0Now most of the items in WP that get modified exists under the <strong>wp-content<\/strong>\u00c2\u00a0directory. \u00c2\u00a0So in my opinion I would make all the files owned by either root or the user who manages the WP files. \u00c2\u00a0Then set the wordpress permissions with the following command.<\/p>\n<p><strong>chmod -R 655 wordpress<\/strong><\/p>\n<p>After this we must modify the <strong>wp-content<\/strong>\u00c2\u00a0subdirectory permissions. (Note: If you are using suExec or suPHP the previous permissions are enough, skip the rest.)<\/p>\n<p>If you have root access set the group permissions of the files to the webserver group.<\/p>\n<pre>chgrp -R apache wp-content\r\nchmod -R 775 wp-content<\/pre>\n<p>If you don&#8217;t have the ability to set the permissions to the webserver group then do the following with extreme caution.<\/p>\n<pre>chmod -R 777 wp-content<\/pre>\n<p>I must point out that setting any directory in your web path to 777 is a security risk. \u00c2\u00a0At those permissions any files within are a free for all. \u00c2\u00a0If you don&#8217;t find giving your ftp password everytime you make a change you could also leave those permissions at 777 and just put in your ftp username and password each time you need to upload plugins for themes.<\/p>\n<h2>mod_security<\/h2>\n<p>By far one of the most successful web security tools no matter what application you are running is <a href=\"http:\/\/www.modsecurity.org\/\">mod_security<\/a>. \u00c2\u00a0I can&#8217;t stress how amazing this Apache module is (I believe it has an IOIS version also) \u00c2\u00a0This module basically works as a firewall for your webserver. \u00c2\u00a0It actually inspects every request that comes into your server and searches for potential attacks in the request. \u00c2\u00a0It has a very high detection rate (sometimes to high). \u00c2\u00a0I can say for sure that this tool has saved some of the larger web sites I&#8217;ve run.<\/p>\n<p>It has several version including an opensource community edition. \u00c2\u00a0USE THIS!<\/p>\n<h2>Patching<\/h2>\n<p>Always stay up to date on your system patches. \u00c2\u00a0This is critical, don&#8217;t let your WP get compromised from your operating system or it&#8217;s applications (IE. apache, mysql, ssh etc)<\/p>\n<p>Also make sure to keep your WordPress install current. \u00c2\u00a0When you see the update notice, follow it and run the update.<\/p>\n<h2>Backups<\/h2>\n<p>The one thing I&#8217;ve seen was looked over by every site I&#8217;ve been called into repair, is they didn&#8217;t do proper backups. \u00c2\u00a0This can and will save you SO much money. \u00c2\u00a0It will also help you get your site back online faster. \u00c2\u00a0Make sure that you backup both your database and your actual files.<\/p>\n<h2>WordPress Changes<\/h2>\n<p>Once you have a secure server setup, then you need to really take the time to lock down Wp from the inside. \u00c2\u00a0The following are the tips I follow.<\/p>\n<ul>\n<li>Change the admin username. \u00c2\u00a0By default WordPress likes to use the username <strong>admin<\/strong>\u00c2\u00a0this makes it easy for people to brute force your blog so change it!<\/li>\n<li>Use permalinks to hide url details like post id&#8217;s.<\/li>\n<li>Set the permissions of the wp-config.php so it is is only readable by the webserver user and the owner. \u00c2\u00a0Remember this file has your database password in it.<\/li>\n<\/ul>\n<h2>WordPress Security Plugins (That Work with current!)<\/h2>\n<p>Security in WP can also be increased by certain plugins. \u00c2\u00a0Here is a great list of plugins to help.<\/p>\n<ul>\n<li><a href=\"http:\/\/wordpress.org\/extend\/plugins\/limit-login-attempts\/\">Limit Login Attempts<\/a>\u00c2\u00a0This plugin can be used to prevent people from brute forcing your blog by limiting the number of login attempts.<\/li>\n<li><a href=\"http:\/\/wordpress.org\/extend\/plugins\/mute-screamer\/\">Mute Screamer<\/a>\u00c2\u00a0This plugin is basically an IDS for WP. \u00c2\u00a0It monitors traffic and logs abnormal traffic. \u00c2\u00a0It can even email you when it detects an attack<\/li>\n<li><a href=\"http:\/\/wordpress.org\/extend\/plugins\/bulletproof-security\/screenshots\/\">Bulletproof Security<\/a>\u00c2\u00a0This is a well designed slightly complicated plugin for wordpress that implements most of what I&#8217;ve discussed here for you. \u00c2\u00a0It has a free and pro version. \u00c2\u00a0It takes a bit of reading, testing and tuning but this plugin does a pretty good job.<\/li>\n<\/ul>\n<h1>Coding Tips for Plugins &amp; Themes<\/h1>\n<p>The biggest problem with the Security of WP is not the core code, but the plugins and themes. \u00c2\u00a0As a plugin or theme author you should know about these api functions by heart <a href=\"https:\/\/codex.wordpress.org\/Data_Validation\">https:\/\/codex.wordpress.org\/Data_Validation<\/a>\u00c2\u00a0\u00c2\u00a0These functions are the data validation functions. \u00c2\u00a0They are how you test to make sure that the data coming from the user is safe to use. \u00c2\u00a0Lack of input validation is responsible for most security bugs like cross site scripting (XSS) or SQL Injections.<\/p>\n<p>Below are my personal coding tips for making secure plugins and themes.<\/p>\n<ul>\n<li>Dont leave those comments in the output. \u00c2\u00a0often times as developers we will place html style comments in the output with print_r or backtrace statements in them. \u00c2\u00a0This gives up too much information about your program.<\/li>\n<li>Any SQL statement you make that uses a variable should use the <strong>$wpdb-&gt;prepare<\/strong>\u00c2\u00a0function. \u00c2\u00a0See <a href=\"http:\/\/codex.wordpress.org\/Class_Reference\/wpdb\">wpdb codex<\/a><\/li>\n<li>Before you use any variable test it and escape it! \u00c2\u00a0What this means is if you expect to have a variable passed to you make sure it&#8217;s usable and safe. \u00c2\u00a0For example in the following code notice the use of the <strong>isset<\/strong>, <strong>!empty<\/strong>\u00c2\u00a0and <strong>esc_html<\/strong>\u00c2\u00a0calls\n<pre>function printWelcom($name = false){\r\n\r\n     if(isset($name) &amp;&amp; !empty($name)){\r\n          print \"Hello \".esc_html($name).\" welcome back!\";\r\n     }\r\n}<\/pre>\n<p>This serves many purposes, first it makes sure that you will never receive those pesky notices in your php log about <strong>PHP Notice: Undefined index: name in<\/strong>. It also makes sure you didn&#8217;t make a typo in variable name. Finally notice the use of the <strong>esc_html<\/strong>\u00c2\u00a0function. \u00c2\u00a0This is one of those input validation functions discussed above. \u00c2\u00a0It makes sure that what ever they send doesn&#8217;t contain malicious code the could cause a XSS attack.<\/li>\n<li>Try to avoid using PHP&#8217;s <strong>eval<\/strong>\u00c2\u00a0function. \u00c2\u00a0Especially if you are passing a variable to it. \u00c2\u00a0These are hackers favorite things to abuse. \u00c2\u00a0Because they can load their own code into a string and get it executed.<\/li>\n<li>Declare all variables and set them to false before you use them. \u00c2\u00a0This prevents hackers from abusing magic_quotes<\/li>\n<li>Any form that you use should implement the <a href=\"http:\/\/codex.wordpress.org\/WordPress_Nonces\">WordPress nounce<\/a>. \u00c2\u00a0Also when you process the request make sure you verify the nounce. \u00c2\u00a0Nounces are security precautions that WP uses to make sure page request aren&#8217;t being forged (Or at least making it more difficult to forge).<\/li>\n<li>Place .htaccess files in your plugin and theme directories that limit access to the files directly. The following example is one I use in by wp-content directory.\n<pre>Order Allow,Deny\r\nDeny from all\r\n&lt;Files ~ \"\\.(css|jpe?g|png|gif|js)$\"&gt;\r\n Allow from all\r\n&lt;\/Files&gt;<\/pre>\n<p>In this example only javascript, css and images are allowed. This will prevent people from directly calling any php scripts.<\/li>\n<\/ul>\n<p>If you have a security recommendation. Place it in the comments below. If you are confused about one of the recommendations, let me know and I&#8217;ll break it down more for you.<\/p>\n<p>See Also<\/p>\n<p><a href=\"http:\/\/codex.wordpress.org\/Hardening_WordPress\">http:\/\/aymanh.com\/checklist-for-securing-php-configuration<\/a><\/p>\n<p><a href=\"http:\/\/codex.wordpress.org\/Hardening_WordPress\">http:\/\/codex.wordpress.org\/Hardening_WordPress<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Everybody Plays Guitar, few play well! WordPress or WP as I call it went viral long ago, with 54% or all CMS systems using WP\u00c2\u00a0it&#8217;s obvious it&#8217;s not a fad. \u00c2\u00a0But with that many people using the code, you also have lots of people now vulnerable to a whole slew of attacks. \u00c2\u00a0Because WordPress is [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[44,40,43,22,21],"tags":[],"class_list":["post-458","post","type-post","status-publish","format-standard","hentry","category-featured","category-web-development","category-web-security","category-wordpress","category-wordpress-ecommerce"],"_links":{"self":[{"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/posts\/458","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/comments?post=458"}],"version-history":[{"count":13,"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/posts\/458\/revisions"}],"predecessor-version":[{"id":491,"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/posts\/458\/revisions\/491"}],"wp:attachment":[{"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/media?parent=458"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/categories?post=458"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.analogrithems.com\/rant\/wp-json\/wp\/v2\/tags?post=458"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}