Union-based SQL injection is an in-band attack that abuses the SQL UNION operator to bolt a second, attacker-controlled SELECT onto a legitimate query, so both result sets come back in a single response. Because the stolen rows land directly on the page, it is one of the fastest ways to read whole tables: usernames, password hashes, payment records, session tokens. It thrives wherever an application builds SQL by pasting raw user input into the statement. This guide covers how the technique works, how it differs from other injection methods, how to detect it in your logs and traffic, and how to stop it for good. The mechanics are simpler than most teams expect, and so is the core fix.
Key Takeaways
- Union-based SQL injection uses UNION SELECT to merge a rogue query with a legitimate one, so stolen data appears in the normal page response.
- It only succeeds when the injected SELECT returns the same number of columns and compatible data types as the original query.
- It belongs to the in-band family of SQL injection, alongside error-based attacks, and is faster than blind (inferential) techniques.
- SQL injection is OWASP Top 10 risk A03:2021 (Injection) and CWE-89; the 2015 TalkTalk breach that exposed 156,959 customers used it.
- Parameterized queries (prepared statements) are the primary fix, because they stop user input from ever changing query structure.
- A web application firewall running the OWASP Core Rule Set blocks UNION SELECT signatures at the edge, adding a second layer.
- Least-privilege database accounts limit how much a successful injection can read.
How a UNION SELECT Statement Hijacks Your Query
A union-based attack ends the application’s original query mid-stream and appends a UNION SELECT, so the database runs two queries and stacks their rows into one result that the app then displays.
SQL’s UNION operator was built for a legitimate job: combining the rows of two SELECT statements into a single result set. Union-based SQL injection turns that feature against the application. When a page builds a query like SELECT name, price FROM products WHERE id = ‘$input’ and the input is not sanitized, an attacker can supply 1′ UNION SELECT username, password FROM users– and the database returns product rows followed by user credentials.
The trailing double dash comments out the rest of the original query so it stays valid. The app, expecting only product data, renders the attacker’s rows in the same table or list. Union-based attacks are simply one branch of the broader family of injection attacks, and the most direct one: no error messages to decode, no guessing, the data is right there on screen.
The attack follows a predictable sequence:
- Find an input that reaches a SQL query and reflects data back on the page.
- Count how many columns the original query returns, using ORDER BY n or a run of UNION SELECT NULLs.
- Identify which returned columns are actually displayed and accept text.
- Swap the placeholders for real data, such as UNION SELECT username, password FROM users.
- Read the exfiltrated rows straight from the response.
That column-count step is not optional, which points to the two conditions every union-based attack has to satisfy first.
The Two Conditions That Make UNION Injection Possible
A union-based injection only works when two conditions hold: the injected SELECT returns the same number of columns as the original query, and each column’s data type is compatible with the matching column in the first query.
Databases refuse to UNION two result sets of different widths. If the original query returns three columns and the attacker’s SELECT returns two, the statement fails. So the first move is always counting columns, usually with ORDER BY probing or a run of UNION SELECT NULL, NULL, NULL until the query stops erroring.
Data types matter too, though most engines are forgiving. Attackers place their target data in a column they know renders as text, then pad the rest with NULL. Once the shape matches, they swap in real column names pulled from the database’s own metadata, such as information_schema.tables and information_schema.columns.
A runtime shield helps here. An Advanced Web Application Firewall inspects requests before they reach the query, flagging the tell-tale UNION SELECT and NULL-padding patterns that legitimate traffic rarely contains.
The probing toolkit is small and consistent:
- Column count: ORDER BY 1..N until an error appears, or UNION SELECT NULL, NULL, … until it succeeds.
- Displayed columns: replace each NULL with a marker string to see which slot shows on the page.
- Schema discovery: query information_schema to list tables and columns.
- Type matching: keep NULL in numeric slots and put strings in text slots.
If union-based is the loud version, it helps to see what the quiet ones look like.
Union-Based vs Other SQL Injection Types
Union-based injection is one of four common SQL injection styles. It is an in-band attack that returns data directly, unlike inferential (blind) methods that leak data through timing or true/false behavior.

