CSS Injection
Lerne & übe AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lerne & übe GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
CSS Injection
Attribut-Selektor
CSS-Selektoren sind so gestaltet, dass sie die Werte der name
- und value
-Attribute eines input
-Elements abgleichen. Wenn das value-Attribut des Eingabeelements mit einem bestimmten Zeichen beginnt, wird eine vordefinierte externe Ressource geladen:
Allerdings stößt dieser Ansatz auf eine Einschränkung, wenn es um versteckte Eingabeelemente (type="hidden"
) geht, da versteckte Elemente keine Hintergründe laden.
Umgehung für versteckte Elemente
Um diese Einschränkung zu umgehen, können Sie ein nachfolgendes Geschwisterelement mit dem ~
allgemeinen Geschwisterkombinator anvisieren. Die CSS-Regel wird dann auf alle Geschwister angewendet, die dem versteckten Eingabeelement folgen, wodurch das Hintergrundbild geladen wird:
Ein praktisches Beispiel für die Ausnutzung dieser Technik ist im bereitgestellten Code-Snippet detailliert beschrieben. Sie können es hier einsehen.
Voraussetzungen für CSS-Injection
Damit die CSS-Injection-Technik effektiv ist, müssen bestimmte Bedingungen erfüllt sein:
Payload-Länge: Der CSS-Injection-Vektor muss ausreichend lange Payloads unterstützen, um die gestalteten Selektoren unterzubringen.
CSS-Neubewertung: Sie sollten die Fähigkeit haben, die Seite einzurahmen, was notwendig ist, um die Neubewertung von CSS mit neu generierten Payloads auszulösen.
Externe Ressourcen: Die Technik setzt die Möglichkeit voraus, extern gehostete Bilder zu verwenden. Dies könnte durch die Content Security Policy (CSP) der Seite eingeschränkt sein.
Blinder Attributselektor
Wie in diesem Beitrag erklärt, ist es möglich, die Selektoren :has
und :not
zu kombinieren, um Inhalte sogar von blinden Elementen zu identifizieren. Dies ist sehr nützlich, wenn Sie keine Ahnung haben, was sich in der Webseite befindet, die die CSS-Injection lädt.
Es ist auch möglich, diese Selektoren zu verwenden, um Informationen aus mehreren Blöcken desselben Typs zu extrahieren, wie in:
Kombiniert man dies mit der folgenden @import-Technik, ist es möglich, eine Menge Info mit CSS-Injection von blinden Seiten zu exfiltrieren mit blind-css-exfiltration.
@import
Die vorherige Technik hat einige Nachteile, siehe die Voraussetzungen. Du musst entweder in der Lage sein, mehrere Links an das Opfer zu senden, oder du musst in der Lage sein, die CSS-Injection-anfällige Seite in ein Iframe zu laden.
Es gibt jedoch eine weitere clevere Technik, die CSS @import
verwendet, um die Qualität der Technik zu verbessern.
Dies wurde zuerst von Pepe Vila gezeigt und funktioniert so:
Anstatt die gleiche Seite immer wieder mit Dutzenden von verschiedenen Payloads zu laden (wie in der vorherigen), werden wir die Seite nur einmal und nur mit einem Import zum Server des Angreifers laden (das ist die Payload, die an das Opfer gesendet werden soll):
Der Import wird einige CSS-Skripte von den Angreifern empfangen und der Browser wird sie laden.
Der erste Teil des CSS-Skripts, den der Angreifer senden wird, ist ein weiteres
@import
zum Server des Angreifers.Der Server des Angreifers wird diese Anfrage noch nicht beantworten, da wir einige Zeichen leaken und dann diesen Import mit der Payload beantworten wollen, um die nächsten zu leaken.
Der zweite und größere Teil der Payload wird ein Attributselektor-Leakage-Payload sein.
Dies wird an den Server des Angreifers das erste Zeichen des Geheimnisses und das letzte senden.
Sobald der Server des Angreifers das erste und letzte Zeichen des Geheimnisses erhalten hat, wird er den Import, der in Schritt 2 angefordert wurde, beantworten.
Die Antwort wird genau die gleiche sein wie in den Schritten 2, 3 und 4, aber diesmal wird sie versuchen, das zweite Zeichen des Geheimnisses und dann das vorletzte zu finden.
Der Angreifer wird diesen Loop fortsetzen, bis es ihm gelingt, das Geheimnis vollständig zu leaken.
Sie können den ursprünglichen Code von Pepe Vila, um dies auszunutzen, hier finden oder Sie können fast den gleichen Code, aber kommentiert, hier finden.
Das Skript wird versuchen, jedes Mal 2 Zeichen zu entdecken (vom Anfang und vom Ende), da der Attributselektor es ermöglicht, Dinge zu tun wie:
Dies ermöglicht es dem Skript, das Geheimnis schneller zu leaken.
Manchmal erkennt das Skript nicht korrekt, dass das entdeckte Präfix + Suffix bereits die vollständige Flagge ist und es wird weiterhin vorwärts (im Präfix) und rückwärts (im Suffix) fortfahren und irgendwann wird es hängen bleiben. Keine Sorge, überprüfe einfach die Ausgabe, denn du kannst die Flagge dort sehen.
Andere Selektoren
Andere Möglichkeiten, um auf DOM-Teile mit CSS-Selektoren zuzugreifen:
.class-to-search:nth-child(2)
: Dies wird das zweite Element mit der Klasse "class-to-search" im DOM suchen.:empty
Selektor: Wird zum Beispiel in diesem Writeup** verwendet:**
Fehlerbasierte XS-Search
Referenz: CSS-basierter Angriff: Missbrauch von unicode-range von @font-face , Error-Based XS-Search PoC von @terjanq
Die allgemeine Absicht ist es, eine benutzerdefinierte Schriftart von einem kontrollierten Endpunkt zu verwenden und sicherzustellen, dass Text (in diesem Fall 'A') nur mit dieser Schriftart angezeigt wird, wenn die angegebene Ressource (favicon.ico
) nicht geladen werden kann.
Verwendung von benutzerdefinierten Schriftarten:
Eine benutzerdefinierte Schriftart wird mit der Regel
@font-face
innerhalb eines<style>
-Tags im<head>
-Bereich definiert.Die Schriftart heißt
poc
und wird von einem externen Endpunkt (http://attacker.com/?leak
) abgerufen.Die Eigenschaft
unicode-range
ist aufU+0041
gesetzt, um das spezifische Unicode-Zeichen 'A' anzusprechen.
Objektelement mit Fallback-Text:
Ein
<object>
-Element mitid="poc0"
wird im<body>
-Bereich erstellt. Dieses Element versucht, eine Ressource vonhttp://192.168.0.1/favicon.ico
zu laden.Die
font-family
für dieses Element ist auf'poc'
gesetzt, wie im<style>
-Bereich definiert.Wenn die Ressource (
favicon.ico
) nicht geladen werden kann, wird der Fallback-Inhalt (der Buchstabe 'A') innerhalb des<object>
-Tags angezeigt.Der Fallback-Inhalt ('A') wird mit der benutzerdefinierten Schriftart
poc
gerendert, wenn die externe Ressource nicht geladen werden kann.
Styling Scroll-to-Text Fragment
Die :target
Pseudo-Klasse wird verwendet, um ein Element auszuwählen, das durch einen URL-Fragment angesprochen wird, wie in der CSS Selectors Level 4-Spezifikation angegeben. Es ist wichtig zu verstehen, dass ::target-text
keine Elemente übereinstimmt, es sei denn, der Text wird ausdrücklich durch das Fragment angesprochen.
Ein Sicherheitsproblem entsteht, wenn Angreifer die Scroll-to-text Fragmentfunktion ausnutzen, die es ihnen ermöglicht, das Vorhandensein bestimmter Texte auf einer Webseite zu bestätigen, indem sie eine Ressource von ihrem Server durch HTML-Injection laden. Die Methode besteht darin, eine CSS-Regel wie diese einzufügen:
In solchen Szenarien, wenn der Text "Administrator" auf der Seite vorhanden ist, wird die Ressource target.png
vom Server angefordert, was auf die Anwesenheit des Textes hinweist. Eine Instanz dieses Angriffs kann durch eine speziell gestaltete URL ausgeführt werden, die das injizierte CSS zusammen mit einem Scroll-to-text-Fragment einbettet:
Hier manipuliert der Angriff die HTML-Injektion, um den CSS-Code zu übertragen, der auf den spezifischen Text "Administrator" abzielt, durch den Scroll-to-text-Fragment (#:~:text=Administrator
). Wenn der Text gefunden wird, wird die angegebene Ressource geladen, was unbeabsichtigt ihre Präsenz an den Angreifer signalisiert.
Zur Minderung sollten die folgenden Punkte beachtet werden:
Eingeschränkte STTF-Übereinstimmung: Das Scroll-to-text-Fragment (STTF) ist so konzipiert, dass es nur Wörter oder Sätze übereinstimmt, wodurch seine Fähigkeit, beliebige Geheimnisse oder Tokens zu leaken, eingeschränkt wird.
Einschränkung auf Top-Level-Browsing-Kontexte: STTF funktioniert ausschließlich in Top-Level-Browsing-Kontexten und nicht innerhalb von iframes, wodurch jeder Versuch der Ausnutzung für den Benutzer auffälliger wird.
Notwendigkeit der Benutzeraktivierung: STTF erfordert eine Benutzeraktivierungs-Geste, um zu funktionieren, was bedeutet, dass Ausnutzungen nur durch benutzerinitiierte Navigationen möglich sind. Diese Anforderung verringert erheblich das Risiko, dass Angriffe automatisiert ohne Benutzerinteraktion durchgeführt werden. Dennoch weist der Autor des Blogbeitrags auf spezifische Bedingungen und Umgehungen hin (z. B. Social Engineering, Interaktion mit verbreiteten Browsererweiterungen), die die Automatisierung des Angriffs erleichtern könnten.
Das Bewusstsein für diese Mechanismen und potenziellen Schwachstellen ist entscheidend für die Aufrechterhaltung der Websicherheit und den Schutz vor solchen ausbeuterischen Taktiken.
Für weitere Informationen siehe den ursprünglichen Bericht: https://www.secforce.com/blog/new-technique-of-stealing-data-using-css-and-scroll-to-text-fragment-feature/
Sie können einen Exploit, der diese Technik für ein CTF verwendet, hier überprüfen.
@font-face / unicode-range
Sie können externe Schriftarten für spezifische Unicode-Werte angeben, die nur gesammelt werden, wenn diese Unicode-Werte auf der Seite vorhanden sind. Zum Beispiel:
When you access this page, Chrome und Firefox holen "?A" und "?B", weil der Textknoten von sensitive-information die Zeichen "A" und "B" enthält. Aber Chrome und Firefox holen "?C" nicht, weil es "C" nicht enthält. Das bedeutet, dass wir "A" und "B" lesen konnten.
Textknoten-Exfiltration (I): Ligaturen
Referenz: Wykradanie danych w świetnym stylu – czyli jak wykorzystać CSS-y do ataków na webaplikację
Die beschriebene Technik beinhaltet das Extrahieren von Text aus einem Knoten, indem Schriftligaturen ausgenutzt und Änderungen in der Breite überwacht werden. Der Prozess umfasst mehrere Schritte:
Erstellung von benutzerdefinierten Schriftarten:
SVG-Schriftarten werden mit Glyphen erstellt, die ein
horiz-adv-x
-Attribut haben, das eine große Breite für ein Glyphen darstellt, das eine zweiziffrige Sequenz repräsentiert.Beispiel SVG-Glyph:
<glyph unicode="XY" horiz-adv-x="8000" d="M1 0z"/>
, wobei "XY" eine zweiziffrige Sequenz bezeichnet.Diese Schriftarten werden dann mit fontforge in das woff-Format konvertiert.
Erkennung von Breitenänderungen:
CSS wird verwendet, um sicherzustellen, dass der Text nicht umbricht (
white-space: nowrap
) und um den Stil der Bildlaufleiste anzupassen.Das Erscheinen einer horizontalen Bildlaufleiste, die deutlich gestaltet ist, fungiert als Indikator (Orakel), dass eine bestimmte Ligatur und damit eine bestimmte Zeichenfolge im Text vorhanden ist.
Das verwendete CSS:
Exploit-Prozess:
Schritt 1: Schriftarten werden für Zeichenpaare mit erheblicher Breite erstellt.
Schritt 2: Ein trick mit der Bildlaufleiste wird verwendet, um zu erkennen, wann das Glyph mit großer Breite (Ligatur für ein Zeichenpaar) gerendert wird, was auf die Anwesenheit der Zeichenfolge hinweist.
Schritt 3: Nach der Erkennung einer Ligatur werden neue Glyphen generiert, die dreiziffrige Sequenzen darstellen, wobei das erkannte Paar und ein vorangestelltes oder nachgestelltes Zeichen hinzugefügt werden.
Schritt 4: Die Erkennung der dreiziffrigen Ligatur wird durchgeführt.
Schritt 5: Der Prozess wiederholt sich und enthüllt schrittweise den gesamten Text.
Optimierung:
Die aktuelle Initialisierungsmethode mit
<meta refresh=...
ist nicht optimal.Ein effizienterer Ansatz könnte den CSS
@import
-Trick beinhalten, um die Leistung des Exploits zu verbessern.
Textknoten-Exfiltration (II): Leaking des Zeichensatzes mit einer Standard-Schriftart (ohne externe Assets)
Referenz: PoC using Comic Sans by @Cgvwzq & @Terjanq
Dieser Trick wurde in diesem Slackers-Thread veröffentlicht. Der Zeichensatz, der in einem Textknoten verwendet wird, kann unter Verwendung der Standard-Schriftarten, die im Browser installiert sind, geleakt werden: keine externen - oder benutzerdefinierten - Schriftarten sind erforderlich.
Das Konzept dreht sich darum, eine Animation zu nutzen, um die Breite eines div
schrittweise zu erweitern, sodass jeweils ein Zeichen von dem 'Suffix'-Teil des Textes in den 'Präfix'-Teil übergeht. Dieser Prozess teilt den Text effektiv in zwei Abschnitte:
Präfix: Die erste Zeile.
Suffix: Die nachfolgende(n) Zeile(n).
Die Übergangsphasen der Zeichen würden wie folgt erscheinen:
C ADB
CA DB
CAD B
CADB
Während dieses Übergangs wird der unicode-range-Trick verwendet, um jedes neue Zeichen zu identifizieren, während es dem Präfix beitritt. Dies wird erreicht, indem die Schriftart auf Comic Sans gewechselt wird, die deutlich höher ist als die Standard-Schriftart, was eine vertikale Bildlaufleiste auslöst. Das Erscheinen dieser Bildlaufleiste offenbart indirekt die Anwesenheit eines neuen Zeichens im Präfix.
Obwohl diese Methode die Erkennung einzigartiger Zeichen ermöglicht, während sie erscheinen, gibt sie nicht an, welches Zeichen wiederholt wird, sondern nur, dass eine Wiederholung stattgefunden hat.
Im Grunde wird der unicode-range verwendet, um ein Zeichen zu erkennen, aber da wir keine externe Schriftart laden wollen, müssen wir einen anderen Weg finden. Wenn das Zeichen gefunden wird, erhält es die vorinstallierte Comic Sans-Schriftart, die das Zeichen größer macht und eine Bildlaufleiste auslöst, die das gefunden Zeichen leakt.
Überprüfen Sie den aus der PoC extrahierten Code:
Textnode-Exfiltration (III): Leaking des Zeichensatzes mit einer Standard-Schriftart durch Verstecken von Elementen (ohne externe Assets)
Referenz: Dies wird als eine erfolglose Lösung in diesem Bericht erwähnt
Dieser Fall ist sehr ähnlich zum vorherigen, jedoch besteht in diesem Fall das Ziel darin, spezifische Zeichen größer als andere zu machen, um etwas wie einen Button zu verstecken, der nicht vom Bot gedrückt werden soll, oder ein Bild, das nicht geladen wird. So könnten wir die Aktion (oder das Fehlen der Aktion) messen und wissen, ob ein spezifisches Zeichen im Text vorhanden ist.
Textnode-Exfiltration (III): Leaking des Zeichensatzes durch Cache-Timing (ohne externe Assets)
Referenz: Dies wird als eine erfolglose Lösung in diesem Bericht erwähnt
In diesem Fall könnten wir versuchen zu leaken, ob ein Zeichen im Text vorhanden ist, indem wir eine gefälschte Schriftart aus demselben Ursprung laden:
Wenn es eine Übereinstimmung gibt, wird die Schriftart von /static/bootstrap.min.css?q=1
geladen. Obwohl sie nicht erfolgreich geladen wird, sollte der Browser sie cachen, und selbst wenn es keinen Cache gibt, gibt es einen 304 not modified Mechanismus, sodass die Antwort schneller sein sollte als andere Dinge.
Wenn der Zeitunterschied der zwischengespeicherten Antwort zur nicht zwischengespeicherten nicht groß genug ist, wird dies jedoch nicht nützlich sein. Zum Beispiel erwähnte der Autor: Nach Tests stellte ich fest, dass das erste Problem darin besteht, dass die Geschwindigkeit nicht viel anders ist, und das zweite Problem ist, dass der Bot das disk-cache-size=1
Flag verwendet, was wirklich durchdacht ist.
Textknoten-Exfiltration (III): Leaking des Zeichensatzes durch zeitgesteuertes Laden von Hunderten von lokalen "Schriftarten" (ohne externe Assets)
Referenz: Dies wird als eine erfolglose Lösung in diesem Bericht erwähnt
In diesem Fall können Sie CSS angeben, um Hunderte von gefälschten Schriftarten aus demselben Ursprung zu laden, wenn eine Übereinstimmung auftritt. Auf diese Weise können Sie die Zeit messen, die benötigt wird, und herausfinden, ob ein Zeichen erscheint oder nicht, mit etwas wie:
Und der Code des Bots sieht so aus:
So, wenn die Schriftart nicht übereinstimmt, wird die Antwortzeit beim Besuch des Bots voraussichtlich etwa 30 Sekunden betragen. Wenn jedoch eine Schriftartübereinstimmung vorliegt, werden mehrere Anfragen gesendet, um die Schriftart abzurufen, was zu kontinuierlicher Aktivität im Netzwerk führt. Infolgedessen dauert es länger, die Stoppbedingung zu erfüllen und die Antwort zu erhalten. Daher kann die Antwortzeit als Indikator verwendet werden, um festzustellen, ob eine Schriftartübereinstimmung vorliegt.
References
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking:
HackTricks Training GCP Red Team Expert (GRTE)
Last updated