WP Contact Form Security

There are a couple of aspects to the security of my Contact Kenny page.

WP Contact Form Security

  1. Protecting my visitors: I need to make sure the data my visitors enter on my contact form is safe and not intercepted in transit. Just as important – or perhaps even more important – my visitors must have confidence that their data is safe and will not be intercepted in transit.
  2. Protecting me: I really effing hate contact form spam. Actually, I really effing hate all spam, but I’ve kinda gotten used to a certain amount of email and certain other spam being inevitable. But not contact form spam. I want exactly zero contact form spam.

#1 is pretty straightforward. SSL solves the problem. And SSL is now free and relatively easy provided that my hosting provider offers Let’s Encrypt. If my hosting provider does not offer Let’s Encrypt – time to switch hosting providers. Which I did. Sorry LunarPages. You were otherwise a solid host – which is why I stayed with you for roughly a decade and a half – but Let’s Encrypt became essential.

#2 is a little trickier. Most WP contact form plugins support recaptcha and/or a honeypot. Or I could use a CloudFlare page rule to turn on ‘Browser Integrity Check’ and set the security level to ‘I’m Under Attack’. Any one of these measures will stop the vast majority of spam bots – but a few extra-smart bots will still slip through. Any two of these measures, working together, will stop all bots. ‘All’ is probably an exaggeration, but I have never seen a bot slip through when I use two separate bot stoppers.

Update: Drat, I spoke too soon. It doesn’t happen much, but maybe once every couple of days a spam bot will slip through both my CloudFlare page rule and honeypot to kindly inform me about sexy singles in my area.

Honeypot

I was using both a recaptcha and a honeypot, but a plugin update at some point broke my recaptcha. So, I switched to a CloudFlare page rule paired with a honeypot. This method has the huge advantage of blocking the vast majority of bots at the reverse proxy level – keeping them completely off my site. It has the huge disadvantage of using up one of my three precious page rules.

To free up a page rule for contact form bot-blocking, I reluctantly gave up my ‘Cache Everything’ page rule. My sites are still speedy since I use a quality host and the excellent LiteSpeed cache. Also CloudFlare by default still globally caches images, CSS, and JavaScript – just not html. Site speed decreased by only about 2% in North America, but about 10% in Europe and Asia. For me, that’s a small price to pay for my obsessive hatred of spam bots.

2FA

Two factor authentication (2FA) is an extremely strong security measure to keep bad guys, gals, and bots from hacking into my important accounts – WP admin, email, registrar, cPanel, and so on. And … I’m just not a fan.

2fa

That’s not to say I don’t use it. I use 2FA quite a bit, but only when other, more convenient security measures are not available. A bit of background on 2FA, courtesy of Wikipedia

Multi-factor authentication (MFA) is a method of confirming a user’s claimed identity in which a computer user is granted access only after successfully presenting two or more pieces of evidence (or factors) to an authentication mechanism: knowledge (something the user and only the user knows), possession (something the user and only the user has), and inherence (something the user and only the user is).

Two-factor authentication (also known as 2FA) is a type, or subset, of multi-factor authentication. It is a method of confirming users’ claimed identities by using a combination of two different factors: 1) something they know, 2) something they have, or 3) something they are.

A good example of two-factor authentication is the withdrawing of money from an ATM; only the correct combination of a bank card (something that the user possesses) and a PIN (something that the user knows) allows the transaction to be carried out.

In short, 2FA provides awesome security, as good as it gets for WP and other online logins. And I’m a big proponent of WP security, so I should absolutely love 2FA. But, we just haven’t bonded. Maybe it’s a cultural thing. I just don’t like that it depends on me always having my cell phone handy.

I’ve lost my cell phone twice in the past. First time, my phone popped off my day-pack while climbing the cables on Yosemite’s Half Dome, and fell roughly 5,000 feet to its doom. I’m still thankful I wasn’t on a call with my wife at the time. Second time – just being a dunderhead – left it behind when I exited a train. I also sometimes leave it at home when at work, or vice versa. I’m reliant on 2FA now, so I’m more careful with my phone. Still, no guarantee it will never be lost or stolen.

