Hlavní navigace

Bezpečnostní díra v Java knihovně ohrožuje stovky aplikací

9. 11. 2015

Sdílet

Stephen Breen z FoxGlove Security upozorňuje na velmi vážnou bezpečnostní chybu v Java knihovně, která postihuje aktuální verze aplikací jako WebLogic, WebSphere, JBoss, Jenkins, OpenMMS a mnoha dalších. Týká se totiž běžné Java knihovny, kterou řada aplikací používá.

Chyba umožňuje vzdálené exploitování a ovládnutí aplikací a přestože byla zveřejněna už před 9 měsíci, doposud neexistuje patch a nikdo problém neřeší. Nikdo tomu nedal slušivé jméno, nevyšly tisková zprávy a žádný z vývojářů velkých produktů o tom nepsal na svém blogu. Chyba přitom ohrožuje řadu velkých komerčních aplikací, ale i menší aplikace jednotlivých firem.

Našli jste v článku chybu?
  • Aktualita je stará, nové názory již nelze přidávat.
  • 9. 11. 2015 9:30

    Filip Jirsák
    Stříbrný podporovatel

    Zprávička zní dost neseriózně, když je v ní napsáno obecně „Java knihovna“ a nikde v ní není napsáno, která. Ještě pozoruhodnější je, že ta knihovna není pořádně identifikována ani v odkazovaném článku. Pravděpodobně se jedná o knihovnu Apache Commons Collection (dříve součást Apache Jakarta). Navíc podle toho popisu má být chyba v implementaci readObject(), přičemž nikde není popsané, v čem přesně má chyba spočívat – a řešením má být odstranění třídy org.apache.com­mons.collecti­ons.functors.In­vokerTransfor­mer, která v aktuální verzi knihovny ani není, protože se přejmenoval package – a hlavně ta třída neimplementuje metodu readObject().

    Zkrátka je to celé velmi podezřelé a každý by si měl pořádně rozmyslet, než spustí ty údajné exploity – ony to exploity mohou být, ale na něco úplně jiného…

  • 9. 11. 2015 15:38

    Andrei Badea (neregistrovaný)

    Máte pravdu, že popis exploitu je zmatečný.

    Exploit funguje tak, že zaserializuje instanci sun.reflect.an­notation.Anno­tationInvocati­onHandler. Tato třída je z hlediska exploitu zajímavá dvěma aspekty:

    * Má v sobě field java.util.Map memberValues, a
    * Implementuje readObject(), volá v něm defaultReadOb­ject(), a pak iteruje memberValues.en­trySet().

    Exploit místo té mapy zaserializuje instanci LazyMap z commons-collections, obalenou opět v dynamické proxy jejíž handler je opět AnnotationInvo­cationHandler. Zde se AIH používá je na to, že jeho metoda invoke() volá memberValues.get() -- tedy se tím zavolá LazyMap.get().

    LazyMap.get() vytváří prvky on-demand tak, že volá instanci Transformer. Exploit tam dává TransformerChain delegující na řetěz instancí InvocationTran­sformer. InvocationTran­sformer je klíčový pro exploit protože umí volat metody. Konkrétně, tento řetěz InvocationTran­sformerů volá Runtime.getRun­time().exec().

    Takže při deserializaci se přečte top-level AIH a vše co k němu patří, tedy až po řetěz InvocationTran­sformerů, a pak se zavolá AIH.readObject(), to zavolá LazyMap.get() a to zavolá transformery.

    InvocationTran­sformer je tedy klíčový protože kvůli němu neplatí, že deserialzujete jen data. Svým způsobem deserializujete kód.

  • 9. 11. 2015 16:37

    Filip Jirsák
    Stříbrný podporovatel

    Díky za rozbor.

    Na tu třídu InvokerTransformer jsem se díval, ale právě jsem zjistil, že je zneužitelná pouze při zavolání metody transform, pokud útočník může do té metody předat vhodný parametr. A jak se to stane, že se při deserializaci volá ta metoda, to jsem v tom popisu nikde nenašel.

    Podle mne je chyba v implementaci AIH.readObject(), protože to je to místo, kde se při deserializaci najednou místo načítání dat volá kód (i když je pravda, že metoda Map.get() volající kód místo toho, aby jen vrátila data z mapy, je ne příliš časté řešení – ale není to ani porušení kontraktu Map). LazyMap a InvokeTransformer je pak už jenom způsob, jak z volání kódu při deserializaci udělat volání toho správného kódu, který potřebuje útočník – a využívá to toho, že tyhle dvě třídy jsou v jedné docela používané knihovně, takže tam, kde má útočník k dispozici jednu z nich, bude mít i tu druhou.

    Pokud bych měl v aplikaci třeba implementaci mapy, která by jako klíč měla příkaz a vracela třeba návratový kód spuštění příkazu:

    (key) -> Runtime.getInstance().exec(key).waitFor()

    byla by přes AIH.readObject() zneužitelná ještě snáz.

    Akorát že případů jako AIH.readObject() mohou být stovky a podle mne není reálné všechny ošetřit (navíc jediné možné ošetření je, že AIH nebude serializovatelná). Jediné skutečné řešení je tam, kde může do serializovaných dat někdo zasáhnout, nepoužívat způsob serializace, ve kterém může útočník vnutit deserializaci instance libovolné třídy dostupné na classpath.

  • 9. 11. 2015 21:20

    Palo (neregistrovaný)

    Najdolezitejsia je cast:
    > find a part of the application that takes a serialized object as input

    Takuto aplikaciu som nikdy nenapisal lebo je to dost blby napad. A o ziadnej ani neviem. Ziadny kod sa tam neda z webu nahrat, da sa iba zavolat metoda ktoru ste volat nechceli. Napriklad System.exit a to je asi tak vsetko.
    Takze staci nebyt blby a nepouzivat Java serializaciu na prenos udajov cez HTTP. Co je vlastne uplne normalne.

  • 9. 11. 2015 23:00

    Filip Jirsák
    Stříbrný podporovatel

    Takuto aplikaciu som nikdy nenapisal lebo je to dost blby napad. A o ziadnej ani neviem.
    Ale víte. Každá aplikace, která něco ukládá a načítá – třeba každý textový editor. Každá aplikace, která pracuje s databází. Každá vícevrstvá aplikace. Jenom ty způsoby serializace a deserializace se liší.

    Ziadny kod sa tam neda z webu nahrat, da sa iba zavolat metoda ktoru ste volat nechceli.
    Proč z webu? Existují i jiné než webové aplikace. Navíc pokud budete mít na classpath vhodné třídy, třeba BCEL, můžete si tam spustit i svůj kód. Nebo tam můžete mít skriptovací jazyky, a ty jsou součástí Oracle JDK od verze 7.

    Napriklad System.exit a to je asi tak vsetko.
    Ono to úplně stačí. System.exit, Runtime,exec, Connection.exe­cute('Drop database')…

    Takze staci nebyt blby a nepouzivat Java serializaciu na prenos udajov cez HTTP.
    Pokud si myslíte, že se serializované objekty mohou předávat jenom přes HTTP, přenechte starost o bezpečnost raději někomu jinému.

  • 10. 11. 2015 7:11

    Filip Jirsák
    Stříbrný podporovatel

    Ne, nepíše. Podívejte se na ten odkazovaný článek – WebLogic je napaden přes protokol T3, OpenNMS přes RMI…

  • 10. 11. 2015 11:17

    Palo (neregistrovaný)

    A kto ma vystrceny T3 do WEBu? Alebo nebodaj RMI?
    Apache reverse proxy je snad minimum co tam ludia davaju alebo iba my sme cudny?
    Diera to je, netvrdim ze nie, ale nie taka velka ako sa snazi autor exploitu naznacit.

  • 10. 11. 2015 12:08

    Filip Jirsák
    Stříbrný podporovatel

    Vy jste tím webem nějaký uhranutý, ne? Asi jste myslel, kdo má T3 nebo RMI „vystrčené do veřejného internetu“. No tak někdo to tak mít může, vždyť jsou ty přístupy chráněné autorizací a mělo by to být bezpečné. A i když to někdo má přístupné jenom z nějaké privátní sítě, pořád není správné, že kdokoli v té síti může ten server třeba vypnout.

    Apache reverse proxy je snad minimum co tam ludia davaju
    Soudní lidé tam Apache reverse proxy nedávají.

    Diera to je, netvrdim ze nie, ale nie taka velka ako sa snazi autor exploitu naznacit.
    To spíš záleží na konkrétní situaci. Horší podle mne je, že ta díra spočívá v něčem jiném, než autoři exploitu naznačují, a hlavně že ten jejich „fix“ zalepí jednu konkrétní díru, kterou zkouší jejich exploit, ale neřeší tu díru jako takovou.

  • 10. 11. 2015 22:11

    Palo (neregistrovaný)

    > kdokoli v té síti
    tam ma pristup iba administrator

    > Soudní lidé tam Apache reverse proxy nedávají.
    Load balancing a fail over riesite ako? Ci pouzivate WebLogic za velke peniaze a mate ho rovno vystrceny do internetu? :-D

    Diera tam ziadna nie je. Iba niekto zle implementoval deserializaciu udajov. Ked naprogramujem ze ked mi odoslete do requestu 'dole' tak sa spusti System.exit to je aka diera?
    Oni spravili kod v custom deserializacnom hooku ktory robi neplechu, to nie je genericka diera.

  • 10. 11. 2015 23:43

    Filip Jirsák
    Stříbrný podporovatel

    Load balancing a fail over riesite ako?
    No tak konkrétně my to řešíme hardwarovým loadbalancerem. Ale některé aplikace jsou rozvažované na úrovni TCP spojení, takže to má hodně blízko k tomu, kdyby ten WebLogic byl přímo vystrčen do internetu?

    Ci pouzivate WebLogic za velke peniaze a mate ho rovno vystrceny do internetu?
    Bojíte se, aby se neošoupal? Já teda tak nějak u dražšího řešení předpokládám, že by mělo být lepší a tudíž i bezpečnější.

    Jinak já jsem narážel na to, že když tak autoritativně zmíníte jedno řešení v situaci, kdy jich existuje n různých podle konkrétních požadavků, nepůsobí to dojmem znalce, o což jste se asi snažil, ale právě naopak.

    Diera tam ziadna nie je. Iba niekto zle implementoval deserializaciu udajov.
    Jo, a když někdo zadá příjmení „Novák'; drop database;“, tak to také není chyba ale jen „zle implementovaná deserializacia udajov“.

    Oni spravili kod v custom deserializacnom hooku ktory robi neplechu, to nie je genericka diera.
    Přečtěte si popis té chyby, je to hned druhý příspěvek v diskusi. Ta třída, která v rámci deserializace spouští neznámý kód, je součástí JRE. To je dost generické. A takových tříd, které nemají readObject() odolný proti útokům, bude spousta. Spuštění kódu, který útočník nikdy neměl mít možnost spustit, je docela průšvih. Samozřejmě by mohl být ještě větší, tady má útočník přeci jen omezené možnosti – vedle té třídy s readObject() potřebuje další vhodné třídy, přes které útok povede (např. ty z Apache Commons Collections).

  • 10. 11. 2015 23:45

    Filip Jirsák
    Stříbrný podporovatel

    Jo, a když někdo zadá příjmení „Novák'; drop database;“,
    Myslel jsem samozřejmě případ, kdy vám tím smaže databázi.

  • 11. 11. 2015 0:24

    Palo (neregistrovaný)

    - Weblogic som nikdy nevidel napriamo vystrceny ani do Intranetu.
    - Program napisal programator, ziadny iny kod sa tam nedostane, ak napisal aby sa urobil drop database tak sa ma urobit
    - Genericky sa ta diera zatvori tak ze na komunikaciu nebudete pouzivat serializovane objekty v HTTP, nikdy v zivote som taku zvrhlost nevidel

  • 11. 11. 2015 7:12

    Filip Jirsák
    Stříbrný podporovatel

    To, že jste něco neviděl, neznamená vůbec nic. A vzhledem k tomu, co tu píšete v komentářích, to neznamená tuplem vůbec nic.

    Pro útočníka zajímavé metody poskytuje i standardní knihovna, třeba System.exit nebo Runtime.exec. K tomu, že útočník může smazat databázi, i když v programu žádný takový kód není – hledejte pojem „SQL injection“. Když má útočník v ruce spojení do databáze a může na něm zavolat libovolný příkaz, má dost silný nástroj.

    To HTTP a web vás opravdu uhranulo. Vězte, že existují i jiné síťové protokoly, než HTTP, a také se přes ně dají přenášet serializované objekty. A dokonce může útočník podvrhnout serializované objekty i do vstupu, který server nedostane síťovým protokolem, ale třeba ze souboru nebo databáze.

  • 11. 11. 2015 8:28

    Palo (neregistrovaný)

    Nie som nicim uhranuty iba mam asi viacej paranoje nez iny. Ak mozete serveru podhadzovat serializovane udaje nieco je zle. Fakt nepoznam aplikaciu ktora deserializuje objekty odkialkolvek. Je to neprenosne, pomale, ... cele zle.
    Ak mate Java aplikaciu nachylnu na SQL Injection opat ste urobili nieco zle v navrhu. V ziadnej nasej instancii nebezi ani console na porte ktory je dostupny mimo pristupu administratora.
    Security sa neobjavi len tak sama. Musite dodrziavat nejake zasady. Neserializovat Java objecty pomocou standardneho Java serialization frameworku je rovnake pravidlo ako pouzivat binding parametrov do SQL. Absolutne zakladna vec.

  • 11. 11. 2015 8:46

    Filip Jirsák
    Stříbrný podporovatel

    To nevím, co s tou vaší paranoií budete dělat, až zjistíte, že existují i jiné protokoly než HTTP. SQL injection jsem uváděl jako příklad toho, co může útočník udělat, pokud dokáže zneužít téhle chyby. Byla to reakce na vaše tvrzení, že je ta chyba nezajímavá, protože útočník nemůže spustit žádný jiný kód, než ten, který je v aplikaci. Pouze dodržování zásad k zajištění bezpečnosti nestačí – je potřeba tomu také rozumět. Jinak dotyčný dopadne jako vy a bude si myslet, že když používá binding parametrů, nemusí se SQL injection bát.

  • 12. 11. 2015 21:42

    Palo (neregistrovaný)

    Jasne, vy ma poznate a vy ste ten perfektny kto rozumie a ostani nerozumeju. :-D
    Jaj ty moj vzdelany debilko. Nechapes ani zakladom.
    Ja som napisal ze ak NEpouzivas BINDING tak si koledujes o SQL injection. Nie ze ak ho pouzivas tak sa vyhnes SQL Injection.
    Takze dostudovat zaklady logiky a potom sa zase mozes ist chvalit na internety.

  • 11. 11. 2015 9:15

    Kolemjdoucí (neregistrovaný)

    Pro všechny kdož mají Weblogic (konkrétně jeho protokol T3) zpřístupněný na síťové úrovni nedůvěryhodným uživatelům už Oracle vydal patch: https://blogs.oracle.com/security/entry/security_alert_cve_2015_4852

  • 9. 11. 2015 9:41

    Kolemjdoucí (neregistrovaný)

    Ona to totiž ve skutečnosti není chyba, protože se to projevuje pouze pokud uživatel má možnost změnit serializovaná data která následně aplikace bude deserializovat a při tom spustí to co si tam uživatel podvrhnul. Pokud někdo uživateli umožňuje přímo měnit serializovaná data tak je to chyba v návrhu, protože tím dává uživateli asi tak milion možností jak toho zneužít, není důvod se vzrušovat kvůli této jedné konkrétní...

  • 9. 11. 2015 10:11

    Filip Jirsák
    Stříbrný podporovatel

    To, že uživatel má možnost podstrčit data k deserializaci není chyba návrhu. Vždyť jsou to jenom data. Když uživatel na webu odešle formulář, odesílá tím data k deserializaci. Už jenom zadání URL na webu jsou data k deserializaci – i když se v případě toho URL ani formuláře nedeserializuje Java serializací ale textová reprezentace.

    Problém by mohl být, pokud by deserializovaná třída ta přijatá data chybně interpretovala. Což teoreticky je možné. Ke spuštění cizího kódu by to ale znamenalo, že ta data bude interpretovat jako skript a spustí jej, nebo že ta data bude interpretovat jako bajtkód a vytvoří na jeho základě třídu, kterou poté nahraje. Což samo o sobě není vůbec jednoduché – a uvedená třída InvokerTransfor­mer nejen, že nic takového nedělá, ona vůbec neimplementuje vlastní deserializaci.

    Zneužitelné je pouze to, pokud by někdo serializoval a deserializoval instanci té třídy InvokerTransformer, a útočník pak může změnit jenom to, kdy v případě, že se ten deserializovaný InvokerTransformer zavolá na nějakou instanci, může útočník změnit volanou metodu (na stejné instanci) a její parametry. Zaútočit by se tedy dalo jen na konkrétní kód chybně využívající té třídy, rozhodně ne na jakoukoli aplikaci tu třídu využívající. A útok by spočíval jen ve spuštění jiného kódu na dané třídě, nelze tím spustit libovolný kód útočníka.

  • 9. 11. 2015 10:20

    Kolemjdoucí (neregistrovaný)

    Napsal jsem "Pokud někdo uživateli umožňuje přímo měnit serializovaná data tak je to chyba v návrhu" a tím "přímo" jsem myslel měnit rovnou ty serializované bajty, takže třeba změnit třídu a podobně, to je základní princip této "chyby". Měnit data která uživatelem měnitelná být musí samozřejmě není nic špatného, ale všechna data od uživatele musí jít skrz patřičné aplikační kontroly a ten serializovaný formát pak musí být striktně interní, na něj uživatel nesmí sahat protože by tím obešel ty všechny kontroly.

  • 9. 11. 2015 10:32

    Filip Jirsák
    Stříbrný podporovatel

    U každé aplikace, která posílá přes síť data serializovaná pomocí standardní Java serializace (třeba RMI), může uživatel přímo měnit serializovaná data. Aby to bylo zneužitelné, musí ještě někdo na těch uživatelem podstrčených datech zavolat nějaký kód, který provede nějakou neplechu.

    Například pokud bych měl třídu, která má field typu Runnable, serializovanou instanci této třídy bych získal od uživatele a měl bych někde v aplikaci implementaci Runnable, která zavolá System.exit() (a měl bych tohle volání povolené v politice), může mi uživatel do serializovaných dat místo mnou očekávána instance Runnable podstrčit tu, která volá System.exit(). Ale pokud něco takového ty exploity dělají, není to nikde v tom doprovodném textu napsáno a není tam ani napsáno, ve které třídě je chyba.

  • 9. 11. 2015 12:21

    Starous (neregistrovaný)

    nakolik mě tedy má tento možný exploit trápit nebo není tak velké riziko to vyignorivat ?

  • 9. 11. 2015 13:33

    Karel (neregistrovaný)

    To v této chvíli nikdo neví, nebylo zveřejněno dost informací. Podle některých spekulací se jedná o stejný "exploit" jako když webová stránka odněkud stáhne javascript a ten spustí. Jinými slovy - klient si odněkud stáhne data, což je naprosto běžný postup. A pak je otázka ta, zda autor nějaké knihovny měl tak skvělý nápad, že ta data označí za spustitelný kód a spustí ho. Pokud to tak je, pak útočník může pozměnit přenášená data a tím podvrhnout kód, který se pak spustí.

    Jenže nevíme, o jakou knihovnu jde, takže těžko to ověřit. V každém případě Java to v základu neumí, do dat/z dat načítá jen hodnoty atributů, nikoliv bytekód. Ale jde napsat program takový, aby si bytekód tahal a spustil. Běžně se to používá, ale vyžaduje to netriviální úsilí (viz ClassLoader) a autor by si tak měl být vědom toho, že stahuje bytekód, který pak spouští. Včetně úvah nad tím, zda to stahuje z důvěryhodného zdroje.

  • 9. 11. 2015 17:58

    Ondrej Mikle (neregistrovaný)

    Ta zpráva vyjmenovává několik příkladů zranitelných aplikací: WebLogic, WebSphere, JBoss, Jenkins, OpenNMS.

    Zranitelné jsou, pokud mají přístupný port, na kterém běží služba používající problematickou deserializaci.

    Ověřit to lze, přímo původní článek obsahuje HOWTO i odkaz na repozitář s exploit kódem.

    Ono to celé není nová zranitelnost, to samé bylo předvedeno předtím v práci "Marshalling Pickles" (https://www.youtube.com/watch?v=KSA7vUkXGSg). Nové na tom je jen našroubování exploitu na existující aplikace.

  • 9. 11. 2015 18:24

    Filip Jirsák
    Stříbrný podporovatel

    Zranitelné jsou, pokud mají přístupný port, na kterém běží služba používající problematickou deserializaci.
    Důležité také je, zda k té deserializaci dochází před autentizací uživatele, případně zda se rozlišují úrovně oprávnění, nebo pokud je komunikace nešifrovaná a útočník ji může pozměnit (což by ale byl větší problém, než ta deserializace). Pokud je ta problematická služba určena pouze pro administrátory, není to kritické – pokud administrátor sám sobě úmyslně shodí server, je to jeho chyba, a má k tomu ostatně mnoho jiných příležitostí, než hackovat deserializaci.

    Ověřit to lze, přímo původní článek obsahuje HOWTO i odkaz na repozitář s exploit kódem.
    Vzhledem ke zmatenosti toho příspěvku oznamujícího chybu bych byl velmi opatrný při spouštění kódu, na který ten příspěvek odkazuje.

  • 9. 11. 2015 22:59

    Jiri Korbel (neregistrovaný)

    Otazka znela, zda to lze overit. Ano, lze. Fakt, ze s libovolnym exploit kodem se musi zachazet velmi opatrne, je snad uplne jasny.

  • 9. 11. 2015 13:46

    Filip Jirsák
    Stříbrný podporovatel

    No, to by mne také zajímalo. Ta chyba teoreticky existovat může. Knihovna Apache Commons Collections by v takovém případě vystupovala spíše jako nástroj útoku než jako zdroj té bezpečnostní chyby. Každopádně ten odkazovaný popis je velmi zmatený a nepopisuje samotný princip chyby, to by se muselo zjistit reverzním inženýrstvím toho exploitu. Existují už nějaké záplaty k té chybě (třeba pro Groovy), takže reálný základ to asi má. Ale nevím, jestli už existuje nějaký seznam tříd, které jsou k téhle chybě zneužitelné.

    Správné řešení tohohle problému spočívá v tom, že nemůžete deserializovat třídu podle názvu, který vám mohl někdo podstrčit, ale vždy musíte při té deserializaci předem vědět, jaký typ objektu (nebo typy) očekáváte a musíte kontrolovat, že někdo nepodstrčil něco jiného.

    Každopádně chyba je zneužitelná jenom tehdy, pokud má útočník možnost podvrhnout serializovaná data, tedy typicky pokud jde o klient-server aplikaci, kde klient předává serveru objekty serializované pomocí Java serializace – tedy ne třeba přes XML nebo JSON (ale pozor na to, že ty serializované objekty klidně mohou být přenášené třeba přes HTTP).

  • 9. 11. 2015 14:06

    Karel (neregistrovaný)

    Tak jméno mi může podstrčit jaké chce. Když mi místo com.company.Em­ployee pošle com.company.Sup­plier, tak na to asi přijdu při kontrole typu, případně mi to rovnou spadne na chybu přetypování. Přeci jen zavolat funkci typu "deleteAllEmplo­yees" na objektu typu Object nejde. Navíc podvrhnout může jen existující třídu, protože jinak spadne na ClassNotFoundEx­ception. A na té existující musí existovat metoda, kterou program volá a musí se trefit do přetypování, které programátor použil (tady by Interface mohl útočníkovi pomoci).

    Podstatné je, že mi přes serializaci nedokáže poslat spustitelný kód, jen data. Deserializace použije kód z classpath a jen doplní data podle příchozího souboru. Čili dokáže v ideálním případě leda tak zajistit, že se spustí metoda jiné třídy, než by měla. Útok typu, že si serializuji záznam o zaměstnanci, v něm přepíšu plat na desetinásobek a pak deserializuji, je natolik zřejmý, že o ten asi nepůjde.

    Pokud ale nějaká knihovna použije data jako program (vlastní ClassLoader), pak to samozřejmě problém je poměrně zásadní.

  • 9. 11. 2015 14:48

    Filip Jirsák
    Stříbrný podporovatel

    Chytřejší útočník samozřejmě nepodstrčí náhodně zvolené jméno, ale jméno třídy, kterou je možné přiřadit do příslušného typu. Uváděl jsem příklad s Runnable, případně třídy, které pracují s reflexí. Samozřejmě, možnosti útočníka jsou celkem omezené a nemůže volat vlastní kód, ale jen kód, který už je přítomný v aplikaci.

  • 9. 11. 2015 23:29

    Cohen (neregistrovaný)

    Myslím, že pokud deserializujete data, která může útočník upravit, otevírá to úplně jiný prostor pro případný exploit, než klasické vstupy. A nikoliv jen to, co popisujete. Zvláště pokud máte otevřený kód, tak lze hledat cesty, kdy pošle útočník záměrně nevalidní obsah objektu tak, aby zneužil něčeho, co by se za běžného provozu vůbec nemohlo stát, protože se počítá s tím, že je objekt generován standardní cestou.

    Nemám s Javou širší zkušenosti, ale v .Netu můžete třeba plnit nějakou dostatečně volně typovanou proměnnou, tj. např. object, nebo něco zdědit a v rámci deserializace dosáhnout načtení externího typu. Ale to je dost hypotetický příklad.

  • 9. 11. 2015 13:22

    Kolemjdoucí (neregistrovaný)

    "U každé aplikace, která posílá přes síť data serializovaná pomocí standardní Java serializace (třeba RMI), může uživatel přímo měnit serializovaná data." - je snad nepochopitelné to co jsem napsal, tedy že toto je zásadní chyba v návrhu? Uživatel se k serializovaným datům vůbec nemá dostat! Co jsem koukal tak toto dělají různé managementové nástroje, ale tam to zase je až po autorizaci administrátora takže to je snad OK. Kdo takhle řeší koumunikaci s běžnými uživateli tak to má prostě blbě navržené a chyb z toho plyne spousta, nemá smysl je pitvat jednu po druhé...

  • 9. 11. 2015 13:51

    Karel (neregistrovaný)

    Takhle to funguje už od dob RPC. Dnes to tak používá obrovské množství protokolů. V čem přesně je podle vás chyba? Jsou to prostě jen data, žádný kód. A protože se to posílá přes TCP/IP, tak to prostě klient i server mohou modifikovat. Nasazení šifrování zabrání ve změnách na cestě, ale oba konce si to mohou změnit jak chtějí.

  • 9. 11. 2015 15:14

    Kolemjdoucí (neregistrovaný)

    Chyba je v tom že to serializační API které je v Javě (které používá metodu readResolve) je k tomuto nevhodné protože neposkytuje potřebné validační mechanismy a navíc neplatí to co píšete "Jsou to prostě jen data, žádný kód" - viz popis té zranitelnosti. Samozřejmě není nic špatného na tom když klient posílá na server serializovaná data, jen je k tomu potřebné použít patřičný serializační mechanismus na straně klienta a validace na straně serveru. Běžně se používají v kombinaci s HTTP např. parametry v URL s metodou GET, nebo nějak naplněné tělo s metodou POST (např. JSON nebo XML), ale kdo tam nacpe tu Javovskou serializaci tak to holt dělá špatně a nadávat za všechny problémy může jen sám sobě protože ten nástroj použil nevhodným způsobem.

  • 9. 11. 2015 14:02

    Filip Jirsák
    Stříbrný podporovatel

    Uživatel se k serializovaným datům vůbec nemá dostat!
    V tom případě ale nemůžete spouštět aplikaci na počítači uživatele. Nebo-li tu aplikaci nebude moci nijak používat. Třeba i webová stránka jsou serializovaná data uživatele. Je potřeba rozlišovat mezi obecným termínem serializace, a standardní Java serializací založenou na rozhraních java.io.Seria­lizable a java.io.Exter­nalizable. Podobnou chybu samozřejmě mohou mít i jiné způsoby serializace, ale serializace do webových stránek a formulářů takovouhle chybu nemá.

    Problém ve skutečnosti není v tom, že jsou serializovaná data u uživatele, ale v tom, co se s nimi při deserializaci provádí. Pokud deserializujete jenom hodnoty datových entit, problém v tom není a musíte na serveru hlídat akorát to, že je datový typ správný, má správný rozsah a případně splňuje další požadavky (rozsah hodnot apod.). Problém je, že při standardní Java serializaci se serializuje i jméno třídy, takže útočník může podstrčit instanci jiné třídy se stejným rozhraním, která je k dispozici na classpath, a pokud se pak provede na té deserializované instanci kód, provede se na té neočekávané třídě (tedy pořád je to kód, který je na serveru, nemůže si útočník podstrčit svůj – ale může to být kód, který v daném kontetxu nikdy neměl být volán). Další možnost je, že by se serializovaná data načítala přímo jako bajtkód, ale to snad nikdo soudný neudělá (už jenom proto, že vnutit do JVM přímo z aplikace svůj bajtkód není úplně triviální, a pokud to někdo dělá, tak snad ví, co dělá).

  • 9. 11. 2015 13:35

    L. (neregistrovaný)

    Pokud jsou data z webového formuláře zpracovávána standardní Javovou deserializací, tak to JE chyba návrhu. Mimo jiné už proto, že se mu těžko povede něco deserializova­telného zadat :D

  • 10. 11. 2015 3:16

    sj (neregistrovaný)

    Třeba cookies? Občas v cookies jsou serializované celé třídy. Takže běžně uživatel to nemusí zadávat, ale útočník může.

    Tady sice diskuze není tak příšerná jako na slashdotu s jejich rezolutním "to nejde", ale stejně je smutné o kolik lepší by i tady mohla být diskuze kdyby každý přečetl alespoň článek a pak třeba i z něj linkovanou slideshow Marshalling Pickles kde se právě o serializavi v cookiech (ať už z Jávy, PHP, Ruby či čeho) mluví.

    A to že tu někdo říká že to je špatný návrh když někdy používá serializavi na komunikaci je możná sice pravda, ale přesto ten problém nelze ignorovat (ve stylu " kdo to napsal tak blbě tak si to zaslouží a uživatelé tak blbě napsaných aplikací taky). Navíc množství reálných aplikací které komunikují např. přes RPC a posílají si serializovaná data, případně tak mají vytvořen formát pro ukládání dat na disk apod. prostě není malé.

  • 10. 11. 2015 9:22

    L. (neregistrovaný)

    Trvám na tom, že pokud někdo ukládá java-serializované objekty do cookies, tak je to broken by design. Už proto, že se tato data musí posílat s každým requestem.

    Aplikaci, která ukládala data na disk Java serializací jsem psal, ale tam uživatel četl pouze jím vytvořená data.

    Popravdě, detaily Java deserializace jsem se nikdy nezabýval, ale tak nějak intuitivně jsem vždycky bral, že to není moc bezpečné a dá se s tím napáchat pěkná paseka.

Byl pro vás článek přínosný?

Autor zprávičky

Petr Krčmář pracuje jako šéfredaktor serveru Root.cz. Studoval počítače a média, takže je rozpolcen mezi dva obory. Snaží se dělat obojí, jak nejlépe umí.