In-band attacks use the same channel to inject and receive data, which makes them fast and easy to confirm. Inferential attacks send no data back at all; the attacker rebuilds each value from tiny clues in the response, so a full table dump can take thousands of requests.
| Type | Family | How data escapes | Speed |
|---|---|---|---|
| Union-based | In-band | Rows appended to the page via UNION SELECT | Fast |
| Error-based | In-band | Data leaks inside database error text | Fast |
| Blind (Boolean) | Inferential | True/false response changes, one bit at a time | Slow |
| Time-based | Inferential | Deliberate SLEEP() delays reveal values | Slow |
A real accelerant makes this worse for defenders. sqlmap, the widely used open-source injection tool, automates all four styles: it fingerprints the database, counts columns, and dumps tables without manual probing. That is why automated UNION attempts show up as bursts of near-identical requests against one parameter.
Fast and automated is a bad combination for defenders, and the breach record shows exactly how bad.
Real Union-Based SQL Injection Examples and Their Impact
SQL injection, including union-based variants, has driven some of the most damaging breaches on record. It is classified as OWASP Top 10 risk A03:2021 (Injection) and catalogued as CWE-89. Injection has appeared on every OWASP Top 10 since the first list in 2003, a streak that reflects how stubborn the root cause is.
The TalkTalk breach is a well-documented case. In October 2015, attackers used SQL injection against legacy TalkTalk web pages inherited from its Tiscali acquisition. The UK Information Commissioner’s Office found the personal data of 156,959 customers was accessed, with bank details of 15,656 customers exposed, and issued a record 400,000 pound fine. The ICO noted the pages carried a known, patchable flaw that had gone unaddressed after two earlier attacks the same year.
The typical union-based payload targets exactly what attackers want to monetize. A statement like UNION SELECT email, password_hash FROM users returns credential pairs in one response, and weak or unsalted hashes fall quickly to offline cracking afterward.
Stolen credentials rarely stay contained. When an application also suffers from Broken Access Control, a single leaked admin row can open the door to account takeover across the whole system, turning a read-only leak into full compromise.
Knowing the stakes is one thing. Catching the attack in progress is another.
How to Detect Union-Based SQL Injection
You detect union-based SQL injection by watching for its signatures: the UNION SELECT keyword pair, column-count probing (repeated ORDER BY or NULL sequences), and bursts of near-identical requests from one source.
Most of these signals live in three places: application logs, web application firewall logs, and database query logs. The trick is capturing enough detail to see the payload, then alerting on the patterns that normal traffic never produces.
Watch for these signals:
- Query logs containing UNION SELECT, a climbing ORDER BY n, or long NULL, NULL sequences.
- Requests referencing information_schema, internal table names, or SQL comment markers (double dash, hash, or block comments).
- Spikes of similar requests to a single parameter, the fingerprint of automated tooling.
- Sudden changes in response size or unexpected columns appearing on a page.
A web application firewall running the OWASP Core Rule Set flags these patterns automatically, matching known SQL injection signatures in its 942xxx rule family with the libinjection engine. Because automated tools fire hundreds of probing requests, a strict Rate Limit on sensitive endpoints both slows discovery and surfaces the abnormal request volume in your metrics.
Detection tells you it is happening. Prevention makes sure it does not matter.
How to Prevent Union-Based SQL Injection
The definitive fix is to stop building queries from raw input. Parameterized queries (prepared statements) bind user input as data, so a UNION SELECT payload is treated as a literal string and never executed as SQL.
Layer the rest of your defenses around that core fix so a single missed query does not become a breach:
- Use parameterized queries or prepared statements everywhere user input meets SQL. This alone neutralizes the attack.
- Validate and allow-list input by type, length, and format before it reaches the data layer.
- Run the application on a least-privilege database account, read-only where possible.
- Disable detailed database error messages in production so nothing leaks to attackers.
- Add a web application firewall as a second layer to catch payloads that slip past code review.

One point trips up many teams. A network firewall solution controls traffic at the perimeter, but it inspects packets and ports, not SQL. Union-based payloads ride inside valid HTTP requests, so they pass straight through it and need application-layer defenses instead.
That safety net still earns its place, especially when it lives at the edge and can be tuned to your traffic.
How a WAF and OWASP CRS Stop UNION Attacks at the Edge
An edge web application firewall inspects every incoming request before it reaches your origin, blocking UNION SELECT patterns, schema-probing, and NULL-padding with rule sets like the OWASP Core Rule Set.
The Core Rule Set groups its SQL injection defenses in the 942xxx rule family, pairing the libinjection engine with pattern rules to score suspicious requests, in line with OWASP’s SQL injection guidance. At the default paranoia level, common UNION and boolean payloads are caught; higher paranoia levels catch more at the cost of more false positives.
Off-the-shelf rules cover the common cases, but every application is different. The option to Customize WAF packages lets you add rules for your own parameters, tune paranoia levels, and cut false positives without lowering protection.
The Bottom Line on Slowloris Attack
Union-based SQL injection is dangerous because it is direct and fast, but it depends on one weakness you fully control: queries that treat user input as code. Close that gap with parameterized queries and the attack loses its footing. Everything else, from input validation to least-privilege accounts to edge filtering, hardens the result and buys time when something is missed.
Treat it as a layered problem. Fix the code first, then let a well-tuned web application firewall catch what slips through. Strong data protection and a fast, reliable site are not a trade-off; the same disciplined query handling that blocks injection also keeps your database queries lean.
Frequently Asked Questions About Slowloris Attack
Is union-based SQL injection still a threat?
Yes. It remains common wherever applications build SQL from unsanitized input. SQL injection has stayed in the OWASP Top 10 for two decades, and breaches like TalkTalk’s show the impact is severe.
What is the difference between union-based and blind SQL injection?
Union-based injection returns stolen data directly in the page using UNION SELECT, so it is fast. Blind injection returns no data; the attacker infers values from true/false behavior or response timing, which is far slower.
How do attackers find the number of columns for a UNION attack?
They probe it. Running ORDER BY 1, ORDER BY 2, and upward until the query errors reveals the count, as does adding UNION SELECT NULL, NULL, … until the statement succeeds.
Can a web application firewall alone stop union-based SQL injection?
A WAF blocks most automated and signature-based attempts, but determined attackers use encoding and comment tricks to evade rules. Parameterized queries in the application code are the reliable fix, and the WAF is a strong second layer.