CSS Injection
Last updated
Last updated
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE) GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
CSS seçicileri, bir input
öğesinin name
ve value
özniteliklerinin değerleriyle eşleşecek şekilde oluşturulmuştur. Eğer input öğesinin value özniteliği belirli bir karakterle başlıyorsa, önceden tanımlanmış bir dış kaynak yüklenir:
Ancak, bu yaklaşım gizli giriş öğeleri (type="hidden"
) ile çalışırken bir sınıra sahiptir çünkü gizli öğeler arka planları yüklemez.
Bu sınırlamayı aşmak için, ~
genel kardeş kombinatörünü kullanarak bir sonraki kardeş öğeyi hedefleyebilirsiniz. CSS kuralı, gizli giriş öğesini takip eden tüm kardeşlere uygulanır ve arka plan resmi yüklenir:
A practical example of exploiting this technique is detailed in the provided code snippet. You can view it here.
CSS Enjeksiyonu tekniğinin etkili olabilmesi için belirli koşulların sağlanması gerekmektedir:
Yük Uzunluğu: CSS enjeksiyon vektörü, oluşturulmuş seçicileri barındıracak kadar uzun yükleri desteklemelidir.
CSS Yeniden Değerlendirmesi: Sayfayı çerçeveleme yeteneğine sahip olmalısınız; bu, yeni oluşturulmuş yüklerle CSS'nin yeniden değerlendirilmesini tetiklemek için gereklidir.
Dış Kaynaklar: Teknik, dışarıda barındırılan resimleri kullanma yeteneğini varsayar. Bu, sitenin İçerik Güvenlik Politikası (CSP) tarafından kısıtlanabilir.
As explained in this post, it's possible to combine the selectors :has
and :not
to identify content even from blind elements. This is very useful when you have no idea what is inside the web page loading the CSS injection.
It's also possible to use those selectors to extract information from several block of the same type like in:
Bunu aşağıdaki @import tekniği ile birleştirerek, gözlemci sayfalardan CSS enjeksiyonu kullanarak çok fazla bilgi sızdırmak mümkün blind-css-exfiltration.
Önceki tekniğin bazı dezavantajları vardır, ön koşulları kontrol edin. Ya kurbanın birden fazla bağlantı alabilmesi gerekir, ya da CSS enjeksiyonu zafiyeti olan sayfayı iframe'leyebilmeniz gerekir.
Ancak, tekniğin kalitesini artırmak için CSS @import
kullanan başka bir akıllı teknik vardır.
Bu ilk olarak Pepe Vila tarafından gösterildi ve şöyle çalışır:
Her seferinde on farklı yük ile aynı sayfayı tekrar tekrar yüklemek yerine (öncekinde olduğu gibi), sayfayı sadece bir kez ve sadece saldırganın sunucusuna bir import ile yükleyeceğiz (bu, kurbana gönderilecek yük):
İthalat, saldırganlardan bazı CSS scriptleri alacak ve tarayıcı bunu yükleyecek.
Saldırganın göndereceği CSS scriptinin ilk kısmı, saldırganın sunucusuna tekrar başka bir @import
olacak.
Saldırganın sunucusu bu isteğe henüz yanıt vermeyecek, çünkü bazı karakterleri sızdırmak istiyoruz ve ardından bu ithalatı, sonraki karakterleri sızdırmak için yük ile yanıtlayacağız.
Yükün ikinci ve daha büyük kısmı, bir nitelik seçici sızıntı yükü olacak.
Bu, saldırganın sunucusuna sırrın ilk karakterini ve son karakterini gönderecek.
Saldırganın sunucusu sırrın ilk ve son karakterini aldıktan sonra, adım 2'de talep edilen ithalata yanıt verecek.
Yanıt, adım 2, 3 ve 4'tekiyle tam olarak aynı olacak, ancak bu sefer sırrın ikinci karakterini ve ardından sondan bir önceki karakteri bulmaya çalışacak.
Saldırgan, sırrı tamamen sızdırana kadar bu döngüyü takip edecek.
Orijinal Pepe Vila'nın bunu istismar etmek için kodunu burada bulabilirsiniz veya neredeyse aynı kodu ama yorumlu burada bulabilirsiniz.
Script, her seferinde 2 karakter keşfetmeye çalışacak (başlangıçtan ve sondan) çünkü nitelik seçici, şunları yapmaya izin veriyor:
Bu, scriptin sırrı daha hızlı sızdırmasına olanak tanır.
Bazen script önek + sonek'in zaten tam bayrak olduğunu doğru bir şekilde tespit etmez ve ileri (önek içinde) ve geri (sonek içinde) devam eder ve bir noktada takılır. Endişelenmeyin, sadece çıktıyı kontrol edin çünkü orada bayrağı görebilirsiniz.
CSS seçicileri ile DOM parçalarına erişmenin diğer yolları:
.class-to-search:nth-child(2)
: Bu, DOM'daki "class-to-search" sınıfına sahip ikinci öğeyi arar.
:empty
seçici: Örneğin bu yazıda** kullanılır:**
Referans: CSS tabanlı Saldırı: @font-face'in unicode-range'ini kötüye kullanma, Hata Tabanlı XS-Search PoC @terjanq tarafından
Genel amaç, kontrol edilen bir uç noktadan özel bir font kullanmak ve metnin (bu durumda, 'A') yalnızca belirtilen kaynak (favicon.ico
) yüklenemediğinde bu fontla görüntülenmesini sağlamaktır.
Özel Yazı Tipi Kullanımı:
Özel bir yazı tipi, <head>
bölümündeki bir <style>
etiketi içinde @font-face
kuralı kullanılarak tanımlanır.
Yazı tipinin adı poc
ve harici bir uç noktadan (http://attacker.com/?leak
) alınır.
unicode-range
özelliği, belirli Unicode karakteri 'A' hedef alınarak U+0041
olarak ayarlanmıştır.
Yedek Metin ile Nesne Elemanı:
<body>
bölümünde id="poc0"
olan bir <object>
elemanı oluşturulur. Bu eleman, http://192.168.0.1/favicon.ico
adresinden bir kaynak yüklemeye çalışır.
Bu eleman için font-family
, <style>
bölümünde tanımlandığı gibi 'poc'
olarak ayarlanmıştır.
Eğer kaynak (favicon.ico
) yüklenemezse, <object>
etiketinin içindeki yedek içerik (harf 'A') görüntülenir.
Harf 'A', harici kaynak yüklenemezse özel yazı tipi poc
kullanılarak render edilecektir.
:target
psödo-sınıfı, CSS Seçicileri Seviye 4 spesifikasyonu gereğince bir URL parçası tarafından hedeflenen bir elementi seçmek için kullanılır. ::target-text
'in, metin açıkça parça tarafından hedeflenmedikçe hiçbir elementi eşleşmeyeceğini anlamak önemlidir.
Saldırganların Kaydırma ile Metin parçası özelliğini kullanarak belirli bir metnin bir web sayfasında varlığını doğrulamak için HTML enjeksiyonu yoluyla kendi sunucularından bir kaynak yüklemelerine olanak tanıyan bir güvenlik endişesi ortaya çıkmaktadır. Yöntem, şu şekilde bir CSS kuralı enjekte etmeyi içerir:
Bu tür senaryolarda, sayfada "Administrator" metni varsa, target.png
kaynağı sunucudan talep edilir ve metnin varlığını gösterir. Bu saldırının bir örneği, enjekte edilen CSS'yi bir Scroll-to-text parçasıyla birlikte içeren özel olarak hazırlanmış bir URL aracılığıyla gerçekleştirilebilir:
Burada, saldırı CSS kodunu iletmek için HTML enjeksiyonunu manipüle ediyor ve "Administrator" metnini Scroll-to-text fragment (#:~:text=Administrator
) aracılığıyla hedef alıyor. Metin bulunursa, belirtilen kaynak yüklenir ve bu durum istemeden saldırgana varlığını sinyal eder.
Hafifletme için aşağıdaki noktalar dikkate alınmalıdır:
Sınırlı STTF Eşleşmesi: Scroll-to-text Fragment (STTF), yalnızca kelimeleri veya cümleleri eşleştirmek üzere tasarlanmıştır, bu nedenle rastgele sırların veya token'ların sızdırılma yeteneğini sınırlamaktadır.
Üst Düzey Tarayıcı Bağlamlarına Kısıtlama: STTF yalnızca üst düzey tarayıcı bağlamlarında çalışır ve iframe'ler içinde işlev görmez, bu da herhangi bir istismar girişimini kullanıcıya daha belirgin hale getirir.
Kullanıcı Etkileşimi Gerekliliği: STTF'nin çalışması için bir kullanıcı etkileşimi gereklidir, bu da istismarların yalnızca kullanıcı tarafından başlatılan gezintilerle mümkün olduğu anlamına gelir. Bu gereklilik, saldırıların kullanıcı etkileşimi olmadan otomatikleştirilme riskini önemli ölçüde azaltır. Bununla birlikte, blog yazısının yazarı, saldırının otomatikleştirilmesini kolaylaştırabilecek belirli koşulları ve geçiş yollarını (örneğin, sosyal mühendislik, yaygın tarayıcı uzantılarıyla etkileşim) belirtmektedir.
Bu mekanizmaların ve potansiyel zayıflıkların farkında olmak, web güvenliğini sağlamak ve bu tür istismar taktiklerine karşı korunmak için anahtardır.
Daha fazla bilgi için orijinal raporu kontrol edin: https://www.secforce.com/blog/new-technique-of-stealing-data-using-css-and-scroll-to-text-fragment-feature/
Bu teknikle bir CTF için bir istismar kontrol edebilirsiniz.
Sayfada mevcut olan unicode değerleri için yalnızca toplanacak olan belirli unicode değerleri için dış fontlar belirtebilirsiniz. Örneğin:
When you access this page, Chrome and Firefox fetch "?A" and "?B" because text node of sensitive-information contains "A" and "B" characters. But Chrome and Firefox do not fetch "?C" because it does not contain "C". This means that we have been able to read "A" and "B".
Reference: Wykradanie danych w świetnym stylu – czyli jak wykorzystać CSS-y do ataków na webaplikację
Açıklanan teknik, font ligatürlerini kullanarak bir düğümden metin çıkarmayı ve genişlikteki değişiklikleri izlemeyi içerir. Süreç birkaç adımdan oluşur:
Özel Fontların Oluşturulması:
İki karakter dizisini temsil eden bir glif için büyük bir genişlik ayarlayan horiz-adv-x
niteliğine sahip glifler ile SVG fontları oluşturulur.
Örnek SVG glifi: <glyph unicode="XY" horiz-adv-x="8000" d="M1 0z"/>
, burada "XY" iki karakter dizisini belirtir.
Bu fontlar daha sonra fontforge kullanılarak woff formatına dönüştürülür.
Genişlik Değişikliklerinin Tespiti:
Metnin sarılmamasını sağlamak için CSS kullanılır (white-space: nowrap
) ve kaydırıcı stilini özelleştirmek için.
Farklı bir şekilde stillendirilmiş yatay bir kaydırıcının görünümü, metinde belirli bir ligatürün ve dolayısıyla belirli bir karakter dizisinin mevcut olduğunun bir göstergesi (oracle) olarak işlev görür.
İlgili CSS:
Sömürü Süreci:
Adım 1: Genişliği büyük olan karakter çiftleri için fontlar oluşturulur.
Adım 2: Büyük genişlik glifinin (bir karakter çiftinin ligatürü) render edildiğini tespit etmek için kaydırıcı tabanlı bir hile kullanılır, bu da karakter dizisinin mevcut olduğunu gösterir.
Adım 3: Bir ligatür tespit edildiğinde, tespit edilen çifti içeren ve bir önceki veya sonraki karakter ekleyen üç karakter dizilerini temsil eden yeni glifler üretilir.
Adım 4: Üç karakter ligatürünün tespiti gerçekleştirilir.
Adım 5: Süreç tekrarlanır, metnin tamamı yavaş yavaş açığa çıkar.
Optimizasyon:
<meta refresh=...
kullanarak mevcut başlatma yöntemi optimal değildir.
Daha verimli bir yaklaşım, sömürünün performansını artıran CSS @import
hilesini içerebilir.
Reference: PoC using Comic Sans by @Cgvwzq & @Terjanq
Bu hile, bu Slackers thread içinde yayımlandı. Bir metin düğümünde kullanılan karakter seti, tarayıcıda yüklü olan varsayılan fontlar kullanılarak sızdırılabilir: dışarıdan -veya özel- fontlara ihtiyaç yoktur.
Kavram, bir div
'in genişliğini kademeli olarak artırmak için bir animasyon kullanmayı ve bir karakterin bir seferde 'suffix' kısmından 'prefix' kısmına geçiş yapmasını sağlamayı içerir. Bu süreç, metni iki bölüme ayırır:
Prefix: İlk satır.
Suffix: Sonraki satır(lar).
Karakterlerin geçiş aşamaları şu şekilde görünecektir:
C ADB
CA DB
CAD B
CADB
Bu geçiş sırasında, unicode-range trick kullanılarak her yeni karakterin prefix'e katılması tespit edilir. Bu, fontun Comic Sans'a değiştirilmesiyle gerçekleştirilir; bu font, varsayılan fonttan belirgin şekilde daha yüksektir ve dolayısıyla dikey bir kaydırıcıyı tetikler. Bu kaydırıcının görünümü, prefix'te yeni bir karakterin varlığını dolaylı olarak ortaya çıkarır.
Bu yöntem, benzersiz karakterlerin görünmesiyle tespit edilmesini sağlasa da, hangi karakterin tekrarlandığını belirtmez, yalnızca bir tekrarın gerçekleştiğini gösterir.
Temelde, unicode-range bir karakteri tespit etmek için kullanılır, ancak dış bir font yüklemek istemediğimiz için başka bir yol bulmamız gerekir. Karakter bulunduğunda, önceden yüklenmiş Comic Sans fontu ile verilir, bu da karakteri büyütür ve kaydırıcıyı tetikler; bu da bulunan karakteri sızdırır.
Check the code extracted from the PoC:
Referans: Bu, bu yazıda başarısız bir çözüm olarak belirtilmiştir
Bu durum, önceki duruma çok benziyor, ancak bu durumda belirli karakterleri diğerlerinden daha büyük yapmak, bir butonun bot tarafından basılmaması veya yüklenmeyecek bir görüntüyü gizlemek gibi bir amaca hizmet ediyor. Böylece eylemi (veya eylemsizliği) ölçebilir ve metin içinde belirli bir karakterin mevcut olup olmadığını bilebiliriz.
Referans: Bu, bu yazıda başarısız bir çözüm olarak belirtilmiştir
Bu durumda, metinde bir karakterin olup olmadığını sızdırmaya çalışabiliriz, aynı kaynaktan sahte bir font yükleyerek:
Eğer bir eşleşme varsa, font /static/bootstrap.min.css?q=1
'den yüklenecektir. Başarılı bir şekilde yüklenmeyecek olsa da, tarayıcı bunu önbelleğe almalıdır ve önbellek olmasa bile, 304 not modified mekanizması vardır, bu nedenle yanıt diğer şeylerden daha hızlı olmalıdır.
Ancak, önbellekli yanıt ile önbelleksiz yanıt arasındaki zaman farkı yeterince büyük değilse, bu faydalı olmayacaktır. Örneğin, yazar şunları belirtti: Ancak, test ettikten sonra, ilk sorunun hızın çok farklı olmadığı ve ikinci sorunun botun disk-cache-size=1
bayrağını kullanması olduğunu buldum, bu gerçekten düşünceli.
Referans: Bu, bu yazıda başarısız bir çözüm olarak belirtilmiştir
Bu durumda, bir eşleşme gerçekleştiğinde CSS'nin aynı kökenden yüzlerce sahte font yüklemesini belirtebilirsiniz. Bu şekilde, geçen süreyi ölçebilir ve bir karakterin görünüp görünmediğini şu şekilde bulabilirsiniz:
Ve botun kodu şöyle görünüyor:
So, eğer font eşleşmiyorsa, bota erişim sırasında yanıt süresinin yaklaşık 30 saniye olması beklenir. Ancak, eğer bir font eşleşmesi varsa, fontu almak için birden fazla istek gönderilecektir, bu da ağda sürekli bir aktivite olmasına neden olacaktır. Sonuç olarak, durdurma koşulunu tatmin etmek ve yanıt almak daha uzun sürecektir. Bu nedenle, yanıt süresi bir font eşleşmesi olup olmadığını belirlemek için bir gösterge olarak kullanılabilir.
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)