Nedávno se ve full-disclosure mailing-listu objevila zpráva o heap-overflow zranitelnosti v parsování ASN.1 v OpenSSL. Zranitelnost je složena ze dvou částí:
- Při konverzi long -> int na x86_64 architektuře dochází k ořezání nejvyšších 32 bitů, výsledek se uloží do 32-bit integeru se znaménkem. Použitím DER-enkódovaného certifikátu, který má nějaký length-field s bitem 32 nastaveným, dojde k přetečení do záporných čísel.
- Funkce realloc() podle C99. standardu musí umět jak paměť alokovaného bloku zvětšit, tak zmenšit. Problém spočívá v tom, že obdobná funkce CRYPTO_realloc_clean() v OpenSSL nepodporuje zmenšení bloku. Pokud je nová délka alokovaného bloku menší než původní délka, část paměti za alokovaným bufferem se přepíše bajty navíc z původního bloku.
Kombinací obou chyb lze část paměti přepsat „speciálně formovaným“ certifikátem. Chybu je poměrně těžké zneužít, ale rozhodně to není nemožné. Týká se funkcí pojmenovaných d2i_*_bio a d2i_*_fp (a pár dalších pracujících s CMS a S/MIME).
Zatím probíhá šetření, který software používající OpenSSL je chybou ovlivněn. V tuto chvíli jsou chyby s největší pravděpodobností vyloučeny u:
- OpenSSH – používá vlastní kód pro parsování ASN.1
- Tor – používá in-memory d2i_* a PEM_* funkce, žádné z napadnutelných
- DNSSEC Validator – ASN.1 parsování se vůbec nepoužívá
- dslib – openssl se vůbec nepoužívá, ASN.1 parsování dělá pyasn1
- datovka – potenciálně zranitelná funkce OpenSSL.crypto.load_pkcs12 se nachází jen u načtení vašeho certifikátu z disku (tudíž dokud ho někdo nezmění, nic se nestane; navíc používá se jenom při přihlašovaní certifikátem)
- Knot DNS 1.0.3 – žádná zranitelná funkce se nevolá
- Firefox 11, Thunderbird 11.0.1 (komponenty NSS, NSPR a XulRunner) – Firefox i Thunderbird mají ale spoustu závislostí; je teoreticky možné, že jsem něco přehlédnul
- Apache 2.4.2, nginx 1.0.15 a 1.1.19, lighttpd 1.4.30 – používají některé ze zranitelných funkcí, ale jenom při čtení certifikátů z disku
Další pár očí pro kontrolu samozřejmě neuškodí. Statickou analýzou kódu jsem vytvořil call-graph a regexp, kterým lze ověřit, jestli nějaký kód volající funkce openssl používá potenciálně zranitelné funkce. Bugy jsou opraveny ve verzích openssl 1.0.1a, 1.0.0i or 0.9.8v. Jeden způsob, jak zmírnit dopad chyby v openssl (i budoucí), je použití stunnel v jail-u, ale má to některé další nevýhody jako těžší zpracování logů.
Další zajímavý fakt je, že tato konkrétní chyba (bez části o realloc()) byla publikována v roce 2006 v knize The Art of Software Security Assessment: Identifying and Preventing Software Vulnerabilities. Zde je fotografie stránek se zmíněnou chybou (konverze long -> int). Nicméně to není první ani poslední „znovuobjevený“ bug v softwaru.
Ondrej Mikle