Difference between revisions of "WordPress"
Line 1: | Line 1: | ||
− | + | WordPress is popular, feature-rich and useful, despite the awful spaghetti state of its PHP code. Luckily we can lock it all down pretty well as follows. | |
+ | |||
+ | == Allow user-installed plugin and themes == | ||
+ | |||
+ | If you're game, you can enable WordPress users with admin access to install their own plugins and themes by allowing write access to wp-content/{plugins,themes} and configuring as follows: | ||
# in wp-config.php | # in wp-config.php | ||
define('FS_METHOD', 'direct'); | define('FS_METHOD', 'direct'); | ||
+ | |||
+ | The obvious disadvantage to this approach is you lose control of what god-awful unaudited third-party code they might install. | ||
== WP CLI == | == WP CLI == |
Revision as of 04:42, 20 August 2021
WordPress is popular, feature-rich and useful, despite the awful spaghetti state of its PHP code. Luckily we can lock it all down pretty well as follows.
Allow user-installed plugin and themes
If you're game, you can enable WordPress users with admin access to install their own plugins and themes by allowing write access to wp-content/{plugins,themes} and configuring as follows:
# in wp-config.php define('FS_METHOD', 'direct');
The obvious disadvantage to this approach is you lose control of what god-awful unaudited third-party code they might install.
WP CLI
Use wp-cli, a really useful tool for managing WordPress sites from the command line. Once downloaded you can keep it updated with:
wp cli update
Use SSL
Use Letsencrypt to enforce HTTPS everywhere and dehydrated to maintain the SSL certificate, and use the latest Mozilla SSL Guideline from their configurator to set up strong SSL.
Content security
Use a content security policy. There is a plugin for managing one from within WordPress, but it is straightforward to cobble one and add it to the headers. Here's an example content security policy that allows JavaScript, images and CSS from only certain origins, and denies everything else:
Header always set Content-Security-Policy "base-uri 'self'; default-src 'none'; media-src 'self'; connect-src 'self' https://*.wp.com wss://public-api.wordpress.com https://api.stripe.com https://checkout.stripe.com; font-src 'self' data: https://*.wp.com https://wordpress.com https://fonts.googleapis.com https://fonts.gstatic.com; form-action 'self'; frame-ancestors 'self'; frame-src 'self' https://jetpack.wordpress.com https://*.wp.com https://www.google.com https://*.stripe.com https://player.vimeo.com https://www.youtube.com https://www.surveymonkey.com; img-src 'self' data: https://*.tile.openstreetmap.org https://*.gravatar.com https://*.wp.com https://*.wordpress.com https://s.w.org https://maps.googleapis.com https://maps.gstatic.com https://q.stripe.com https://secure.surveymonkey.com; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://widget.surveymonkey.com https://*.wp.com https://public-api.wordpress.com https://*.stripe.com https://maps.googleapis.com https://ajax.googleapis.com; style-src 'self' 'unsafe-inline' https://*.wp.com https://ajax.googleapis.com https://fonts.googleapis.com;"
Other headers can be used to further enforce some secure behaviour:
Header always set X-Content-Type-Options "nosniff" Header always set X-XSS-Protection "1; mode=block" Header always set Referrer-Policy "strict-origin-when-cross-origin" Header always set Access-Control-Allow-Origin "*"
- gzip + WP SuperCache = win
Some more security hardening
There's a lot of written material out there. but for a start, as suggested by WPScan, prevent DDoS attacks on web-accessible cron and XMLRPC endpoints, but allow CLI invocation, and prevent execution of uploaded PHP content:
<Files "xmlrpc.php"> Require ip 127 </Files> <Files "wp-cron.php"> Require ip 127 </Files> RedirectMatch 404 "/readme\.html" <Location "/wp-content/uploads"> SetHandler none RedirectMatch 404 ".+\.php" </Location>