Learn / Security basics

Website Security Basics

GUIDE

10 min read · 2,162 words

Most hacked sites were not targeted. They were found by a scanner looking for something old.

Most hacked sites were not targeted. Nobody read your About page and decided you were interesting. A scanner, running continuously from somewhere, asked ten thousand servers whether they had a particular old plugin, a particular exposed file, or a login form that accepts a guessed password, and yours said yes.

That is good news, in a bleak sort of way. It means the defences that matter are the dull ones: patching, unique passwords, closing doors you do not use, and having a backup that works. None of it needs a security budget. All of it needs someone to own it, which on a small site is usually you.

What follows is arranged by how much protection each habit buys for the effort. Work down the list. Each section ends in something you can check today, and the last sections cover how to know you have a problem and what to do when you do.

Accounts first

The hosting account, the registrar account and the email address attached to both are the keys to everything. If someone owns your email, they can reset the other two, and then they own the domain, the site and the mail. Start there.

Give each account a unique password from a password manager, and turn on two-factor authentication. An authenticator app or a hardware key is better than text messages, because phone numbers can be taken over by persuading a mobile operator. Store the recovery codes somewhere that is not the same inbox.

Then look at who has logins. Remove users who no longer need access: the freelancer from two years ago, the agency that built the site, the colleague who moved on. Review the list every few months. On a CMS, give people the lowest role that lets them do their job; an editor does not need to be an administrator, and a shop assistant does not need to install plugins.

Reuse is what undoes most good passwords. When a service you used in 2019 leaks its user table, attackers try the same address and password everywhere else. A password manager makes unique passwords painless, and breach lookup services will tell you if your address has appeared in a known leak.

Keep software current

Updates are dull and they work. Core, plugins, themes and the PHP version should all be on supported releases. Check your PHP version in the hosting panel: running a release that no longer gets security fixes means every new flaw stays open for good. Current supported versions are in the 8.x series, and most hosts let you switch per site.

Delete what you do not use rather than leaving it deactivated, because inactive code can still be vulnerable. A disabled plugin's files are still on disk, and many flaws can be reached by requesting the file directly, whether or not WordPress loaded it. Avoid pirated themes and plugins: they are one of the most reliable ways to get a backdoor installed for you.

If automatic updates make you nervous, update on a staging copy first, then on the live site at a quiet time with a backup taken just before. Security releases for popular plugins tend to be exploited within days of announcement, so do not let a fix sit for months.

It also pays to prefer fewer, better-maintained plugins. Each one is code written by someone else, running with the full authority of your site. Look at when it was last updated, how many installs it has, and whether the developer responds to reports.

Monitoring: uptime, certificate expiry, logs, file changes Firewall: host or CDN filtering of automated probing Limited access: SFTP/SSH only, tight permissions, restricted admin Current software, unused code removed Your site, with strong accounts at the centre Backups sit outside all the layers, off the server.
Each layer catches what the one inside it misses; backups sit outside all of them.

Limit what can be reached

Use SFTP or SSH, not plain FTP. FTP sends the password in readable form, and anyone on the same network path can collect it. Check your file transfer client's saved sites; if the protocol says "FTP" and not "SFTP", change it.

Keep file permissions tight. A common safe pattern on shared and VPS hosting is 644 for files and 755 for directories, with configuration files such as wp-config.php at 600 or 640 if the host allows it. Never use 777 as a fix for an upload error; it lets any process on the machine write to that path.

find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;
chmod 600 wp-config.php

Restrict the admin area by IP address or add a second layer of authentication if it is practical. On Apache, a short block in .htaccess inside the admin folder can allow only your office address. If your address changes, use HTTP basic authentication in front of the login instead.

Rename or remove default accounts such as admin, because the first thing a password-guessing bot tries is the obvious user name. A web application firewall, whether from your host or a CDN, blocks a great deal of automated probing, including login floods and requests for known-vulnerable paths. It will not rescue an unpatched site, but it buys time.

The same logic applies to the server itself. On a VPS or dedicated machine, disable SSH password logins in favour of keys, keep the firewall closed except for ports you use, and do not leave database ports open to the internet. On shared hosting your host handles most of this, so your part is the application and its files.

Backups you have actually tested

Automate them, keep at least one copy off the server, and restore one occasionally to a test location. A backup that has never been restored is an assumption. Include both the files and the database, since one without the other does not rebuild a dynamic site.

Keep several generations. If you discover on Thursday that the site was infected on Monday, the Wednesday backup contains the infection. A reasonable pattern is daily copies for a week and weekly copies for a month, though how much that costs in space depends on the size of your uploads folder.

Restoring is the real test. Pick a quarter, create a throwaway subdomain, restore into it, and load a few pages. Time the whole exercise. You then know the number that matters, which is how long recovery really takes.

HTTPS everywhere

Serve everything over HTTPS, redirect HTTP to HTTPS, and make sure the certificate renews itself. Consider HSTS once you are confident that nothing on the site needs plain HTTP. The HTTPS migration guide covers the order of operations, and the expiry checker shows how long the current certificate has left.

HTTPS protects logins and form data in transit, and it stops hostile networks from injecting content into your pages. It does not tell you the site is free of malware. A padlock on a compromised site is still a padlock.

