Bir şirketin satın alma akışını düşünün: tedarikçi faturayı PDF olarak yüklüyor, onaylayan kişi açıp bakıyor, uygun görürse onaylıyor, sonra muhasebe tarafındaki bir araç aynı dosyadan tutarı okuyup ödeme kaydını açıyor. Burada sessiz bir varsayım var: herkes aynı dosyaya baktığına göre aynı rakamı görür. Oysa bu her zaman doğru değil.
PDF tek katman değil
PDF göründüğünden daha karışık bir format. Bir form alanının iki ayrı temsili olabilir: alanın düz “değeri” ve o alanın ekrana nasıl çizileceğini anlatan ayrı bir “görünüm” akışı. Normalde ikisi aynı şeyi söyler. Ama her görüntüleyici ikisine aynı önemi vermez. Bazı okuyucular görünüm akışını çizer, bazıları onu yok sayıp düz değeri gösterir.
İşte bütün mesele bu küçük ayrımda. Bir saldırgan alanın düz değerine düşük bir tutar (örneğin 399), görünüm akışına ise yüksek bir tutar (999) koyarsa, aynı dosya açan programa göre iki ayrı rakam söyler.
İlk deneme neden tutmaz
Bunu denemek isteyen biri önce en bariz yolu dener: bir PDF kütüphanesiyle alanın değerini değiştirmek. Ama bu çoğu kütüphanede işe yaramaz, çünkü değeri değiştirince kütüphane alanın görünümünü de kendiliğinden yeniden üretir; iki kısım yine aynı tutarı gösterir, çelişki kaybolur.
İşe yarayan yol, bu otomatik üretimi devre dışı bırakıp görünüm akışını elle yazmaktır. Değer alanında 399 kalır, ama ekrana çizilen akışı saldırgan kendisi hazırlar ve oraya 999 koyar.
Sonuç: dosya açana göre konuşuyor
Böyle hazırlanmış bir dosya, masaüstü görüntüleyicilerde ve hızlı önizlemelerde düz değeri (399), tarayıcı tabanlı ve bulut önizlemelerinde ise görünüm akışını (999) gösterir. Aynı dosya, açan programa göre farklı konuşur.
İşin bugün en can alıcı yanı, araya otomatik bir okuyucu girince ortaya çıkıyor. Bir belgeyi özetleyen yapay zeka araçları çoğunlukla görünüm akışını işlemez, yalnızca düz değeri okur. Yani insan gözünün gördüğüyle, akışı otomatik işleyen tarafın okuduğu rakam birbirinden ayrılır.
Bu senaryoda onaylayan kişi 399’luk bir fatura görüp içi rahat onaylar, ödeme tarafındaki araç aynı dosyadan 999 okuyup o tutarı işler. Kimse sahte bir belge görmez; herkes kendi programının gösterdiğine bakar ve o programlar aynı dosyadan farklı şeyler okur.
Asıl fikir: ayrıştırma farkı
Bu numara aslında PDF’e özel değil. Altında yatan fikir şu: bir veriyi iki ayrı program okuyorsa, ikisinin onu birebir aynı anladığını kimse garanti etmez. İki okuyucu arasındaki en küçük yorum farkı bir boşluktur. Güvenlikte buna kabaca “ayrıştırma farkı” (parser differential) denir.
Bir kez bu gözle bakmaya başlayınca aynı deseni başka yerlerde de görürsünüz. Tarayıcının bir çerezi ayrıştırmasıyla sunucunun aynı çerezi ayrıştırması tutmayabilir; bir e-posta adresini kayıt sisteminin okumasıyla erişim kontrolünün okuması farklı olabilir; bir HTTP isteğini öndeki sunucuyla arkadaki sunucunun bölmesi uyuşmayabilir. Hepsinde mantık aynı: iki ayrıştırıcı, tek girdi, çatlak ortada.
Savunan taraf için ders kısa: aynı veriye bakan iki bileşen varsa, ikisinin onu aynı okuduğundan emin olun. Bir belgeyi onaylayan göz ile o belgeyi işleyen sistem aynı kaynağı okumalı; özellikle bir belgeyi hem insana gösterip hem de otomatik bir araca özetlettiğiniz yerlerde.
Kaynak
Bu yazıdaki PDF görüntüleme farkı tekniği, PortSwigger Research’ün Fickle PDFs: exploiting browser rendering discrepancies araştırmasına dayanır. Teknik detay ve kavram kanıtı için orijinal yazıya bakabilirsiniz.