Přehled
Toto oznámení se týká bezpečnostní chyby ve vlastní autentizační vrstvě DPGW (nejedná se o závislost na řešení třetích stran). Při určitých konfiguracích autentizace může dojít k úniku identity autentizovaného uživatele z jednoho HTTP požadavku do následujícího požadavku zpracovávaného stejným pracovním vláknem ze skupiny, což umožňuje, aby byl požadavek jednoho uživatele zpracován pod identitou jiného uživatele.
Podrobnosti o zranitelnosti
- CVE ID: Žádné (interní identifikace)
- Komponenta: DPGW Security Manager (org.medoro.dpgw.base.priv.security2.SecurityManager2) a filtry pro ověřování požadavků (Security2FilterHandler, AuthFilter a přihlašovací obslužné rutiny ESB / OAuth2 / GoldDigger)
- Třída zranitelnosti: CWE-488 (vystavení datového prvku nesprávné relaci) / CWE-384 (fixace relace) / nesprávné vyčištění kontextu zabezpečení lokálního pro vlákno u vlákna v poolu
- Skóre závažnosti: 7.8 High (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N)
Dotčené verze DPGW
Týká se pouze případů, kdy je povoleno ověřování ESB nebo OAuth2 (stejnou chybu vykazuje i ověřovací filtr „open“ v GoldDiggeru).
- 1.11 — všechna vydání (<= 1.11.47-REL), zatím bez opravy
- 1.12 — všechna vydání (<= 1.12.51-REL), zatím bez opravy
- 1.13 — verze <= 1.13.29-REL (opraveno ve větvi, bude zahrnuto v příští verzi 1.13.x)
- 1.14 — všechny verze (<= 1.14.08-REL), zatím bez opravy
- main / devel — dosud nevydáno, zatím bez opravy
Posouzení rizik a použitelnosti
Použití
DPGW ověřuje HTTP požadavky prostřednictvím řetězce servletových filtrů. Ověřený subjekt (Principal) je uchováván pro každé vlákno v proměnné typu ThreadLocal uvnitř SecurityManager2 (funkce login() jej nastaví, funkce logout() jej vymaže pomocí ThreadLocal.remove()). Žádosti jsou obsluhovány pracovními vlákny Jetty ze skupiny, takže proměnná lokální pro vlákno musí být vymazána na konci každé žádosti; v opačném případě hodnota přetrvává ve vlákně a je viditelná pro jakoukoli žádost, kterou skupina tomuto vláknu přiřadí jako další.
Vymazání provádí AuthFilter v blocích finally { sm2.logout(); } — avšak pouze u cest žádostí, které procházejí přes chain.doFilter(…). Přijímací modul pro přihlášení důvěryhodného uživatele používaný v procesech federovaného přihlášení, TrustedUserAuthenticateAction.authenticateAndLoginToSession(), volá sm.login(principal) (čímž naplní proměnnou thread-local) a uloží principal do HTTP relace, ale není spárován s odhlášením v daném rozsahu.
Analýza
Přihlašovací postupy ESB, OAuth2 a GoldDigger dokončují požadavek tím, že zapíší přesměrování/odpověď a vrátí se bez volání chain.doFilter(…), takže se nikdy nedosáhne bloků cleanup finally v AuthFilteru:
- ESB: ESBTokenAuthFilterHandler.filterAction() (/openviewer) → authenticateAndLoginToSession() (→ sm.login) → filterAction.sendRedirect(…) a návrat. Žádný logout(), žádný chain().
- OAuth2: OAuth2AuthorizeServletV1 (/public/auth/v1/oauth2/authorize/*) → AuthorizeHandler.loginUser() → OAuth2Login.loginUser() → authenticateAndLoginToSession() (→ sm.login). Protože je koncový bod pod /public/…, AuthFilter jej směruje přes svou větev „else“, která se řetězí bez finally-logout.
- GoldDigger: GoldDiggerAuthenticationWebFilter.filterAction() (/openzauth/*) — stejný vzor „přihlášení a následné přesměrování“.
Po dokončení takové žádosti o přihlášení zůstává principál uživatele ESB/OAuth2/GoldDigger v proměnné thread-local daného pracovního vlákna Jetty. Když pool následně přiřadí toto vlákno jinému, jinak neověřenému požadavku, bezpečnostní vrstva zachází s požadavkem jako s již ověřeným pod identitou zbývajícího uživatele — důvěryhodnými body, které čtou proměnnou vlákna namísto opětovného odvození identity z požadavku/relace, jsou AuthFilter (if (sm2.getCurrentPrincipal().isPresent()) { … }) a OAuth2AuthorizeServletV1 (sm.getCurrentPrincipal().isPresent()).
Okno zranitelnosti nastává při prvním opětovném použití daného vlákna krátce po úspěšném přihlášení: požadavek, který zdědí tuto identitu, je v rámci něj obsloužen a následně se odhlásí, čímž se hodnota vymaže. Útočník nemůže ovlivnit, které vlákno z fondu obslouží jeho požadavek, ani nemůže vynutit načasování, takže zneužití je nezávislé na souběžném legitimním přihlášení (odráží se v AC:H). Pokud se to podaří, důsledkem je úplné zosobnění postiženého uživatele — přístup k datům tohoto uživatele a schopnost jednat jeho jménem — odtud C:H/I:H. Nedochází k žádnému dopadu na dostupnost.
Stav
Ovlivněno
Skóre závažnosti v kontextu DPGW: 7.8 High CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
Zranitelnost je přístupná ze sítě (AV:N) a nevyžaduje přihlašovací údaje útočníka (PR:N). Složitost útoku je vysoká (AC:H), protože k úspěchu je nutné bezprostředně po přihlášení oběti do jednotného systému předběhnout konkrétní vlákno sdílené v poolu. Převzetí identity má vysoký dopad na důvěrnost a integritu (C:H/I:H) v případě systému pro lékařské zobrazování; nemá žádný dopad na dostupnost (A:N).
Dopad na DPGW
Je-li povoleno ověřování pomocí ESB nebo OAuth2, může být požadavek zpracován pod identitou jiného uživatele při prvním opětovném použití vlákna ze sdíleného fondu po přihlášení daného uživatele. Jedná se o obcházení ověřování a autorizace: převzatý požadavek získá role a oprávnění k přístupu k datům původního uživatele, což umožňuje neoprávněné prohlížení studií a údajů o pacientech jiného uživatele a akcí provedených pod jeho identitou. Toto se netýká nasazení, která nemají povoleno ověřování pomocí ESB nebo OAuth2 (nebo GoldDigger open).
Náprava a zmírnění dopadů
Oprava
Tato oprava zajišťuje, že kontext zabezpečení na úrovni vlákna je vždy vymazán na konci každého požadavku, bez ohledu na to, který handler přihlášení provedl, a to tak, že nejvnější zpracování požadavku /* filtrovacího handleru je obaleno blokem finally { sm.logout(); }:
– 1.13 — commit d42c8925c3 („oprava (Security): zajištění správného odhlášení v Security2FilterHandler“); bude součástí příštího vydání řady 1.13.x (po verzi 1.13.29-REL).
Protože Security2FilterHandler je nejvyšší /* handler, jeho finally-logout se spustí i v případě, že vnitřní handler ESB/OAuth2/GoldDigger zkrátí proces přesměrováním, takže pokrývá všechny cesty, kde by mohlo docházet k úniku.
Plánovaná oprava
Stejná oprava má být přenesena i do zbývajících udržovaných větví:
- 1.14 — 1.14.09-REL (28. 7. 2026)
- 1.12 — 1.12.53-REL (23. 7. 2026)
- 1.11 — čeká na schválení
- main / devel — čeká na schválení
Akce uživatele
- Dočasné zmírnění rizika: Pokud není vyžadováno otevřené ověřování pomocí ESB, OAuth2 nebo GoldDigger, deaktivujte jej, dokud nebude nasazena opravená verze. Nasazení, která využívají pouze standardní ověřování pomocí souborů cookie/relace nebo tokenů DPGW (jejichž cesty již vymažou proměnné lokální pro vlákno), nejsou ohrožena.
- Jakmile bude pro používanou větev k dispozici verze DPGW obsahující opravu, proveďte upgrade na ni.