Tinklaraštis

CVE-2026-34486: kaip pataisymas atvėrė naują skylę Apache Tomcat

CVE-2026-34486-apache-tomcat
Apache / CVE / Saugumas

CVE-2026-34486: kaip pataisymas atvėrė naują skylę Apache Tomcat

Įsivaizduokite: gavote pranešimą apie Apache Tomcat pažeidžiamumą, greitai atnaujinote iki 9.0.116, uždarėte užduotį užduočių seklyje ir atsikvėpėte. O po mėnesio paaiškėjo, kad kaip tik tas pataisymas sukūrė naują skylę — ir dar pavojingesnę nei pradinė.

CVE-2026-34486 — klasikinė regresija: kūrėjai taisė CVE-2026-29146, padding oracle ataką prieš Tomcat Tribes, tačiau padarė loginę klaidą, kuri atvėrė kelią unauthenticated RCE per deserializavimą. Apache įvertino kaip Important, NVD priskyrė CVSS 7.5 — ir tai vienas tų atvejų, kai skaičius neatspindi tikrojo pavojaus: ankstesnė pažeidžiamybė tame pačiame komponente reikalavo valandų darbo, ši išnaudojama vienu paketu. Pažeistos versijos: 9.0.116, 10.1.53 ir 11.0.20. PoC paskelbė tyrėjas Bartlomiej Dmitruk iš striga.ai.

Pataisymas išleistas 2026 m. balandžio 9 d. — commit 776e12b3 oficialioje saugykloje. Jei atsinaujinote būtent dėl CVE-2026-29146 ir įdiegėte 9.0.116 — vis dar esate pažeidžiami. Reikia 9.0.117.

KAS YRA APACHE TOMCAT TRIBES

Apache Tribes — tai vidinė Tomcat klasterio pranešimų magistralė. Kai turite kelis egzempliorius už apkrovos balansuotojo, jiems reikia sinchronizuoti sesijų būseną — kitaip vartotojas, patekęs į kitą mazgą po perjungimo, bus atjungtas. Tribes kaip tik tuo ir rūpinasi: perduoda pranešimus tarp klasterio mazgų per atskirą prievadą (pagal nutylėjimą 4000), neprieinamą iš išorės.

Skamba kaip uždara vidinė magistralė — ir kaip tik todėl jos saugumui dažnai skiriama mažiau dėmesio nei žiniatinklio sąsajai. Veltui. Į Tribes prievadą galima patekti trimis keliais: sukompromituoti bet kurį įmonės tinklo kompiuterį, rasti mažiausiai apsaugotą serverį pačiame klasteryje ir panaudoti jį kaip atramą, arba — kas pasitaiko dažniau nei atrodo — per SSRF: jei žiniatinklio programa siunčia HTTP užklausas pagal vartotojo nurodytus URL, užpuolikas tiesiog nurodo vidinį adresą ir prievadą 4000.

KAIP VEIKIA KLAIDA

Pradinėje CVE-2026-29146 problema buvo ta, kad EncryptInterceptor naudojo CBC šifravimą be pranešimo autentifikavimo. Tai klasikinis padding oracle: perimant šifruotus paketus ir stebint, kaip serveris reaguoja į padding klaidas, užpuolikas galėjo metodiškai atkurti atvirą tekstą. Varginančiai ilgai, bet veikia.

Taisydami klaidą, kūrėjai pertvarkė messageReceived() metodą EncryptInterceptor klasėje — tačiau išnešė super.messageReceived() iškvietimą už try/catch bloko ribų. Taip atrodo pažeidžiamas kodas:

@Override
public void messageReceived(ChannelMessage msg) {
    try {
        byte[] data = msg.getMessage().getBytes();
        data = encryptionManager.decrypt(data);
        XByteBuffer xbb = msg.getMessage();
        xbb.clear();
        xbb.append(data, 0, data.length);
    } catch (GeneralSecurityException gse) {
        log.error(sm.getString("encryptInterceptor.decrypt.failed"), gse);
    }
    // Deserializavimas vykdomas bet kuriuo atveju — net ir po iššifravimo klaidos
    super.messageReceived(msg);
}

Logika čia sulaužyta iš esmės. Jei užpuolikas atsiųs neapdorotus nešifruotus duomenis, decrypt() iškvietimas išmes BadPaddingException arba IllegalBlockSizeException. Išimtį perims catch blokas, klaida bus užrašyta į žurnalą — ir vykdymas tęsis toliau. super.messageReceived(msg) iškvietimas jau yra už try bloko, todėl jis bus įvykdytas bet kuriuo atveju, perduodamas originalius (neiššifruotus) užpuoliko duomenis į tolesnį apdorojimo etapą.