So, I wish all the accounts that are important to my WP security – admin login, cPanel, email, CloudFlare, host, registrar – provided security mechanisms less reliant on me not losing my phone. But not all do. So, gotta go 2FA. Still not a fan though.

A couple of lessons I learned the hard way …

  • If I use Google Authenticator – which I do – I will get a QR image to scan during the sign-up process. I need to remember to  ***Save the image!*** Save it somewhere safe – encrypted maybe – but save it. I may very well need it later and I can’t find any way to regenerate it.
  • Install WinAuth on one or more laptops or PCs. So, if I leave my phone at work, I can still authenticate.

cPanel and FTP security

I take numerous precautions to prevent malicious logins to my WP admin account. None of which will do me a bit of good if my cPanel or FTP accounts get hacked. I don’t even use FTP. On those infrequent occasions when I need to transfer files, I use my cPanel file manager. I would disable FTP completely – except that I can’t find a way to do it. I also can’t find a way to obfuscate cPanel or FTP login, add a reCaptcha, limit login attempts, or add a security question.

I don’t get it. There are so many ways to secure my WP login, but my cPanel and FTP hack vectors lie relatively naked.  I can restrict both to SSL access, and that is helpful. And of course I use non-obvious user names and strong passwords. I can use two-factor authentication to secure cPanel, but I’m not a huge fan – I worry about my cell phone being lost, stolen, or broken.

My WP login can be super-duper-secure, but if my cPanel gets hacked – game over. All I want is one more simple thing I can do to secure cPanel and FTP – a security question, a reCaptcha, an obfuscated url, a way to limit login attempts … pretty much anything. It seems to me everyone would want this. But not only can I not find one, I can’t even find much discussion about it. Again, I don’t get it.

 

So, here’s my imperfect solutions. I delete the DNS record for FTP. That won’t disable FTP completely – a determined hacker could still try to get in if he or she learns my IP address or server name – but it makes it harder, and I worry a lot more about bad bots than determined human hackers.  My cPanel has a DNS record too, but deleting it seems to have no effect – I’m not sure why. With cPanel, I gotta use two-factor authentication – the only way I’ve found to increase security.

Danger, Will Robinson!

I use CloudFlare page rules to keep bad bots completely off my login screen and admin area. And they have always done a great job. Until recently. Now – Danger, Will Robinson! – bad bots are waltzing merrily past my precautions and attempting to login, or creating bogus subscriber accounts.

Danger, Will Robinson!

The bad bot battle is kinda like cold war espionage. The black hats devise hacks, the white hats develop counter-measures, the black hats concoct new hacks and counter-counter-measures, and on and on and on. For the moment – at least in this situation – the black hats seem to have the upper hand.

The pendulum is sure to swing back toward the white hats. After all, for the careful webmaster the white hats generally have the upper hand. Though there are exceptions enough to keep my guard up. I’ve been using CloudFlare for – well, I can’t remember exactly how long – but more than five years. Only in the last few weeks have I seen bots slipping through my page rules.

So, for now … gotta put recaptchas on login, subscriber, and comment screens. Didn’t want to go there. Didn’t think I would have to. Recaptchas are kinda annoying, but the least obtrusive remedy I know of. Curse you, bad bots!

WP Malware Scanners

I take a number of security precautions to keep my sites free of malware. But what if malware gets past my defenses? I need to be able to detect it so that I can eradicate it. With WP malware scanners, as with everything else WP, I prefer free. I know of three types of free WP malware scanners: Host-based; Web-based; and Plugins.

wp malware scanners

The malware scanner offered by my host – and by many other hosts – built into cPanel, is ClamAV, although it is labeled simply “Virus Scanner”. It has the advantage of scanning not just my WP site but my entire home directory, including email. On a neglected legacy site with about a decade and a half of email in multiple accounts, I was shocked to find hundreds of infected emails, which ClamAV dutifully exterminated for me.

There are a number of web-based scanners. Three that I know of that are free and do not require me to create an account are Sucuri Site Check, Quttera, and WP Scans. A big advantage of all three is super convenience. I just visit the website and run a scan. Which works best? I have no idea. I suspect each has its plusses and minuses.

