Kódování jako bezpečnostní hrozba

Taky vidíte posledních pár dní na stránce Ulož.to​ čínské znaky? Je to jedna z chyb, která může mít dopady na bezpečnost webu – to se už ale málo ví. O co jde?

Web Ulož.to na tomto místě má reklamu, ale při jejím umístění zanedbal několik zásad, tedy zejména určení znakové sady (např.: UTF-8, v tomto případě Windows-1250).

Chyba je konkrétně v souboru o2-search-bar2.html (archiv), který má reklamu zobrazit. Tato stránka nemá nikde definovanou znakovou sadu a tak se prohlížeč musí rozhodnout sám, jakou zvolí. Chrome na OS X se rozhodl pro UTF-16BE, nicméně protože soubor je ve skutečnosti v jiném kódování, zobrazily se nesmyslné čínské znaky.

A právě tato chyba jde zneužít pro útok. Pokud totiž není sada určena, může se do kódu vpašovat něco, co bude vypadat a fungovat jinak v každém kódování. 

Vytvořil jsem ukázkový příklad takové zákeřné stránky: danger-encoding.html. Nebojte se, tahle stránka je pouze ukázka, Vašemu počítači neublíží. Stránka se skládá ze dvou částí, každá je napsána v jiném kódování. Prohlížeč ale v jednom okamžiku dokáže porozumět pouze jednomu a to se použije.

Zákeřná stránka zobrazená v WIN-1250
Stejná zákeřná stránka, ale tentokrát zobrazená v kódování UTF-16 LE

A to může útočník ovlivnit (nejen) díky vlastnosti prohlížečů, které u IFRAME bez vlastní definice kódování nastaví kódování rodiče. Stejný kód načtený do stránek s různým kódováním:

Největší nebezpečí této chyby spočívá ve snadném obejití ochran, filtrů a escapování – takže útočník může za určitých okolností dostat na váš web obsah, který tam nechcete, stačí jen, aby ho tam dostal v jiném kódování a pak přiměl prohlížeč uživatele, aby jej v takovém kódování načetl.

Všechny léty prověřené escapovací funkce (htmlspecialchars()mysql_real_escape_string(),  ap.) totiž fungují pouze ve znakové sadě, kterou očekávají – nedokáží zneškodnit zákeřný kód, který se schován do jiné znakové sady.

Proto na svém webu pečlivě vyplňujte kódování. A nebo ještě lépe: nastavte si na serveru posílání výchozího kódování, pokud nebude určeno jinak:

  • Apache: AddDefaultCharset utf-8
  • Nginx: charset UTF-8;

Zajistíte tak, že kód bude aplikace na serveru zpracovávat ve stejném kódování jako prohlížeč uživatele a do kódu se tak nemůže schovat nic, co by prošlo běžnými filtry, pokud je používáte správně.

Důležité: Nepokoušejte se tento ověřený postup »inovovat« třeba snahou preventivně escapovat vstup pro všechna známá kódování. Jednak je jich opravdu hodně a na některé určitě zapomenenete, ale především si tím zaručeně data poškodíte.

Zkušenější čtenář správně namítne, že běžné escapovací funkce pro WIN-1250 zlikvidují nebezpečné znaky i v UTF-16 (byť jej zcela rozbijí). Ano, to je pravda, UTF-16 jsem zvolil pouze pro demonstraci. Útočník by si určitě zvolil UTF-7, které je bitově posunuté a jeho úmysl schová lépe.

Původně vydáno jako status na Facebooku.