Toliau duomenys patenka į GroupChannel, kuris perduoda juos į XByteBuffer.deserialize(). Tai standartinis Java ObjectInputStream — o tai reiškia, kad deserializavimo metu automatiškai iškviečiami metodai kaip readObject() ir hashCode() visų objektų, aprašytų atsiųstame payload.

KAIP TAI IŠNAUDOJAMA

Java deserializavimas pats savaime nėra pavojingas — pavojingos klasės, esančios serverio classpath. Apache Commons Collections 3.x — tai beveik standartinė Java programų priklausomybė, o joje jau seniai žinomos gadget grandinės, vedančios tiesiai į savavališko kodo vykdymą.

Iškvietimų grandinė naudojant Commons Collections atrodo taip:

HashSet.readObject()
  → HashMap.put(key, ...)
    → TiedMapEntry.hashCode()
      → LazyMap.get("poc")
        → ChainedTransformer.transform()
          → ConstantTransformer → Runtime.class
          → InvokerTransformer → Runtime.getMethod("getRuntime")
          → InvokerTransformer → Runtime.getRuntime()
          → InvokerTransformer → runtime.exec(cmd)

Įrankis ysoserial turi aštuonis paruoštus Commons Collections variantus skirtingoms bibliotekos versijoms, taip pat grandines Spring, Groovy, Commons BeanUtils ir integruotoms JDK klasėms. Užpuoliko užduotis — parinkti tinkamą grandinę konkrečiai aplinkai ir išsiųsti vieną paketą į Tribes prievadą.

Palyginkite su pradine CVE-2026-29146: reikėjo perimti srautą, metodiškai zondoti serverį, analizuoti atsakymus į padding klaidas. Čia — viena užklausa, be autentifikavimo, be išankstinio šifravimo rakto žinojimo.

REALUS ATAKOS SCENARIJUS

Užpuolikas yra įmonės vidiniame tinkle — per sukompromituotą darbuotojo kompiuterį, neapsaugotą Wi-Fi segmentą arba atramą gretimame klasterio serveryje. Alternatyvus įėjimas — SSRF žiniatinklio programoje: jei programa siunčia HTTP užklausas pagal vartotojo nurodytus URL, užpuolikas nukreipia jas į vidinį adresą ir prievadą 4000. Tribes prievadas neklauso išorėje, tačiau iš vidaus — pasiekiamas.

Toliau viskas paprasta. Užpuolikas nustato Tomcat versiją per HTTP antraštes arba klaidos puslapį, įsitikina, kad Tribes aktyvus (klasterio konfigūracija numato <Cluster> elementą server.xml), sugeneruoja payload per ysoserial su tinkama grandine pagal programos priklausomybes — ir išsiunčia vieną raw paketą į 4000 prievadą. Jokio autentifikavimo. Jokio šifravimo rakto. Pats serveris iškviečia reikiamus metodus deserializavimo metu.

Rezultatas priklauso nuo to, kaip paleistas Tomcat. Be izoliacijos per systemd — tai visiškas serverio kompromitavimas vienu paketu, su Tomcat proceso vartotojo teisėmis. Jei sukonfigūruoti PrivateTmp, NoNewPrivileges ir capabilities apribojimai — žalos spindulys apribotas procesu, tačiau RCE vis tiek įvyko, ir užpuolikas jau viduje.

LAIKO JUOSTA

Pradinė CVE-2026-29146 pažeidžiamybė — padding oracle EncryptInterceptor — buvo ištaisyta versijose 9.0.116, 10.1.53 ir 11.0.20. Būtent šiose versijose atsirado commit 0112ed22, kuris išnešė super.messageReceived()try/catch bloko ribų — ir tuo pačiu sukūrė naują problemą.

2026 m. kovo 26 d., netrukus po pataisymo išleidimo, tyrėjas Bartlomiej Dmitruk iš striga.ai pranešė Apache Tomcat saugumo komandai apie regresiją. Pagal terminus sprendžiant, pranešimas sekė beveik iš karto po išleidimo — tai rodo tikslinį pataisymo auditą, o ne atsitiktinį atradimą.

2026 m. balandžio 9 d. paskelbta CVE-2026-34486. Tą pačią dieną išleistos ištaisytos versijos 9.0.117, 10.1.54 ir 11.0.21 su commit 776e12b3, atkūrusiu teisingą klaidų apdorojimą messageReceived(). Viešas PoC iš striga.ai pasirodė netrukus po atskleidimo.