And the plugins. There are several. The two that I’ve tried are WordFence and NinjaScanner. The advantage of a plugin scanner is that it works from inside my WP site, so presumably it can find things that external scanners miss. I have a quibble – actually a couple – with WordFence, so I prefer NinjaScanner.

So, which of these WP malware scanners should I use? Why not all of them? They presumably all have strong points. Using multiple scanners would seem to increase my chances of catching even obscure malware. During my monthly site maintenance I alternate among ClamAV, Sucuri Site Check, Quttera, and WP Scans. Annually, I run NinjaScanner.

 

WP is not ready for CSP

A Content Security Policy (CSP) relies on code headers to help prevent cross site scripting and other malware, providing a great addition to a layered security approach. I think of it as a reverse firewall. It tells browsers exactly what content should be accepted from my site. All other content – malware for example – should be rejected. So, it doesn’t protect my site. But if my site gets infected, it can prevent the infection from spreading.

WP is not ready for CSP

A correct CSP is a really good thing, adding to interweb safety. So, why do almost no websites – something incredibly small like 1% of 1% – have a CSP? Partly because it is not very well known yet, but also because it is really complicated to create a correct one. It is much more likely that I will screw up my WP site and deliver false errors to my visitors than it is that my CSP will work properly.

If I create a flat HTML website, and code it myself, so I know the code really well, inside and out, I have a good chance of being able to create a correct CSP. But WP, like any content management system, intentionally obfuscates the code details. Themes and plugins – unless I spend many hours to really study and understand the code – are black boxes by design.

The WP Content Security Policy plugin is an ambitious attempt to solve the challenges of implementing CSP on WP. It is really cool. I tried it out and wanted very much to love it. It resolves the problem of code obfuscation by letting me create a bare-bones CSP then add to it over time. It logs CSP errors so that I can examine them and tweak my CSP to eliminate the false errors.

The problem? The plugin relies on the WP REST API to log CSP errors. I use the excellent Disable WP REST API plugin by Jeff Starr of Perishable Press to substantially reduce hacker attack vectors that the REST API opens. I have to choose between no-CSP security risks vs. REST API security risks. I choose to leave REST API disabled, and forgo – for now – the benefits of CSP.

 

My full list of WP security settings, plugins, etc..

I am convinced that for most WordPress users one of the popular all-in-one security plugins like WordFence or All In One WP Security & Firewall is a good solution. I like to tinker though, and to choose the best tool for me for each aspect of security. I also like light solutions, and a layered approach to security.

My full list of WP security settings

This is my full list of WP security settings and other security things:

  • Free Plugins:
  • In my Custom Plugin
    • Auto-update WP, themes, and plugins
    • Remove Windows Live Writer link from header data
    • Remove EditURI (XML-RPC) link from header data
    • Disable password reset
    • Disable login using email account name
    • Disable login hints
    • Disable login Remember Me option
  • In main htaccess
    • Set ErrorDocument for 400, 401, 403, and 500 to short text strings (e.g. “400: Sorry, bad request.”)
    • The excellent 6G Firewall from Jeff Starr of Perishable Press
    • Add security headers to protect against XSS attacks, page-framing, click-jacking, and content-sniffing
    • Block directory browsing
    • Block access to wp-config.php, xmlrpc.php, .htaccess, readme.html, license.txt, install.php, installer.php
  • In other htaccess
    • Block php execution in /wp-content/uploads/ – and –  /wp-includes/ folders
  • In wp-config.php:
    • Disable the Plugin and Theme Editor
    • Disable PHP error reporting
    • Disable custom HTML
  • In CloudFlare:
    • Hide IP address for A and CNAME records
    • Enable DNSSEC for my most most important sites
    • Full (strict) SSL
    • Always use HTTPS
    • Enable HSTS for my most important sites
    • Enable the latest version of the TLS protocol
    • Security Level: Medium
    • Challenge Passage: 4 hours
    • Page rules for login security
    • Email address obfuscation
    • Hotlink protection
  • Miscellaneous
    • Non-obvious admin username (e.g. not ‘admin’)
    • Strong passwords for my admin account, cPanel, host, registrar, email, CloudFlare – any account associated with administering my site
    • Two factor authentication (used selectively – on accounts that matter most)
    • TLS (i.e. HTTPS) using Let’s Encrypt

