← Back to blog

SQL Injection Explained: How Attackers Steal Data from Business Websites

What SQL Injection Actually Is

SQL injection is the oldest and still one of the most damaging web application vulnerabilities. It has been around since the late 1990s, and despite decades of awareness, it continues to appear in production websites with alarming regularity. OWASP data from their testing of thousands of applications found injection flaws in 94% of the apps they analyzed. That number should concern every business owner.

The concept is straightforward: when a website takes user input (a login form, a search box, a URL parameter) and passes it directly into a database query without proper sanitization, an attacker can inject their own SQL commands. Instead of submitting a username, they submit a fragment of database code. The server executes that code as if it were a legitimate query, and the attacker gains access to data they should never see.

If your business website stores customer data, order records, email addresses, or any other information in a database, SQL injection is a threat you need to understand. Not at a theoretical level, but in practical terms: how does an attacker actually do this, and how do you stop them?

How a Normal Database Query Works

Before we look at the attack, let us understand what happens when things work correctly. Imagine a login form on your website. A user types their username and password and clicks "Sign In." Behind the scenes, your website builds a database query that looks something like this:

SELECT * FROM users WHERE username = 'marco' AND password = 'mypassword123'

The database receives this query, looks for a row where the username is "marco" and the password matches, and returns the result. If a match is found, the user is logged in. If not, they see an error message. Simple and logical.

The problem starts when the application constructs this query by concatenating strings, essentially pasting the user's input directly into the SQL statement. The code behind the form might look like this:

query = "SELECT * FROM users WHERE username = '" + userInput + "' AND password = '" + passInput + "'"

That userInput variable contains whatever the user typed. If they type a normal username, everything works. But what if they type something else entirely?

Classic SQL Injection: The Basic Attack

Instead of typing a username, an attacker types this into the username field:

' OR '1'='1' --

The application pastes this into the query, producing:

SELECT * FROM users WHERE username = '' OR '1'='1' --' AND password = 'anything'

Let us break down what happened. The single quote after the empty string closes the username value. The OR '1'='1' adds a condition that is always true. The -- is a SQL comment marker, which tells the database to ignore everything after it, including the password check. The result: the database returns all users, because '1'='1' is always true. The attacker is logged in, usually as the first user in the table, which is often the administrator.

This is the simplest form of SQL injection, and it has been used to breach companies of every size. The 2008 Heartland Payment Systems breach, which exposed 130 million credit card numbers, started with a SQL injection attack.

Data Extraction with UNION Attacks

Login bypass is just the beginning. The more dangerous use of SQL injection is data extraction. An attacker uses the UNION SQL operator to append additional queries to the original one and pull data from any table in the database.

For example, if a website has a product search that queries the database like this:

SELECT name, price FROM products WHERE category = 'electronics'

An attacker can modify the input to:

electronics' UNION SELECT username, password FROM users --

The resulting query becomes:

SELECT name, price FROM products WHERE category = 'electronics' UNION SELECT username, password FROM users --'

Now the page that was supposed to show product listings also displays every username and password stored in the users table. The attacker sees this data directly on the page, formatted as if it were product information.

Blind SQL Injection: When You Cannot See the Output

Not all SQL injection vulnerabilities produce visible output. Sometimes the application does not display query results on the page. In these cases, attackers use blind SQL injection, which is slower but equally effective.

Boolean-Based Blind SQLi

The attacker sends queries that ask the database true-or-false questions. Based on whether the page behaves differently (shows content or shows an error, loads or does not load), the attacker infers one bit of information at a time.

For example, to extract the first character of the admin password:

' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin') = 'a' --

If the page loads normally, the first character is 'a'. If it shows an error or different behavior, the attacker tries 'b', then 'c', and so on. Character by character, they reconstruct the entire password. Automated tools like sqlmap can do this in minutes.

Time-Based Blind SQLi

When even the page behavior does not change, attackers use timing. They inject queries that cause the database to pause for a specific duration if a condition is true:

' AND IF((SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a', SLEEP(5), 0) --

If the page takes 5 seconds to respond, the first character is 'a'. If it responds immediately, it is not. This technique is slower but works against applications that show identical responses regardless of the query result.

Second-Order SQL Injection

This is the variant that catches even experienced developers off guard. In second-order SQL injection, the malicious input is stored safely in the database during the first interaction (say, during user registration). It is properly escaped when stored. But when that stored value is later retrieved and used in a different query without being sanitized again, the injection executes.

