☑️Attacks
SQLMap on HTTP
One of the best and easiest ways to properly set up an SQLMap request against the specific target (i.e., web request with parameters inside) is by utilizing Copy as cURL feature from within the Network (Monitor) panel inside the Chrome, Edge, or Firefox Developer Tools:

By pasting the clipboard content (Ctrl-V) into the command line, and changing the original command curl to sqlmap, we are able to use SQLMap with the identical curl command:
GET/POST Request
In the most common scenario, GET parameters are provided with the usage of option -u/--url, as in the previous example. As for testing POST data, the --data flag can be used, as follows:
In such cases, POST parameters uid and name will be tested for SQLi vulnerability. For example, 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 * as follows:
Using request file for long HTTP requests
If we need to specify a complex HTTP request with lots of different header values and an elongated POST body, we can use the -r flag. With this option, SQLMap is provided with the "request file," containing the whole HTTP request inside a single textual file. In a common scenario, such HTTP request can be captured from within a specialized proxy application (e.g. Burp) and written into the request file, as follows:

Making Custom SQLMap Requests
If we wanted to craft complicated requests manually, there are numerous switches and options to fine-tune SQLMap.
For example, if there is a requirement to specify the (session) cookie value to PHPSESSID=ab4530f4a7d10448457fa8b0eadac29c option --cookie would be used as follows:
The same effect can be done with the usage of option -H/--header:
We can apply the same to options like --host, --referer, and -A/--user-agent, which are used to specify the same HTTP headers' values.
Furthermore, there is a switch --random-agent designed to randomly select a User-agent header value from the included database of regular browser values. This is an important switch to remember, as more and more protection solutions automatically drop all HTTP traffic containing the recognizable default SQLMap's User-agent value (e.g. User-agent: sqlmap/1.4.9.12#dev (http://sqlmap.org)). Alternatively, the --mobile switch can be used to imitate the smartphone by using that same header value.
Targetting Header Values for SQLi
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.
Also, if we wanted to specify an alternative HTTP method, other than GET and POST (e.g., PUT), we can utilize the option --method, as follows:
JSON/XML Requests
Apart from the most common form-data POST body style (e.g. id=1), SQLMap also supports JSON formatted (e.g. {"id":1}) and XML formatted (e.g. <element><id>1</id></element>) HTTP requests.
Support for these formats is implemented in a "relaxed" manner; thus, there are no strict constraints on how the parameter values are stored inside. In case the POST body is relatively simple and short, the option --data will suffice.
However, in the case of a complex or long POST body, we can once again use the -r option:
SQLMap Handling Errors
Display Errors
The first step is usually to switch the --parse-errors, to parse the DBMS errors (if any) and displays them as part of the program run:
With this option, SQLMap will automatically print the DBMS error, thus giving us clarity on what the issue may be so that we can properly fix it.
Storing the Traffic
The -t option stores the whole traffic content to an output file:
Verbose Output
Another useful flag is the -v option, which raises the verbosity level of the console output:
As we can see, the -v 6 option will directly print all errors and full HTTP request to the terminal so that we can follow along with everything SQLMap is doing in real-time.
Using Proxy
Finally, we can utilize the --proxy option to redirect the whole traffic through a (MiTM) proxy (e.g., Burp). This will route all SQLMap traffic through Burp, so that we can later manually investigate all requests, repeat them, and utilize all features of Burp with these requests:

Attack Tuning
In most cases, SQLMap should run out of the box with the provided target details. Nevertheless, there are options to fine-tune the SQLi injection attempts to help SQLMap in the detection phase. Every payload sent to the target consists of:
vector (e.g.,
UNION ALL SELECT 1,2,VERSION()): central part of the payload, carrying the useful SQL code to be executed at the target.boundaries (e.g.
'<vector>-- -): prefix and suffix formations, used for proper injection of the vector into the vulnerable SQL statement.
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 as follows:
This will result in an enclosure of all vector values between the static prefix %')) and the suffix -- -.
For example, if the vulnerable code at the target is:
The vector UNION ALL SELECT 1,2,VERSION(), bounded with the prefix %')) and the suffix -- -, will result in the following (valid) SQL statement at the target:
Level/Risk
By default, SQLMap combines a predefined set of most common boundaries (i.e., prefix/suffix pairs), along with the vectors having a high chance of success in case of a vulnerable target. Nevertheless, there is a possibility for users to use bigger sets of boundaries and vectors, already incorporated into the SQLMap.
For such demands, the options --level and --risk should be used:
The option
--level(1-5, default1) extends both vectors and boundaries being used, based on their expectancy of success (i.e., the lower the expectancy, the higher the level).The option
--risk(1-3, default1) extends the used vector set based on their risk of causing problems at the target side (i.e., risk of database entry loss or denial-of-service).
The best way to check for differences between used boundaries and payloads for different values of --level and --risk, is the usage of -v option to set the verbosity level. In verbosity 3 or higher (e.g. -v 3), messages containing the used [PAYLOAD] will be displayed, as follows:
On the other hand, payloads used with the default --level value have a considerably smaller set of boundaries:
As for vectors, we can compare used payloads as follows:
As for the number of payloads, by default (i.e. --level=1 --risk=1), the number of payloads used for testing a single parameter goes up to 72, while in the most detailed case (--level=5 --risk=3) the number of payloads increases to 7,865.
As SQLMap is already tuned to check for the most common boundaries and vectors, regular users are advised not to touch these options because it will make the whole detection process considerably slower. Nevertheless, in special cases of SQLi vulnerabilities, where usage of OR payloads is a must (e.g., in case of login pages), we may have to raise the risk level ourselves.
This is because OR payloads are inherently dangerous in a default run, where underlying vulnerable SQL statements (although less commonly) are actively modifying the database content (e.g. DELETE or UPDATE).
Advanced Tuning
To further fine-tune the detection mechanism, there is a hefty set of switches and options. In regular cases, SQLMap will not require its usage. Still, we need to be familiar with them so that we could use them when needed.
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
In some special cases, we have to narrow down the used payloads only to a certain type. For example, if the time-based blind payloads are causing trouble in the form of response timeouts, or if we want to force the usage of a specific SQLi payload type, the option --technique can specify the SQLi technique to be used.
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).
Failing to use the proper FROM appendix automatically could be due to the inability to detect the DBMS name before its usage.
Last updated