Bazen bir açık ilk bakışta küçük görünüyor. Basit bir input validation eksikliği gibi. Ama akışın nereye çıktığını takip edince etkisinin düşündüğünden daha büyük olduğu ortaya çıkıyor. Craft Agent'ta bulduğum bu açık da tam olarak böyleydi.

Sorun, Electron main process tarafındaki STORE_ATTACHMENT IPC handler'da yer alıyordu. Kullanıcıdan gelen sessionId değeri yeterince doğrulanmadan dosya yolu oluşturma sürecine giriyordu. Bu da uygulamanın yazması gereken dizinin dışına çıkılmasına izin veriyordu.

Normal şartlarda attachment dosyalarının workspace altındaki ilgili session klasörüne yazılması bekleniyor. Ama sessionId içine ../../../../tmp gibi bir değer girdiğinde, oluşan path beklenen dizinin dışına taşıyor. Sonuç olarak uygulamanın erişebildiği başka konumlara dosya yazılabiliyor.

Buradaki mesele sadece dosyanın yanlış klasöre kaydedilmesi değil. Doğrudan arbitrary file write etkisi var.

Sorun nerede ortaya çıkıyor?

Açık, STORE_ATTACHMENT IPC handler içinde ortaya çıkıyor. sessionId kullanıcı kontrollü geliyor ve bu değer getSessionAttachmentsPath() içine aktarılıyor. Path oluşturulurken de path.join() kullanılıyor.

Asıl problem burada başlıyor. path.join() bir güvenlik kontrolü değil. İçindeki .. bileşenlerini çözüyor. Yani saldırgan kontrollü sessionId traversal içeriyorsa, ortaya çıkan path kolayca hedef dizinin dışına çıkabiliyor.

Bu durumda uygulama attachment içeriğini olması gereken session dizinine değil, saldırganın yönlendirdiği başka bir konuma yazıyor.

Etki neden kritik?

En net sonuç şu: Craft Agent sürecinin yazabildiği yerlere dosya bırakmak mümkün hale geliyor.

Bu tek başına zaten ciddi. Ama etkisi bununla sınırlı kalmayabilir. Eğer yazılabilen konumlardan biri startup dizini, shell profile dosyası ya da otomatik çalışan başka bir yol ise, açık code execution tarafına kadar gidebilir. Daha düşük etkili senaryolarda bile mevcut dosyaların ezilmesi, bozulması ya da uygulama davranışının değiştirilmesi mümkün.

Yani bu açık, teknik olarak path traversal olsa da pratik etkisi çok daha ağır sonuçlar doğurabilecek türden.

Saldırı vektörü

Açık, Electron IPC bridge üzerinden sömürülebiliyor. Yani saldırganın STORE_ATTACHMENT kanalına crafted bir IPC mesajı göndermesi ve içine kötü niyetli bir sessionId koyması yeterli.

Electron uygulamalarda renderer ile main process arasındaki sınır zaten kritik. Bu sınırda validation eksik bırakıldığında, dosya sistemi işlemleri gibi hassas noktalar doğrudan riskli hale geliyor.

PoC mantığı

PoC tarafı oldukça net.

sessionId olarak şu tarz bir değer kullanıldığında:

../../../../../../../../tmp

dosyalar beklenen:

sessions/<sessionId>/attachments/

yapısı altına değil, doğrudan:

/tmp/attachments/

altına yazılabiliyor.

Bu da traversal'ın gerçekten çalıştığını ve path'in intended directory dışına çıktığını açık şekilde gösteriyor.

Kök neden

Kök neden klasik ama etkili: güvenilmeyen input'un doğrulama olmadan dosya sistemi operasyonuna taşınması.

sessionId burada güvenli bir identifier gibi ele alınmış. Oysa dışarıdan gelen her değer potansiyel olarak saldırgan kontrollüdür. Böyle bir değeri validation olmadan path üretiminde kullanınca, saldırı yüzeyi doğrudan açılmış oluyor.

Bu açıkta da olan şey tam olarak buydu.

Fix nasıl geldi?

Düzeltme tarafında tek katmanlı bir yaklaşım tercih edilmemiş.

İlk olarak validateSessionId() ile input validation eklenmiş. sessionId artık allowlist mantığında kontrol ediliyor. Buna ek olarak path.basename(sessionId) === sessionId doğrulaması yapılıyor. Böylece traversal içeren değerler daha dosya işlemleri başlamadan engelleniyor.

İkinci olarak getSessionPath() tarafında ek bir sanitization katmanı var. sanitizeSessionId() ya da path.basename() ile değer tekrar temizleniyor. Yani validation katmanı bir şekilde atlatılsa bile altta ikinci bir koruma daha bulunuyor.

Bu yaklaşım önemli. Çünkü dosya sistemiyle çalışan kodda tek bir kontrol noktasına güvenmek çoğu zaman yeterli olmuyor.

Neden önemli?

Bu açık, temel bir güvenlik hatasının masaüstü uygulamalarda ne kadar ciddi etki yaratabildiğini gösteriyor.

Path traversal yeni bir zafiyet sınıfı değil. Ama Electron uygulamalarda, özellikle IPC handler'larında, hâlâ yüksek etkiyle karşımıza çıkabiliyor. Buradaki örnek de bunu net biçimde gösteriyor: dışarıdan gelen bir değer, yeterli kontrol olmadan filesystem path'ine giriyor ve güven sınırı kırılıyor.

Kodun küçük bir parçası gibi görünse de etkisi oldukça büyük.

Referanslar