KODĖL TAI SVARBU

Apache Tomcat — vienas labiausiai paplitusių Java serverių pasaulyje, naudojamas bankuose, mokėjimų sistemose, įmonių portaluose. Klasterizavimas su Tribes taikomas visur, kur reikalingas horizontalus mastas — tai yra ten, kur apkrova ir duomenų vertė yra didžiausi.

Padėtį apsunkina tai, kad daugelis komandų gali manyti esančios apsaugotos — juk atsinaujino iki 9.0.116 dėl CVE-2026-29146. Pasirodo, ne. Tai sukuria klaidingą saugumo jausmą, kuris kartais pavojingesnis nei visiškas neturėjimas pataisymo: bent jau tada žinai, kad esi pažeidžiamas.

Ir dar viena pamoka — apie regresines pažeidžiamumo. Saugumo pataisymas, įvestas nevisiškai atsekant vykdymo srautą, gali sukurti blogesnę problemą nei pradinė klaida. CVE-2026-29146 reikalavo srauto perėmimo ir metodinio zondavimo. CVE-2026-34486 — vieno neautentifikuoto paketo.

KĄ DARYTI

Pirma — išsiaiškinkite, kokią versiją iš tikrųjų naudojate. Jei Tomcat įdiegtas per paketų tvarkyklę, versija ne visada akivaizdi. Patikrinti galite taip:

find / -name "catalina.jar" 2>/dev/null | xargs -I{} sh -c 'unzip -p "{}" org/apache/catalina/util/ServerInfo.properties 2>/dev/null | grep server.number'

Arba per HTTP, jei įgalintas būsenos puslapis:

curl -s http://localhost:8080/ | grep -i tomcat

Toliau — atnaujinimas. Čia slypi vienas spąstas: Debian/Ubuntu saugyklos dažnai atsilieka nuo upstream keliais minor versijų. Visai nebūtina, kad apt install tomcat9 duos jums 9.0.117 — pirma patikrinkite:

apt-cache policy tomcat9

Žiūrėkite į eilutę Candidate:. Jei ten nėra 9.0.117 ar naujesnės — atnaujinkite rankiniu būdu iš oficialaus atsisiuntimų puslapio (tomcat.apache.org/download-90.cgi 9.x šakai): sustabdykite egzempliorių, pakeiskite bin/ ir lib/ paliekant webapps/ ir conf/ nepaliestus, paleiskite iš naujo. Jei saugykla aktuali:

apt update && apt install tomcat9

Po atnaujinimo įsitikinkite, kad versija tikrai pasikeitė:

sh /path/to/tomcat/bin/version.sh | grep "Server version"

Turi rodyti 9.0.117, 10.1.54 arba 11.0.21 — priklausomai nuo šakos. Jei versija nepasikeitė, atnaujinimas nepavyko.

Jei dabar atnaujinti neįmanoma — bent jau izoliuokite prievadą. Pirma įsitikinkite, kad Tribes apskritai aktyvus:

grep -n "Cluster" /opt/tomcat/conf/server.xml
ss -tlnp | grep 4000

Jei prievadas klauso — uždarykite jį per nftables, palikdami prieigą tik patikimiems klasterio mazgams:

nft add rule inet filter input tcp dport 4000 ip saddr != { 10.0.1.10, 10.0.1.11 } drop

Tai laikina priemonė, o ne pataisymo pakaitalas. Jei Tribes apskritai nenaudojamas — patikrinkite, kad <Cluster> elementas yra pakomentuotas arba jo nėra server.xml, ir išjunkite jį.

IŠVADOS

CVE-2026-34486 — pavyzdys, kai vaistas pasirodė pavojingesnis už ligą. Kūrėjai ištaisė padding oracle, tačiau dėl loginės klaidos vykdymo sraute sukūrė unauthenticated RCE pažeidžiamybę. Paveiktos versijos — kaip tik tos, kurios turėjo būti saugios po ankstesnio pataisymo.

Patikrinkite Tomcat versiją dabar. Jei esate ant 9.0.116 — atsinaujinkite iki 9.0.117. 10.x ir 11.x šakoms: 10.1.53 → 10.1.54, 11.0.20 → 11.0.21. Tai negali laukti iki kito priežiūros lango, jei Tribes prievadas yra pasiekiamas iš bet kurios vietos jūsų tinklo viduje.

Leave your thought here

El. pašto adresas nebus skelbiamas. Būtini laukeliai pažymėti *