Skip to content
Website Security

SQL Injection and XSS Explained for Website Owners

Two terms that fill security reports, explained without code: how SQL injection and cross-site scripting work, and what they leave behind on a hacked site.

A combination padlock and bank cards resting on a keyboard
8 sections · 7 min read
In this article · 8 sections

Security reports and plugin changelogs are full of two terms that mean little to most business owners: SQL injection and cross-site scripting, often shortened to SQLi and XSS. They show up in update notes, in host warnings and in cleanup reports after a hack. Owners nod along without knowing whether either is something they should lose sleep over.

You do not need to write code to understand them. Both come down to one idea: a website trusting text it should have checked. This post explains each in plain language, with everyday comparisons, what each looks like when it has been used against a site, and what you as an owner can actually do about them.

The shared root: trusting input

Websites constantly accept text from strangers. Search boxes, contact forms, login fields, comment boxes, the address bar itself. Even a link someone clicks can carry text in it, after the question mark in the URL.

Well-written code treats every piece of that text as suspect. It checks it, cleans it and handles it in a way that cannot change the code’s own instructions. When code skips that step, an attacker can type something that the site mistakes for instructions. SQL injection and XSS are two versions of that mistake, aimed at different targets.

  • SQL injection targets the database behind the site.
  • Cross-site scripting targets the browsers of people visiting the site.

SQL injection, explained

What a database query is

A WordPress site keeps almost everything in a database: posts, pages, users, settings, orders. When a page loads, the code asks the database questions in a language called SQL. A product search, for example, might ask “give me all products whose name contains the word the visitor typed”.

Where it goes wrong

Imagine a receptionist who reads out whatever is written on a visitor’s form, word for word, to the filing clerk. A normal visitor writes “Please fetch the file for Sharma”. A malicious visitor writes “Please fetch the file for Sharma, and also hand me every file in the cabinet”. If the receptionist reads it out without thinking, the clerk does both.

SQL injection is exactly that. Badly written code pastes the visitor’s text straight into its database question. A carefully crafted entry can turn the question into a different one: list every user and password hash, change a setting, add a new administrator.

What an attacker can do with it

That depends on the flaw, but common outcomes include:

  • Reading data from the database, such as customer details, email addresses or order history.
  • Reading the password hashes of user accounts, which can then be attacked offline.
  • Changing data, such as creating an administrator account or altering the site address.
  • Planting spam links or malicious scripts into posts and settings stored in the database.

How WordPress code avoids it

WordPress gives developers a safe way to build database questions: prepared statements, through a function called $wpdb->prepare. The visitor’s text is passed in separately from the instructions, so it is always treated as data and never as part of the command. The receptionist hands the clerk the visitor’s form in a sealed envelope marked “name only” instead of reading it aloud.

WordPress core uses this approach. SQL injection flaws in WordPress sites are almost always in plugins or themes where a developer built a query by hand and skipped the safe method.

Cross-site scripting, explained

What it targets

XSS does not attack the database directly. It gets the website to deliver the attacker’s JavaScript to visitors, so that the script runs in their browsers as if your site had written it. Because the browser trusts your site, the script gets the same access your own pages have.

An everyday comparison

Think of a shop noticeboard where anyone can pin a card. Usually people pin “Bicycle for sale”. Now imagine a card that, when read aloud by the shop assistant, makes the assistant hand the reader’s wallet to a stranger. The danger is not the card itself. It is that the shop repeats what is on it without looking.

The three common kinds

  • Stored XSS. The attacker’s script is saved on the site, for example in a comment, a review, a profile field or a form entry, and runs every time someone views that content. This is the most damaging kind, because it can hit administrators who open the entry in the dashboard.
  • Reflected XSS. The script is in a link. The site takes part of the link and puts it on the page without cleaning it. The attacker has to get someone to click the crafted link, often by email.
  • DOM-based XSS. The flaw is in the page’s own JavaScript, which takes text from the URL or elsewhere and inserts it into the page unsafely.