Watch for trouble

Monitor uptime and certificate expiry. Check for unexpected admin users and recently changed files. Read your error and access logs now and then, even when nothing is broken. Strange spikes in traffic from one address are worth a look.

A few commands give you a quick read on a Linux host with shell access:

# files in the web root changed in the last 3 days
find public_html -type f -mtime -3 -name '*.php'

# top requesters in an access log
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head

# repeated requests to the login page
grep 'POST /wp-login.php' access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head

PHP files turning up in the uploads folder deserve immediate attention, since that folder should only hold media. The same goes for files with random-looking names, or a copy of a core file that does not belong where it is. Pair this with a file integrity check from a security plugin or your host's scanner, which compares core files with the official versions.

Guessed-password logins that succeed (illustrative) Weak shared password high Unique password low Unique + rate limit very low Unique + 2FA close to none
Bar lengths are illustrative only, to show how the layers stack; they are not measurements.

A worked example: how an ordinary site gets taken over

Here is a composite of something I have seen many times, with details changed. A small business site runs a contact-form plugin installed three years ago. On a Tuesday the plugin's author publishes a fix for a file upload flaw. Nobody at the business reads the announcement. On Thursday, an automated scanner requests the vulnerable path on the site, gets a response that matches, and uploads a small PHP file with a random name into the uploads folder.

Nothing visible happens. Over the next fortnight the file is used to add a hidden admin user, edit a theme file, and send a few thousand spam messages a day through the server. The first symptom the owner sees is a warning from the host about outgoing mail, then a customer saying the site redirects to a pharmacy page on mobile devices only.

Every step of that story was preventable by an ordinary habit. A current plugin would have blocked the upload. A rule denying PHP execution in the uploads folder would have made the file inert. A glance at the admin user list would have shown the stranger. A log search would have found the odd POST request. No single habit has to be perfect, which is the whole argument for having several.

# Apache: stop PHP running inside uploads (put in wp-content/uploads/.htaccess)
<FilesMatch "\.(php|phtml|phar)$">
  Require all denied
</FilesMatch>

What changes by hosting type

How much of this is your job depends on what you bought. The table gives the usual split; check your own host's terms, since providers differ.

AreaSharedManaged WordPressVPS or dedicated
Server operating system patchesHostHostYou
PHP version selectionYou, in the panelHost, often automaticYou
Core, plugin and theme updatesYouOften shared with hostYou
Firewall and port rulesHostHostYou
BackupsUsually offered, keep your ownIncluded, keep your ownYou, or an add-on
Account security and passwordsYouYouYou

The last row never moves. Whatever the plan, the logins are yours, and they are the way most of the damage starts.

If you have been hacked

  1. Put the site into maintenance mode or take it offline to protect visitors. Search engines and browsers may start warning people within hours, so speed matters.
  2. Take a copy of the infected files for analysis, then restore from a clean backup. Choose a backup from before the first sign of trouble, not just the last one.
  3. Update everything, remove unused code, and change every password and key: hosting, database, FTP, SSH, email, and the WordPress salts in wp-config.php.
  4. Find the way in. If you only clean the symptoms, it will return. Check for rogue admin users, scheduled tasks and modified .htaccess files, and search for the typical backdoor patterns such as eval(base64_decode(.
  5. Tell your host. They can often help identify what happened and can check other accounts on the same server.
  6. Once clean, request a review from any search engine or browser blocklist that flagged the site.
Cleaning an infected site in place is a last resort. Deleting infected files by hand tends to miss a second backdoor. Restoring a known-good copy and then patching is more reliable. Our casebook has composite write-ups of how this goes wrong, and the troubleshooting guide covers the related symptoms.

What to look at on your own setup

  1. List every user with admin rights on the site, the hosting panel and the registrar, and remove the ones you cannot explain.
  2. Look at the update screen: anything pending, anything abandoned, anything deactivated.
  3. Confirm your PHP version is a supported 8.x release.
  4. Check that your file transfer tool uses SFTP, and run the permission commands above in a staging copy first.
  5. Restore the latest backup somewhere harmless and open it.
  6. Check curl -I https://example.com/ shows a valid response and that the HTTP version redirects.
Checklist: unique passwords and two-factor on hosting, registrar and email; unused users removed; core, plugins, themes and PHP current; unused code deleted; SFTP only; tight file permissions; admin area restricted; firewall on; automated off-site backups with a tested restore; HTTPS with auto-renewal; uptime and expiry monitoring; a written incident plan.

What else people want to know

Is a security plugin enough?

No. A plugin can scan, block and alert, but it cannot fix weak passwords or a vulnerable component it did not notice. Treat it as one layer.

How often should I update?

Apply security releases within a few days, and review everything else weekly or fortnightly. Sites with sensitive data deserve a faster rhythm.

My site is small. Why would anyone bother?

Because attackers want your server, not your content: to send spam, host phishing pages, or redirect visitors. A small site with old software is as useful to them as a large one.

Should I rely on my host's backups?

They are a good second copy. Keep your own as well, stored elsewhere, because a host problem can take the account and its backups down together.