Example: a user registers with the username admin'--. The registration query uses prepared statements, so the value is stored safely. Later, the application has a password change feature that builds a query like:

UPDATE users SET password = 'newpass' WHERE username = '" + storedUsername + "'

When the stored username admin'-- is placed into this query, it becomes:

UPDATE users SET password = 'newpass' WHERE username = 'admin'--'

The attacker just changed the admin's password. The input passed through initial validation perfectly, but the second use of that data created the vulnerability.

What Attackers Actually Do After Getting In

Understanding the attacker's objectives helps you understand why SQL injection is taken so seriously:

  • Data exfiltration: Customer names, email addresses, phone numbers, purchase history, payment data. This is the primary goal for most attackers. The data is sold on dark web marketplaces or used for targeted phishing.
  • Authentication bypass: Logging in as an administrator to gain full control of the application, modify content, install backdoors, or redirect traffic.
  • Data modification: Changing prices, altering order records, inserting malicious content into pages served to other users.
  • Privilege escalation: Using database access to read server configuration files, execute operating system commands (on misconfigured systems), or pivot to other systems on the network.
  • Denial of service: Dropping tables, deleting records, or running resource-intensive queries that bring the database server to its knees.

For a Swiss SME, the consequences include not just the direct damage but also violations of the Federal Act on Data Protection (nDSG) if customer data is exposed through a preventable vulnerability. We have covered the full cost of a breach in our article on the cost of a hacked website for SMEs.

Why SQL Injection Is Still So Common

You might wonder how a vulnerability discovered in the 1990s still affects the majority of web applications. Several factors contribute:

  • Legacy code: Websites built years ago using outdated coding practices are still running in production. Nobody has rewritten the database layer. The original developer may no longer be involved.
  • Inexperienced developers: Not every developer has security training. Many learn to build features first and think about security later, if at all. String concatenation is the first approach many tutorials teach.
  • Dynamic query building: Some applications require complex queries that change structure based on user selections (filters, sorting, search operators). Developers sometimes resort to string concatenation when they find prepared statements cumbersome for these scenarios.
  • ORMs give false confidence: Object-Relational Mapping frameworks handle SQL generation automatically, but developers can still write raw queries when the ORM does not support what they need. Those raw queries often lack proper parameterization.
  • No code review or testing: Many SME websites are built by a single developer or a small agency without code review, security testing, or penetration testing budgets.

Real-World SQL Injection Breaches

These are not theoretical scenarios. SQL injection has been behind some of the largest data breaches in history:

IncidentYearImpact
Heartland Payment Systems2008130 million credit card numbers stolen
Sony Pictures201177 million PlayStation Network accounts compromised
Yahoo2012450,000 credentials leaked via SQL injection on Yahoo Voices
TalkTalk2015157,000 customer records stolen, GBP 400K fine
Equifax2017147 million records exposed (initial vector was a different flaw, but SQLi was part of the lateral movement)

And these are the breaches that make headlines. Thousands of smaller businesses get compromised through SQL injection every year without any public disclosure. A small company in Lugano or Ticino with a vulnerable contact form or product catalog is just as exposed as a large corporation, often more so because they lack the security monitoring to even detect the attack.

Prevention: Prepared Statements (Parameterized Queries)

The single most effective defense against SQL injection is prepared statements, also called parameterized queries. Instead of building a SQL string by pasting user input into it, you define the query structure with placeholders and pass the user input separately:

Vulnerable (string concatenation):

query = "SELECT * FROM users WHERE username = '" + userInput + "'"

Safe (prepared statement):

query = "SELECT * FROM users WHERE username = ?" with parameter [userInput]

With a prepared statement, the database knows that the placeholder is a data value, not part of the SQL structure. Even if the user types ' OR '1'='1' --, the database treats the entire string as a literal username value. It searches for a user named ' OR '1'='1' --, finds none, and returns no results. The injection fails completely.

Every modern programming language and database driver supports prepared statements:

  • PHP: PDO with prepare() and execute(), or MySQLi with prepare()
  • Python: Database API with cursor.execute(query, params)
  • Java: PreparedStatement class in JDBC
  • Node.js: Most database libraries support parameterized queries by default
  • C# / .NET: SqlCommand with SqlParameter

There is no excuse for not using them. If your web developer or agency is building queries with string concatenation, that is a serious red flag about their security practices.

