Stylizovaný štít, databáze a oddělené soubory znázorňující opravu napadeného WordPressu

Fakta v kostce

Nouzový stav webu
HTTP 503
Záloha incidentu
1 kompletní archiv souborů a databáze
Doporučená práva adresářů
755
Doporučená práva souborů
644
Kontrola administrátorů
100 % účtů s rolí Administrator
Počet WordPress salt hodnot
8

Napadený WordPress: technický postup opravy bez ztráty dat

Napadený WordPress neopravujte tak, že smažete první podezřelý soubor. Cílem je zastavit škody, zachovat důkazy, najít vstupní bod a vrátit web do provozu bez backdooru. Níže je postup, který používáme u webů i WooCommerce e-shopů.

Nejdřív zastavte škody, potom čistěte soubory

První chyba je pracovat na živém webu, který dál obsluhuje návštěvníky. Pokud web přesměrovává na cizí domény, rozesílá spam nebo hostuje phishing, přepněte ho na HTTP 503. Nevracejte 200 s hláškou o údržbě, vyhledávačům tím říkáte něco jiného.

Izolace nemusí znamenat vypnutí celého serveru. Stačí blokovat veřejný provoz, nechat přístup přes VPN nebo IP whitelist a zachovat databázi i logy. Pokud máte reverzní proxy nebo DNS správu oddělenou od hostingu, použijte ji pro rychlé přesměrování provozu na statickou stavovou stránku.

  • Nastavte webu návratový kód 503 a krátké hlášení bez detailů o incidentu.

  • Zablokujte administraci pro všechny IP adresy kromě vybraných správců.

  • Pozastavte SMTP odesílání, pokud existuje podezření na spam.

  • Zakonzervujte access logy, error logy a auditní logy minimálně z posledních 7 dnů.

  • Nevyprazdňujte cache dřív, než víte, zda neobsahuje důkaz přesměrování nebo vložený skript.

U e-shopu přidejte kontrolu plateb a objednávek. Pokud útočník měnil checkout, kupony nebo e-maily, nestačí vyčistit šablonu. Musíte ověřit i stav objednávek, callbacky platebních bran a účty s rolí správce obchodu.

Záloha napadeného stavu je důkaz, ne návratový bod

Před čištěním udělejte 1 kompletní kopii souborů, databáze a konfigurace serveru. Je to důkazní snapshot, ne kandidát pro produkční obnovu. Bez něj si snadno smažete jedinou stopu k tomu, odkud kompromitace přišla.

Snapshot uložte mimo napadený hosting. Pokud je server kompromitovaný hlouběji než WordPress, lokální záloha ve stejném účtu může zmizet nebo se sama kontaminovat. Zálohu označte datem, časem, doménou a hashem archivu.

mkdir -p ~/incident-wordpress-$(date +%F)
cd /var/www/example.com

# soubory včetně skrytých položek a časů úprav
tar --xattrs --acls -czf ~/incident-wordpress-$(date +%F)/files.tar.gz .

# databáze; údaje berte z wp-config.php
mysqldump --single-transaction --routines --triggers \
  -u DB_USER -p DB_NAME > ~/incident-wordpress-$(date +%F)/database.sql

