WOR(L)DPRESS Best practice
TIPS AND TRICKS OF COMMON SENSE
Safety is the attention to detail.
#1 - SERVER
Behind every great man there stands a great woman.
Behind a secure website there is always a secure server!
- use iptables
- using SFTP
- use ModSecurity (apache module)
- backup server-side DB and Filesystem
- crontab script to check files and WP updates
-
system monitoring (Munin, Nagios)
#2 - VERSIONs
Show versions of the software
that you use is the first security flaw.
-
Apache
-
PHP
-
Wordpress
-
JS
#3 - FILEs 'n' DIRs
Apache:
<files wp-config.php>
order allow,deny
deny from all
</files>
wp-config.phpdefine('DISALLOW_FILE_EDIT', true);
Directories:
find /path/to/your/wordpress/install/ -type d -exec chmod 755 {} \;
Files:
find /path/to/your/wordpress/install/ -name 'wp-config.php' -exec chmod 440 {} \;
find /path/to/your/wordpress/install/ -type f -exec chmod 644 {} \;
#4 - Script
A crontab script can:
- remove the file: /wp-admin/install.php
-
check files permissions
-
check Wordpress/plugins updates
-
report changed files
Over 70% of the installations of WordPress
are vulnerable to lack of updates.
#5 - DATABASE
-
The table_prefix can be changed at will.
$table_prefix = 'wp_';
-
The port to connect to MySQL can be changed and managed during the connection as follows:
define('DB_HOST', 'localhost:1234');
-
The permission can be changed for a standard use:
CRUD rows (MySQL needs all privileges to update/install Wordpress and/or plugins.) -
To prevent the size of the DB grow out of proportion, it is good practice to import into your
wp-config as follows:
define('WP_POST_REVISIONS', 2); // any integer, but don't get too crazy // define('WP_POST_REVISIONS', false);
- You can trace the number of queries and the queries themselves and possibly control them and rewrite them if they need.
- it is good practice to use the cache of MySQL
#6 - Users
- It is good practice that there is no user "admin".
If it exists, you can create another administrator user and delete the old "admin" . -
Passwords must be complex to be safe
(there are tools that help to remind you) . -
The id of the user can be set to start numbering from a higher to be less easy to deduce.
- Managing user tables can be renamed and defined as follows:
define('CUSTOM_USER_TABLE', $table_prefix.'my_users');
define('CUSTOM_USER_META_TABLE', $table_prefix.'my_usermeta');
#7 - WP-ADMIN & SSL
Is or is not rename the folder a problem? Yes, it is!
Must be used .htpasswdWordpress supports SSL for wp-admin starting from version 3.5:
define('FORCE_SSL_ADMIN', true);
define('FORCE_SSL_LOGIN', true);
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
$_SERVER['HTTPS']='on';
Virtual host http:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)\ HTTP/ [NC]
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^/?(wp-admin/|wp-login\.php) https://mysite.com%{REQUEST_URI}%{QUERY_STRING} [R=301,QSA,L]
Virtual host https:RewriteRule !^/wp-admin/(.*) - [C]
RewriteRule ^/(.*) http://www.mysite.com/$1 [QSA,L]
#8 - wp Version
To not show the Wordpress version:
/* Remove links and version */
add_action('init', 'remheadlink');
function remheadlink() {
remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'wp_generator'); // remove wp versions
remove_action('wp_head', 'start_post_rel_link');
remove_action('wp_head', 'index_rel_link');
remove_action('wp_head', 'adjacent_posts_rel_link');
}
#9 - KEYS
Unique keys for identification
(If you change them you invalidate all existing cookies)
define('AUTH_KEY', '~*+7U?+I!{rmDXf8@Tre0%4_9vYB^z1W^$X}!|niFs#p*`Hxloj6!Vi-IUANSu&l');
define('SECURE_AUTH_KEY', '>)`fA[fW~)ra:nm<XLp`,$%y[:XHO$]M<X#.]tUh.&|DphKQtM2e3q6gO2+aVjF<');
define('LOGGED_IN_KEY', 'xw8ER`;Jgm{wJg2>i&A:kz:ya[-z+p SWVH{chgF-@kw$>_!5n*d7{a!{*XD$-!c');
define('NONCE_KEY', 'A}AO+49yjT!R|NsM,-<DU;O48Oom&9N7N/u+s)gwTnt).*8j`+Z6Xq|qUarKTJWe');
define('AUTH_SALT', '|.aIOi}+v;A5[v/Wg?`}ZH|V6gVcFmpP(I)QX4]PT|s)W5#n~5+YdSNDsBMnGi+j');
define('SECURE_AUTH_SALT', 'Fi:M(D!`O$=xC(w>d7D>*!H`I>lT,|p%l{s?P2&1OvMk_h9#GknHOMYA{n-NOsV=');
define('LOGGED_IN_SALT', 'rn5%)xQQ(/v,+8:;_]i1f|M<&HtV}Xa4v<y,dUyR&3xeg-0YKyzssb`k!Djo{wW(');
define('NONCE_SALT', 'h+QSsR{yBoS&/xo~hoxD8O}k5OTx|T3j7HFVcdZvB(Hy],dm&TN/%tonO}6HyDqF');
https://api.wordpress.org/secret-key/1.1/salt/
#10 - CACHE
Server side:
Varnish
Wordpress side:
WP Super Cache
W3 Total Cache
THe END
Manuel Kanah
manuel@kanah.it
skype: testinaweb
my_wp: http://www.labna.it
http://slides.com/testinaweb/wordpress-best-practice
Special thanks:
Wordpress, Gabriele Giuranno, Francesco Lentini, Diane
Wor(l)dPress best practice
By Manuel Kanah
Wor(l)dPress best practice
- 1,616