Prevention: Input Validation

Prepared statements are the primary defense, but input validation adds a second layer. The principle is simple: define what valid input looks like and reject everything else.

  • Whitelisting over blacklisting: Do not try to filter out dangerous characters. Instead, define what is allowed. If a field should contain a number, validate that it contains only digits. If it should be an email, validate the format.
  • Type checking: If a URL parameter should be an integer (like a product ID), convert it to an integer before using it. parseInt("1 OR 1=1") returns 1 or NaN, neither of which is injectable.
  • Length limits: SQL injection payloads tend to be longer than legitimate input. A username field limited to 30 characters provides less room for an attacker to craft a working payload.
  • Encoding output: Even if injection fails at the SQL level, output encoding prevents stored malicious content from being rendered as code in the browser (this overlaps with XSS prevention, which we cover in our XSS attack explained article).

Prevention: Web Application Firewalls (WAF)

A WAF sits between users and your web application, inspecting every request for patterns that look like attacks. Modern WAFs can detect and block SQL injection attempts in real time.

A WAF is a valuable layer of defense, but it is not a substitute for writing secure code. WAFs can be bypassed. Attackers constantly develop new encoding techniques and payload variations to evade WAF rules. Think of a WAF as a safety net, not a replacement for building the house correctly.

Options for WAFs include:

  • Cloud-based WAFs: Cloudflare, Sucuri, AWS WAF. These are the easiest to deploy and work well for most SME websites.
  • Server-level WAFs: ModSecurity with the OWASP Core Rule Set. More configurable but requires server administration expertise.
  • Application-level WAFs: Libraries and middleware that inspect requests within your application code.

Prevention: Least Privilege Database Access

Even if an attacker successfully injects SQL, you can limit the damage by restricting what the database user can do. The application's database account should have the minimum permissions needed to function:

  • If the application only reads data from a table, the database user should not have write permissions on that table.
  • The application database user should never have DROP TABLE or DROP DATABASE permissions.
  • Administrative database operations (schema changes, user management) should use a separate, more privileged account that the application never touches.
  • Consider using different database users for different parts of the application (e.g., one for the public-facing site, another for the admin panel).

Prevention: Security Testing

You cannot fix what you do not find. Regular security testing is how you discover SQL injection vulnerabilities before attackers do.

  • Automated scanning: Tools like OWASP ZAP (free), Burp Suite, or Acunetix can scan your website for SQL injection and other vulnerabilities. Run these scans after every significant code change.
  • Manual penetration testing: Automated tools catch the obvious cases. A skilled penetration tester will find second-order injections, logic flaws, and context-specific vulnerabilities that scanners miss.
  • Code review: Have someone other than the original developer review the database layer code, specifically looking for raw SQL construction without parameterization.

We offer security assessment services for businesses in Lugano and across Switzerland. If you are unsure whether your website is vulnerable, get in touch with our team for a thorough evaluation.

What to Do If You Suspect Your Site Is Vulnerable

  1. Do not panic, but act quickly. SQL injection is serious but fixable.
  2. Ask your developer or agency directly: "Are we using prepared statements for all database queries?" If they hesitate or are not sure, that is your answer.
  3. Run an automated scan. OWASP ZAP is free and can identify the most common SQL injection patterns.
  4. Deploy a WAF immediately. Cloudflare's free plan includes basic WAF protection and can be set up in under an hour. This buys you time while you fix the underlying code.
  5. Check your logs. Look for requests containing SQL keywords like UNION, SELECT, DROP, or unusual characters like single quotes and semicolons in form submissions.
  6. Prioritize the fix. Do not wait for the next development cycle. SQL injection is a fix-now vulnerability.

For a broader view of web application security vulnerabilities, see our breakdown of the OWASP Top 10, where injection holds a prominent position.

The Bottom Line for Business Owners

SQL injection is not exotic or sophisticated. It is a well-understood vulnerability with well-understood defenses. The fact that it still appears in the majority of web applications is a failure of development practices, not a failure of available solutions.

If your website has a database behind it (and if it has a login form, a search function, a product catalog, or a contact form that stores submissions, it almost certainly does), ask the question: how are our database queries built? The answer should always be "with prepared statements." Anything else is a risk your business should not carry.

Want to know if your site is secure?

Request a free security audit. In 48 hours you get a complete report.

Request Free Audit

Quick Contact