sha256sum ~/incident-wordpress-$(date +%F)/* > ~/incident-wordpress-$(date +%F)/SHA256SUMS.txt

Pokud hosting nedovoluje shell, stáhněte archiv přes správce souborů a exportujte databázi přes phpMyAdmin. Není to ideální, ale pořád lepší než začít mazat bez kopie. U větších webů hlídejte, aby export nebyl zkrácený limitem PHP.

Jak poznat, odkud se útočník do WordPressu dostal

Vstupní bod bývá nudný: zastaralý plugin, nulled šablona, slabé heslo, ukradené FTP nebo nezabezpečený upload. Nehledejte jen malware, hledejte mechanismus návratu. Jinak web vyčistíte a za den řešíte stejný incident znovu.

Začněte časovou osou. Najděte první podezřelý požadavek, první změněný PHP soubor a první vytvořený účet. Časy v access logu, databázi a souborovém systému se nemusí dokonale shodovat, ale rozdíl v řádu minut je použitelný.

  • POST požadavky na admin-ajax.php, xmlrpc.php nebo upload endpointy těsně před změnou souborů.

  • Nové PHP soubory v wp-content/uploads, kde běžně nemá být spustitelný kód.

  • Administrátor vytvořený mimo běžnou pracovní dobu nebo z neznámé IP adresy.

  • Změny v wp_options, hlavně siteurl, home, active_plugins a cron.

  • Neznámé úlohy ve WordPress cronu nebo systémovém cronu hostingu.

Logy porovnávejte i s veřejně známými slabinami. Pokud čas kompromitace sedí na vydaný exploit pluginu, máte silný signál. Neznamená to ale, že můžete ignorovat hesla; kombinované útoky přes leak účtu a zranitelný plugin jsou běžné.

Souborový systém: checksums, mtime a podezřelé PHP

Jádro WordPressu nikdy neopravujte ručním porovnáváním soubor po souboru. Použijte WP-CLI a ověřte checksumy proti oficiálním balíčkům. Příkaz wp core verify-checksums odhalí změny v jádře rychleji než grep.

cd /var/www/example.com

wp core version
wp core verify-checksums --locale=cs_CZ

# pokud web používá anglické jádro, locale parametr vynechte
wp plugin list --fields=name,status,version,update
wp theme list --fields=name,status,version,update

U pluginů je situace horší. WP-CLI umí přes wp plugin verify-checksums ověřit pluginy z wordpress.org, ale placené pluginy a vlastní kód tím nepokryjete. Ty instalujte znovu z důvěryhodného zdroje.

# PHP soubory v uploadech jsou silný signál kompromitace
find wp-content/uploads -type f -name '*.php' -print

# nedávno měněné PHP soubory v obsahu webu
find wp-content -type f -name '*.php' -mtime -14 -print

# typické maskování: dvojité přípony nebo náhodné názvy
find wp-content -type f \( -name '*.php.*' -o -name '*.phtml' -o -name '.*.php' \) -print

Podezřelý soubor neotevírejte přes webový prohlížeč. Čtěte ho lokálně v editoru nebo přes less. Typické backdoory používají eval, base64_decode, gzinflate, dynamické názvy funkcí a řetězce rozdělené na kusy.

Databáze: administrátoři, options a injektovaný obsah

Útočník nemusí měnit žádný soubor. Stačí mu administrátor, vložený JavaScript v obsahu nebo změna hodnoty v wp_options. Proto databázi kontrolujte stejně pečlivě jako souborový systém, hlavně u webů s editorem obsahu pro více lidí.

Začněte účty. Vypište všechny administrátory a porovnejte je s reálným seznamem lidí. Kontrola musí pokrýt 100 % účtů s vysokými právy, včetně starých agenturních přístupů, testovacích uživatelů a účtů dodavatelů.

# administrátoři přes WP-CLI
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered

# podezřelé options
wp option get siteurl
wp option get home
wp option get active_plugins --format=json
wp option get cron --format=json | head -c 2000

# hledání skriptů v obsahu příspěvků
wp db query "SELECT ID, post_title FROM wp_posts WHERE post_content LIKE '%<script%' OR post_content LIKE '%iframe%';"

U databázových prefixů nepočítejte automaticky s wp_. Skutečný prefix najdete ve wp-config.php. Pokud má web více instalací v jedné databázi, zkontrolujte všechny tabulky; malware často sedí v zapomenuté kopii webu vedle produkce.

  • wp_users a wp_usermeta: role, e-maily, datum registrace a neznámé účty.

  • wp_options: přesměrování, aktivní pluginy, cron a autoloadované hodnoty.

  • wp_posts: vložené skripty, iframe, skryté odkazy a přepsané šablonové bloky.

  • wp_terms a wp_termmeta: spamové kategorie a SEO odkazy.

  • Vlastní tabulky pluginů: formuláře, objednávky, feedy a napojení na externí API.

Volba opravy: obnova ze zálohy, ruční čištění, rebuild

Existují 3 reálné strategie. Obnova ze zálohy je rychlá, ale bezpečná jen při známém datu napadení. Ruční čištění je vhodné pro menší zásahy. U vážnějšího incidentu doporučujeme čistý rebuild a přenos pouze ověřených dat.

Porovnání strategií opravy kompromitovaného WordPressu
StrategieKdy dává smyslHlavní riziko
Obnova ze zálohyZnáte čisté datum zálohy a vstupní bod incidentuVrátíte i zranitelný plugin nebo ukradený přístup
Ruční čištěníMalware je lokální a web je malýPřehlédnete backdoor v databázi nebo mu-pluginu
Čistý rebuildNeznáte rozsah kompromitace nebo jde o e-shopTrvá déle a vyžaduje přesnou migraci obsahu
Forenzní analýzaŘeší se únik dat, škoda nebo právní dopadVyšší náklady a nutnost neměnit důkazy

Pokud web obsahuje osobní údaje, objednávky nebo členské sekce, řešte i právní stránku incidentu. Technická oprava neodpoví sama o sobě na otázku, zda došlo k úniku dat. Pro e-shop je to rozdíl mezi běžnou údržbou a bezpečnostním incidentem.

Z praxe: když není jistota, volíme rebuild. Ruční čištění má smysl jen tam, kde rozumíte kódu, znáte historii změn a máte oddělený repozitář. Bez toho je to spíš lov náhodných symptomů než oprava příčiny.

Čistá instalace WordPressu bez přenesení backdooru

Čistý rebuild znamená nové soubory z oficiálních zdrojů, ne kopii starého public_html. Jádro WordPressu stáhněte z wordpress.org, pluginy z repozitáře nebo účtu dodavatele a vlastní šablonu z Gitu, ne z napadeného hostingu.

Z původního webu přenášejte jen data, která projdou kontrolou. Typicky databázový obsah, média bez spustitelných souborů a konfigurační hodnoty ověřené proti dokumentaci. Nepřenášejte mu-plugins, cache adresáře, staré zálohy ani neznámé drop-in soubory.

# příklad bezpečnějšího rebuild postupu
mkdir /var/www/example-clean
cd /var/www/example-clean

wp core download --locale=cs_CZ
wp config create --dbname=DB_NAME --dbuser=DB_USER --dbpass='DB_PASS' --dbhost=localhost

# instalujte pluginy znovu, nepřenášejte jejich staré adresáře
wp plugin install contact-form-7 --activate
wp plugin install wordpress-seo --activate

# média kopírujte selektivně a bez PHP
rsync -av --exclude='*.php' --exclude='*.phtml' /var/www/example-old/wp-content/uploads/ wp-content/uploads/

U šablon je nejlepší mít zdroj v repozitáři a produkci jen jako deploy artefakt. Pokud šablona existuje pouze na hostingu, berte ji jako podezřelou. Zkontrolujte minimálně functions.php, vlastní endpointy, AJAX akce a práci se vstupy.

Hesla, klíče, cookies a přístupy po incidentu

Po opravě souborů rotujte přístupy. Nestačí změnit heslo hlavního administrátora. Útočník mohl získat FTP, SSH, databázi, SMTP, hostingový panel, externí služby nebo aktivní cookie relace přihlášených správců.

WordPress používá 8 autentizačních klíčů a salt hodnot v wp-config.php. Jejich změna odhlásí existující relace. Udělejte ji po vyčištění a před návratem webu do veřejného provozu, jinak můžete útočníkovi nechat platnou session.

# vygeneruje nové klíče do wp-config.php
wp config shuffle-salts

# vynuťte reset hesel administrátorů podle interního procesu
wp user list --role=administrator --fields=ID,user_login,user_email

Administraci dejte za dvoufaktorové ověření. U klientských webů doporučujeme minimálně 2FA pro všechny administrátory a editory s právem měnit šablony, pluginy nebo uživatele. Jeden slabý účet stačí k návratu problému.

Hardening po opravě: práva, aktualizace a logování

Opravený web bez hardeningu je jen dočasně čistý. Oficiální dokumentace Hardening WordPress uvádí konkrétní oblasti: aktualizace, práva souborů, databázi, server, SSL a omezení přístupu.

Na sdíleném hostingu nemáte kontrolu nad vším, ale pořád umíte snížit riziko. Vypněte editaci souborů z administrace, zakažte PHP v uploadech, nastavte práva 755 pro adresáře a 644 pro běžné soubory.

# wp-config.php
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', false); // true jen pokud aktualizace řešíte deployem

# práva souborů z kořene webu
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;
chmod 640 wp-config.php

Do wp-content/uploads přidejte pravidlo, které nespustí PHP. Přesná syntaxe závisí na Apache, Nginx nebo hostingu. Princip je stejný: média mají být statická data, ne runtime prostor pro kód útočníka.

# Apache: wp-content/uploads/.htaccess
<FilesMatch "\.(php|phtml|phar)$">
  Require all denied
</FilesMatch>

# Nginx: blok vložte do server konfigurace
location ~* /wp-content/uploads/.*\.(php|phtml|phar)$ {
  deny all;
}

Nezapomeňte na HTTPS, automatické aktualizace bezpečnostních verzí a logování přihlášení. Pokud web jede za CDN nebo proxy, ukládejte skutečnou IP klienta korektně, jinak jsou access logy při dalším incidentu skoro nepoužitelné.

Ověření před návratem do veřejného provozu

Před přepnutím provozu proveďte technickou i aplikační kontrolu. Nestačí otevřít homepage. Ověřte přihlášení, formuláře, objednávkový proces, e-maily, sitemapu, robots.txt, canonical URL a odpovědi pro mobilní i desktopový user-agent.

Zkontrolujte i indexovatelné stránky. Hacked SEO spam se často projeví jen na náhodných URL, ve vyhledávání nebo při přístupu z konkrétního refereru. Pokud řešíte i výkon po opravě, navazuje na to článek proč je WordPress web pomalý.

# rychlá kontrola stavových kódů a přesměrování
curl -I https://example.com/
curl -I https://example.com/wp-login.php
curl -I -A "Googlebot" https://example.com/

# kontrola nečekaných PHP souborů po rebuild procesu
find wp-content/uploads -type f -name '*.php' -print

# kontrola čekajících aktualizací
wp core check-update
wp plugin list --update=available
wp theme list --update=available

Po návratu sledujte logy alespoň prvních 48 hodin aktivně. Hledejte opakované POST požadavky na stejný endpoint, neexistující soubory s příponou PHP, pokusy o xmlrpc a přihlášení na smazané účty. Tady se často ukáže, zda jste vektor opravdu uzavřeli.

Co si z opravy napadeného webu odnést

Oprava napadeného WordPressu je incident response, ne kosmetická údržba. Správné pořadí je izolace, záloha, analýza, rebuild, rotace přístupů, hardening a dohled. Když některý krok přeskočíte, zvyšujete šanci na opakovanou kompromitaci.

Největší technický dluh bývá v tom, že WordPress nemá repozitář, staging, pravidelné aktualizace ani plán obnovy. Incident je nepříjemný, ale zároveň jasně ukáže, kde systém potřebuje proces, ne jen další bezpečnostní plugin.

Pokud web vydělává peníze nebo pracuje s osobními údaji, doporučujeme řešit kompromitaci jako produkční havárii. Rychlá oprava má hodnotu jen tehdy, když po ní víte, co se stalo, co bylo zasaženo a proč se stejná cesta znovu neotevře.

KATEGORIE:

SDÍLET:

Časté otázky

Jak rychle musím napadený WordPress odstavit?
Okamžitě, pokud web rozesílá spam, přesměrovává uživatele, hostuje phishing nebo vytváří podezřelé administrátory. Technicky stačí vracet HTTP 503, ne mazat celý hosting. Cílem je zastavit škody a současně zachovat logy, soubory i databázi pro analýzu. Pokud jde o e-shop, připravte krátkou stavovou stránku mimo napadený server.
Stačí obnovit WordPress ze zálohy?
Ne vždy. Obnova ze zálohy stačí jen tehdy, když víte, že záloha vznikla před kompromitací a zároveň odstraníte původní vektor útoku. Pokud obnovíte měsíc starou zálohu se stejným zranitelným pluginem a stejnými hesly, útočník se často vrátí během hodin. Zálohu berte jako zdroj dat, ne jako kompletní řešení incidentu.
Jak poznám, že je WordPress po vyčištění opravdu čistý?
Jistotu dává kombinace čisté instalace jádra, ověřených pluginů, kontroly databáze, rotace všech hesel a sledování logů po návratu do provozu. Samotný skener nestačí, protože backdoor může být v mu-pluginu, uploadu, cron úloze nebo mimo adresář WordPressu. Po opravě sledujte minimálně chyby 404, nové PHP soubory a podezřelé POST požadavky.
Mám při incidentu mazat všechny pluginy?
Ne naslepo. Nejprve si udělejte kopii napadeného stavu, potom odstraňte neaktivní, nulled a neudržované pluginy. Aktivní pluginy instalujte znovu z důvěryhodného zdroje a nepřenášejte jejich soubory z napadeného webu. U placených pluginů stáhněte aktuální balíček z účtu dodavatele a ověřte kompatibilitu s verzí PHP.
Kolik stojí oprava napadeného WordPressu?
Cena závisí hlavně na rozsahu, dostupnosti záloh a stavu hostingu. Jednoduchý prezentační web může být opraven během několika hodin, e-shop s WooCommerce vyžaduje opatrnější postup kvůli objednávkám, platbám a osobním údajům. Největší rozdíl v ceně dělá to, zda lze provést čistý rebuild, nebo je nutná ruční forenzní analýza.

Zdroje

  1. Hardening WordPress (otevře se v novém okně)primární zdrojWordPress.org
  2. FAQ My site was hacked (otevře se v novém okně)primární zdrojWordPress.org
  3. wp core verify-checksums (otevře se v novém okně)primární zdrojWordPress Developer Resources
  4. wp plugin verify-checksums (otevře se v novém okně)primární zdrojWordPress Developer Resources
  5. OWASP Top 10 (otevře se v novém okně)OWASP Foundation, 2021

Komentáře (0)

Načítám komentáře...

Přidat komentář

Váš email nebude zveřejněn. Všechny komentáře procházejí schválením administrátorem.

Tento web je chráněn službou reCAPTCHA a platí Zásady ochrany osobních údajů a Smluvní podmínky společnosti Google.