What an attacker can do with it

  • Redirect visitors to spam, scam or malware sites.
  • Show fake login boxes or fake payment forms on your real pages.
  • Capture what visitors type into forms, including card details on a checkout page.
  • If an administrator views the poisoned content, act as that administrator: create new admin accounts, install plugins, or change files through the dashboard.

That last point is why stored XSS in a form or comment plugin is taken so seriously. An anonymous visitor submits a form; the site owner opens the entry in the dashboard; the script runs with the owner’s access. A script that captures card details on checkout is the basis of many payment skimmers. Our page on removing card skimmers from a checkout covers that case.

How WordPress code avoids it

The defence is called escaping: converting special characters so the browser shows them as text instead of running them. WordPress has functions for this, such as esc_html, esc_attr and esc_url, and wp_kses for allowing only a safe list of HTML tags. Good plugin code escapes everything it prints. Flaws appear where a developer forgot one spot.

The two side by side

SQL injection Cross-site scripting
What it attacks The site’s database Visitors’ and admins’ browsers
What the attacker sends Text that changes a database query Text that becomes a script on the page
Typical damage Data read or changed, admin accounts added Redirects, fake forms, stolen input, admin actions
Developer’s fix Prepared statements Escaping and sanitising output
Where you see the aftermath Odd users, changed settings, leaked data Injected scripts in posts, widgets or options

What the aftermath looks like on a hacked site

When one of these flaws has been used, cleanup reports often mention the same things:

  • Script tags in the database. Pieces of JavaScript sitting inside post content, widget text, theme settings or plugin options, often pointing to an outside domain.
  • Altered settings. The site address, home URL or admin email changed to something unfamiliar.
  • Extra administrator accounts, sometimes with names designed to look like system users.
  • Spam content inserted into old posts, often hidden with styling so you do not notice on the page.

Because the damage lives in the database rather than in files, a file scan alone may report the site as clean while visitors still get redirected. Finding and removing it means searching the database tables carefully, without breaking legitimate content that uses similar code.

What owners can do

You cannot fix a plugin’s code, and you should not try to audit it. But owners control most of the factors that decide whether these flaws hurt them.

Keep plugins and themes updated

Most SQLi and XSS flaws on WordPress sites are found and fixed by the plugin developer. The fix only protects you once it is installed. Our explainer on the way plugin flaws get disclosed and fixed covers how to read the warnings and decide how fast to act.

Reduce the places that accept input

Every form, comment box and registration page is a place where text comes in. Turn off comments if you do not use them. Disable open user registration unless the site needs it. Remove old form plugins that still have pages live somewhere.

Limit what admin accounts are exposed to

Stored XSS is most dangerous when an administrator views the poisoned content. Use a separate, lower-role account for daily jobs like reading form entries or moderating comments, if your setup allows it. Keep the number of administrators small.

Use a firewall layer

A web application firewall, either as a plugin or as a service in front of the site, can block many common injection attempts before they reach the code. It is a safety net, not a replacement for updates.

Watch for the signs

Know what unusual looks like on your own site. New admin users, settings that change on their own, visitors reporting redirects, and Search Console security messages are all reasons to look closer. Our list of everyday website security practices brings these together.

A word on “my site is too small to be targeted”

Attackers rarely pick sites by hand. They write tools that try a known flaw against every site they can find running the vulnerable plugin. A small bakery’s site and a large retailer’s site look the same to that tool. What protects you is not being uninteresting. It is not running the vulnerable version.

Next steps

If you suspect one of these flaws has already been used on your site, our hacked website help page explains how to reach us urgently and what we check first.

If a scan or a report mentions injected scripts, extra admin users or spam content stored in your database, our database cleanup for hacked WordPress sites is the service that deals with exactly that. We can look first and tell you what we find before any work starts.

Is Your Website Working Properly?

Get a free website health check from WebMaintor. We'll review your website's speed, security, forms, and technical health — and tell you exactly what needs attention.

No obligation. No automated reports. A real review by our team.