Optimization and security / CMS WordPress
Tags: Audit WordPress, optimization, security, seo, websites, WordPress
iREBU Agencja Interaktywa / Studio graficzne
Autor: Maciej Skrzypczak
Specjalista Wordpress / Programowanie / Projekty graficzne / Wydruk
I. Data backup
Before I start working, first I make a copy of the website.
- BackUpWordPress.
II. Updating CMS WordPress and add-ons
The first step of optimization is to update the system and add-ons to the latest version. It’s crucial, because from time to time authors fix bugs, solve security issues, increase speed or add new interesting functions.
III. Optimizing load speed
Websites installed on WordPress often load slowly, especially in the evenings, when hosts are the most loaded. First, I change PHP version on server to 7 and disable unnecessary plugins. Then, I install a plugin that buffers PHP code, which makes dynamic pages load in a static form, and reduces the weight of website code and images. It’s also useful to configure the website for global CDN cloudflare.com, so that the website will be downloaded from a localization closest to the user.
- P3 Plugin Performance Profiler, analysis and deactivating redundant add-ons,
- W3 Total Cache, WP Super Cache, LiteSpeed Cache, PHP code buffering,
- Autoptimize, website code reduction,
- Jetpack z WordPress.com / Photon, pictures optimization, compression and integration with CDN WordPress,
- .htaccess optimization, modifying buffering time of the code by the browser, code compression for the browser:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule \.(php|html|htm|css|js|ico|jpg|jpeg|png|gif|swf|json|txt|eot|woff|woff2|ttf|svg)$ empty [R=404,L]
<FilesMatch "\.(css|js|ico|jpg|jpeg|png|gif|swf|xml|json|txt|eot|woff|woff2|ttf|svg|pdf|doc|xls)$">
RequestHeader unset Cookie
Header unset Set-Cookie
Header unset Cookie
</FilesMatch>
<IfModule mod_expires.c>
FileETag MTime
ExpiresActive on
ExpiresDefault "access plus 28 days"
ExpiresByType text/html "access plus 3 hours"
ExpiresByType application/json "access plus 3 hours"
ExpiresByType text/xml "access plus 3 hours"
ExpiresByType application/xml+rss "access plus 3 hours"
ExpiresByType text/css "access plus 7 days"
ExpiresByType text/javascript "access plus 14 days"
ExpiresByType application/x-javascript "access plus 14 days"
ExpiresByType application/javascript "access plus 14 days"
ExpiresByType text/plain "access plus 28 days"
ExpiresByType image/x-icon "access plus 28 days"
ExpiresByType image/jpeg "access plus 28 days"
ExpiresByType image/png "access plus 28 days"
ExpiresByType image/gif "access plus 28 days"
ExpiresByType application/x-shockwave-flash "access plus 28 days"
ExpiresByType application/x-font-ttf "access plus 1 years"
ExpiresByType application/x-font-opentype "access plus 1 years"
ExpiresByType application/x-font-woff "access plus 1 years"
ExpiresByType application/x-font-woff2 "access plus 1 years"
ExpiresByType application/vnd.ms-fontobject "access plus 1 years"
ExpiresByType image/svg+xml "access plus 1 years"
ExpiresByType text/x-component "access plus 1 years"
</IfModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE application/json
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE application/xml+rss
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-shockwave-flash
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/x-font-opentype
AddOutputFilterByType DEFLATE application/x-font-woff
AddOutputFilterByType DEFLATE application/x-font-woff2
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE text/x-component
# Remove browser bugs (only needed for really old browsers)
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
Header append Vary User-Agent
</IfModule>
- wp-config.php optimization, modification of cron task calling time:
define('WP_CRON_LOCK_TIMEOUT', 600);
IV. Database optimization
I empty the recycle bin, automatic drafts, spam and old data, optimize database tables. What takes up most space is entries versions, that’s why it’s a good practice to limit their number to 100.
- WP-Optimize,
- wp-config.php optimization, modification of the frequency of auto-saving entries and limiting the number of versions:
define('AUTOSAVE_INTERVAL',3600);
define('WP_POST_REVISIONS',100);
V. Security
First of all, when installing WordPress, you should give a database name other than default. Also, you shouldn’t use a default login for administrator name, like “admin” or “administrator”. If you post on a website, you shouldn’t use administrator’s account for posting articles or commenting, and a nickname should be other than the user’s name. This way you will avoid many attacks that will attempt to get your password by brute force.
- Wordfence Security, protection against basic attacks and viruses,
- Loginizer, login protection / anti brute force,
- PHP security:
function sr_security() {
global $user_ID;
if ($user_ID) {
if ( !current_user_can('manage_options') ) {
if (strlen($_SERVER['REQUEST_URI']) > 255 ||
stripos($_SERVER['REQUEST_URI'], "eval(") ||
stripos($_SERVER['REQUEST_URI'], "CONCAT") ||
stripos($_SERVER['REQUEST_URI'], "UNION+SELECT") ||
stripos($_SERVER['REQUEST_URI'], "base64")) {
if (!headers_sent()) {
header("HTTP/1.1 414 Request-URI Too Long");
header("Status: 414 Request-URI Too Long");
header("Connection: Close");
}
exit;
}
}
}
}
add_action( 'init', 'sr_security' );
- .htaccess security, blocking author search, 5G BLACKLIST/FIREWALL:
RewriteCond %{QUERY_STRING} author=
RewriteRule .* empty [R=404,L]
# 5G BLACKLIST/FIREWALL
# @ http://perishablepress.com/5g-blacklist/
# 5G:[QUERY STRINGS]
<ifModule mod_rewrite.c>
RewriteCond %{QUERY_STRING} (environ|localhost|mosconfig|scanner) [NC,OR]
RewriteCond %{QUERY_STRING} (mod)\=\.?/? [NC,OR]
RewriteCond %{QUERY_STRING} boot\.ini [NC,OR]
RewriteCond %{QUERY_STRING} echo.*kae [NC,OR]
RewriteCond %{QUERY_STRING} etc/passwd [NC,OR]
RewriteCond %{QUERY_STRING} \=\\%27$ [NC,OR]
RewriteCond %{QUERY_STRING} \=\\\'$ [NC,OR]
RewriteCond %{QUERY_STRING} \.\./ [NC,OR]
RewriteCond %{QUERY_STRING} \? [NC]
RewriteRule .* - [F]
</ifModule>
# 5G:[USER AGENTS]
<ifModule mod_setenvif.c>
SetEnvIfNoCase User-Agent (casper|cmsworldmap|diavol|dotbot) keep_out
SetEnvIfNoCase User-Agent (flicky|ia_archiver|jakarta|kmccrew) keep_out
SetEnvIfNoCase User-Agent (libwww|planetwork|pycurl|skygrid) keep_out
SetEnvIfNoCase User-Agent (purebot|comodo|feedfinder|turnit) keep_out
SetEnvIfNoCase User-Agent (zmeu|nutch|vikspider|binlar|sucker) keep_out
<limit GET POST PUT>
Order Allow,Deny
Allow from all
Deny from env=keep_out
</limit>
</ifModule>
# 5G:[REQUEST STRINGS]
<ifModule mod_alias.c>
RedirectMatch 403 (https?|ftp|php)\://
RedirectMatch 403 /(cgi|https?|ima|ucp)/
RedirectMatch 403 /(Permanent|Better)$
RedirectMatch 403 (\=\\\'|\=\\%27|/\\\'/?|\)\.css\()$
RedirectMatch 403 \.(cgi|asp|aspx|cfg|dll|exe|jsp|mdb|sql|ini|rar)$
RedirectMatch 403 /(contac|fpw|install|pingserver|register)\.php$
RedirectMatch 403 (base64|crossdomain|localhost|wwwroot|e107\_)
RedirectMatch 403 (eval\(|\_vti\_|\(null\)|echo.*kae|config\.xml)
RedirectMatch 403 \.well\-known/host\-meta
RedirectMatch 403 /function\.array\-rand
RedirectMatch 403 \)\;\$\(this\)\.html\(
RedirectMatch 403 proc/self/environ
RedirectMatch 403 msnbot\.htm\)\.\_
RedirectMatch 403 /ref\.outcontrol
RedirectMatch 403 com\_cropimage
RedirectMatch 403 indonesia\.htm
RedirectMatch 403 \{\$itemURL\}
RedirectMatch 403 function\(\)
RedirectMatch 403 labels\.rdf
RedirectMatch 403 /playing.php
RedirectMatch 403 muieblackcat
</ifModule>
# 5G:[BAD IPS]
<limit GET POST PUT>
Order Allow,Deny
Allow from all
# uncomment/edit/repeat next line to block IPs
# Deny from 123.456.789
</limit>
# 5G:[WordPress]
<ifModule mod_rewrite.c>
RedirectMatch 403 /\$\&
RedirectMatch 403 (?i)/\&(t|title)=
RedirectMatch 403 (?i)/\.(bash|git|hg|log|svn|swp|tar)
RedirectMatch 403 (?i)/(1|contact|i|index1|iprober|phpinfo|phpspy|product|signup|t|test|tz|visit|webshell|wp-signup).php
RedirectMatch 403 (?i)/(author-panel|class|database|manage|phpMyAdmin|register|submit-articles|system|usage|webmaster)/?$
RedirectMatch 403 (?i)/(=|_mm|cgi|cvs|dbscripts|jsp|rnd|userfiles)
</ifModule>
- wp-config.php security, disabling file editing in WordPress:
define('DISALLOW_FILE_EDIT',true);
WordPress is often used as SEO catalogue, so every user is a potential target of spammer attack. You shouldn’t leave any forms unsecured, otherwise you will be bombarded with tons of automatically generated comments and e-mails.
- Akismet, protection against spam,
- security a form:
.DISABLE{display:none}
<input name="sr-code" value="ąćęłńóśżź" type="hidden" />
<input class="DISABLE" name="submit" value="spam" type="submit" />
<input name="submit" value="Wyślij" type="submit" />
if (($_POST['submit']==='spam') || ($_POST['sr-code']!=='ąćęłńóśżź')) die();