Web Cache Deception Hacks

Web Cache Deception Hacks

Web cache deception hacks are a fairly recent threat, first described by Omer Gil in February 2017. In certain situations a hacker could leverage a misconfiguration between a web server and a proxy cache like CloudFlare to reveal sensitive information that could help the hacker takeover my account. To be honest, this seems like a very unlikely threat. The situations that could cause it seem complex and obscure, and large scale attacks of this sort have not been observed in the wild.

But, I never know when a brilliant bad guy or gal could find a way to expand a tiny, obscure threat into a great big nasty one. So, it makes sense to do what I can to prevent it. CloudFlare initially recommended that each and every CloudFlare user carefully check his or her server and CloudFlare configurations, and fix anything amiss. Kinda wishful thinking there on CloudFlare’s part. This is sure to be over the head of most users, and even those tech-savy enough to do it probably won’t get the word, this being an obscure threat.

Fortunately CloudFlare introduced a more practical solution about a few months later, in January 2018. The Cache Deception Armor page rule promises protection from Web Cache Deception hacks while still allowing static assets to be cached. It makes sense to include this new rule with my ‘Cache Everything’ rule.

Allowing only CloudFlare traffic

No piratesIn other posts I give my point of view on the security advantages of using CloudFlare. But what’s to stop a bad guy, gal, or bot from accessing my site directly by IP address? I can try to keep my IP address secret, but a determined hacker will find it without too much trouble. He or she or his/her robot minions could then avoid CloudFlare security by attacking my site directly – unless I take explicit measures by allowing only CloudFlare traffic.

CloudFlare advises using directives in my htaccess file to allow traffic only from CloudFlare IPs. Problem is – that doesn’t work for me. My server is configured to see each visitor’s origin IP, not the CF IP, so that my visitor analytics make sense. I googled my fingers blue and could not find a solution.

In desperation – because I am a stereotypical guy who hates asking for directions – I asked for directions. A kind and knowledgeable person using the moniker sdayman came immediately to my rescue. It turns out he is a very prolific good Samaritan in the CloudFlare community.

Sdayman’s solution is elegant – three lines of code – and in my experience it works great:

RewriteEngine On
RewriteCond %{HTTP:CF-IPCountry} ^$
RewriteRule ^ - [F,L]

It checks to see if the CloudFlare IP Country header is present. If not, it serves a 403 error. Traffic bypassing CloudFlare will not have the header.

One small gotcha – I have to make sure I turn on the CloudFlare IP Geolocation feature. Easy-breezy. It’s on the Network screen.

Allowing only CloudFlare traffic

Bad bot login attempts

One thing that consistently amuses me on the usually excellent WP support forum is the experts’ responses to questions about bad bot login attempts …

  • “Don’t worry about it”
  • “It’s normal”
  • “I get way more malicious login attempts than that” – as if it were a badge of honor.

Bad bot login attempts
Bots constantly pound away at WP login pages – usually using ‘admin’ as username and a list of common passwords. These hacks are easy to thwart. Just use a non-obvious username and strong password. Problem solved, right? Well, kinda – with a strong password and a username other than ‘admin’, I won’t be hacked by this vector. But I refuse to accept my site being constantly under attack as somehow ‘normal’.

Obfuscating my login URL using a plugin like WPS Hide Login is a great solution. Bots can’t pound away at my login page if they can’t find it. Problem solved, right? Well, kinda – bots are kept off my login page but are still hitting my server and using resources to generate 404 pages.

Next step in the solution is to serve a simple 403 text string instead of a 404 page for login page attempts, by including this text in my .htaccess file:

# Serve a 403 text string not a 404 page for login attempts
ErrorDocument 403 "403: Sorry, not permitted."
RedirectMatch 403 (.*)wp-login\.php$

A text string is much less resource-intensive than a 404 page. Problem solved, right? Well, kinda – I would really rather keep bad login bots off my site completely.

Final step is to use CloudFlare page rules to block bad login bots at the reverse proxy level, before they even get to my server. Problem solved. Maybe not perfectly, but the best I know how to do.