Zavolat Další kontakty >
E-mail Kontakty

Lynt na zimních konferencích: 16.2. Jakub Kašparů na PPC Masters v Berlíně, 18.2. Vláďa Smitka na WordCampu v Praze

Verze WordPress - skrývat, nebo ne?

Má smysl skrývat použitou verzi WordPress? Zlepší skrytí verze bezpečnost vašeho webu? Spíše ne. V článku popisuji důvody a také mou novou metodu detekce verze WP.

[English version]

V mnoha článcích a přednáškách o bezpečnosti WordPress se dozvíte, že je velmi důležité skrýt verzi WP. A tento bod má často velmi velkou prioritu. Ve světle posledních událostí ve světě WordPressu, kdy číslo verze jasně ukázalo, zda je web obsahuje závažnou zranitelnost ve WP REST API, se o tuto problematiku zajímá velké množství uživatelů.

Osobně si nemyslím, že by se mělo jednat o nějak důležitou součást procesu zabezpečování webu. Nemyslí si to ani tvůrci WordPress (se kterými ne se vším souhlasím) a proto se verzi skrýt ani nesnaží. Své argumenty proberu níže, nejprve bych se však věnoval tomu, jaké jsou základní metody detekce verze a jak se jim bránit (pokud přeci jen chcete).

readme.html

  • nejsnadnější cesta, jak zjistit verzi WP je navštívit adresu /readme.html, která nám verzi velkým písmem prozradí

  • od verze 4.7 je tato metoda méně použitelná, protože přestala být zobrazována minor verze (4.7.2) a je zobrazována pouze major (4.7)

meta generator

  • vygenerovaná WordPress stránka obsahuje metatag generator s číslem verze

  • <meta name="generator" content="WordPress 4.7.2" />

  • tato metoda již vyžaduje trochu hledání

RSS feed

  • pokud navštívíte adresu /feed/ můžete najít XML element generator s číslem verze

  • <generator>https://wordpress.org/?v=4.7.2</generator>

Tyto 3 metody jsou jednoznačně nejrozšířenější.

Pokusy o skrytí jsou v případě readme.html realizovány zákazem přístupu k tomuto souboru například pomocí .htaccess

   <files readme.html>
        order allow,deny
        deny from all
   </files>

Takto bude vrácen chybový kód 403 - přístup odepřen, který nám napovídá, že soubor pravděpodobně existuje, ale jen je k němu přístup zakázán.

Pokud chceme soubor skrýt, je lepší předstírat, že vůbec neexistuje - vrácením kódu 404

RewriteRule ^readme.html - [L,R=404]

Na odstranění verze z metatagů a feedu už je potřeba spolupracovat s WP. Číslo verze se bere v souboru wp-includes/version.php kde jej nastavuje do globální proměnné wp_version. Některé metody odstranění fungují tak, že si “předrenderují” stránku (ob_start ...) a naleznou všechny výskyty řetězce s danou verzí a odstraní ho. Nejen že je to tak trochu plýtvání výkonem, ale navíc tato metoda již nefunguje pro /feed a i když ji už pro feedy upravíte, tak není vyhráno - věděli jste například, že číslo verze zjistíte i ze souboru /wp-links-opml.php? Pohlídat si vše vyžaduje značné úsilí.

Správnější postup je typický pro WP - využití hooku the_generator:

add_filter('the_generator', '__return_empty_string');

Toto z výše zmíněných výpisu číslo verze odstraní.

Často se však stává, že autoři šablon/pluginů chtějí po updatu WP klientům dodat nové verze svých js/css souborů a tak při jejich registraci přidávají parametr var=wp_verze.

/wp-includes/js/wp-embed.min.js?ver=4.7.2

Tento parametr je možné opět pomocí hooku odstranit:

function lynt_remove_ver( $src ) {
   $src = remove_query_arg('ver', $src);
    return $src;
}
add_filter( 'script_loader_src', 'lynt_remove_ver' );
add_filter( 'style_loader_src', 'lynt_remove_ver' );

Tímto snippetem se ze všech css a skriptů odstraní parametr ver. Je možné tuto funkci rozšířit o odstraňování verze pouze pokud se jedná o číslo verze WP (podle globální proměnné $wp_version), ale pro ilustraci řešení snad příklad stačí.

Těchto pár řádků je kompletní funkcionalita, kterou nabízí mnoho pluginů slibujících skrývání verze.

Možná vás napadne, že by bylo zajímavé změnit číslo verze rovnou v souboru version.php. To rozhodně není dobrý nápad - rozbijete si tak aktualizace a porušíte tak konzistenci vaší instalace WP - pokud je na serveru nějaký nástroj, který hlídá, zda jsou zdrojové soubory nepozměněny, nebude se mu to líbit.

Pokud se mi všechno toto podaří ošetřit, tak stále zbývá mnoho dalších možností, jak verzi WP poznat. Mohu například porovnat hashe různých statických souborů z jádra WP.

Pokud například z webu stáhnu soubor /wp-admin/js/customize-controls.js a spočítám jeho md5 hash a vyjde d89eff32867dbead906999d2d33df9dc, tak s určitostí vím, že se jedná o první verzi 4.7 - v jiné verzi se přesně s tímto obsahem soubor neobjevil. Pokud je c48eef3773572618f27809300fae0cde, jedná se o 4.3, ve verzi 3.9 půjde o 119ce8b94732f6eb170f8215aa65d47e atd.

A tento postup lze s úspěchem použít u mnoha dalších souborů a přesně určit verzi WP mimo několika výjimek, kdy se mezi verzemi žádné statické soubory nezměnily.

Seznam unikátních souborů v jednotlivých verzích wp naleznete v mém gistu. Pokročilejší analýzou změn ve více souborech mezi verzemi dostaneme ještě mnohem přesnější určení verze.

Nová metoda detekce

Zrovna verze 4.7.1 a 4.7.2 byly tím případem a pro svou analýzu dopadů aktuální zranitelnosti ve WP REST API jsem tento problém musel vyřešit. Soubor readme.html použít nebylo možné, protože WP již nezobrazuje minor verze a weby s bezpečnostními pluginy nastavenými na skrývání verze WP nebylo možné rozpoznat. Potřeboval jsem tady verzi zjišťovat v době, kdy pluginy ještě nezačnou svou práci a zároveň je vypisován výstup se statickými soubory doplněnými o atribut verze. To u WP nastává v několika případech.

Pokud přistoupíte k dialogu pro instalaci - /wp-admin/install.php nebo /wp-admin/upgrade.php - tento soubor musí fungovat ještě dříve než je samotný WP vůbec aktivní. Pokud k němu přistoupíte po instalaci, sice vám řekne, že je WP již nainstalován, ale zároveň ve zdrojovém kód prozradí - právě parametrem ver u statických souborů - opravdovou verzi WordPress. K tomuto účelu lze použít i soubor /wp-login.php. Na některých serverech je přístup k install.php zakázaný, s blokací upgrade.php jsem se však zatím nesetkal (mimo přípúadů s kompletní blokací složky /wp-admin).

Jak detekovat WP samotný?

Pokud chcete jen zjistit, že web používá WordPress, můžete použít několik dalších metod.

  • Vyhledání řetězce wp-content v obsahu stránky - nevýhodou je, že vznikají falešná pozitiva v případě, že jsou na webu hotlinkovány obrázky z jiného webu, je také možné složku wp-content přejmenovat (WP s touto možností počítá). Výhodou může být, že lze detekci provádět i přes různé vyhledávače a cache - např. přes archive.org lze zjistit, že web WP používal i v minulosti.
  • Vyzkoušení adresy /wp-trackback.php nebo /wp-links-opml.php - v případě WP tato adresa vrátí XML jinak 404. Ve výjimečných případech web nedovoluje přímý přístup k PHP souborům a tato metoda nemusí fungovat.
  • Dalším PHP souborem je /wp-admin/admin-ajax.php (od WP 2.1), který při přímém přístupu vrací pouze číslo. Někdy je blokován přístup k celému adresáři wp-admin, ale pro tento soubor by se měla dělat výjimka, jinak mohou přestat fungovat funkcionality, které na frontendu AJAX využívají.
  • Vysoký výkon mají detekční metody založené na statických souborech - nabízí se /readme.html, ale vzhledem ke snahám přístup k němu blokovat lze s větším úspěchem použít test existence souboru /wp-includes/js/colorpicker.js, který je ve WP od verze 2.0. Stejně jako s možností změny adresáře wp-content lze měnit i wp-includes, takže ani tato metoda nemusí být 100% spolehlivá.
  • Pokusy o skrývání se týkají především novějších verzí. V případě, že si někdo dal se skrývání opravdu práci, můžete zkusit, zda nezapomněl třeba na další rewrite administrace, jako je např. /dashboard nebo /login (od verze 3.4.1 - funkce wp_redirect_admin_locations ve souboru /wp-includes/canonical.php).

 

Z informací výše plyne, že pokusy o skrytí verze WP jsou spíše boj s větrnými mlýny a pokud byste měli se skrýváním strávit více než 10 minut svého času, nevyplatí se ho plýtvat. Na našich serverech blokujeme přístup k několika souborům jako je readme.html a dalších readme ve složkách pluginů na straně serveru (viz https://github.com/lynt-smitka/WP-nginx-config), ale je to především z důvodu vyhnutí se masivním scanováním než, že bychom tím chtěli posílit bezpečnost.

Dobrá, a co tedy aktuální problém, kdy na konkrétní minor verzi záleželo, pomohlo by její skrytí? Nepomohlo. Podobné masivní automatizované infekce - ty tvoří naprostou většinu útoků, dovoluji si odhadnou že to bude 99,9% všech útoků - se vůbec neobtěžují zkoumat web a rovnou se snaží exploitovat zranitelnou adresu, nezajímá je dokonce ani to, zda je web opravdu na WP. Cílem je v co nejkratší době napadnout co nejvíce webů, než budou mít aplikovánu opravu a jakákoliv další komunikace s webem by znamenala zbytečné zdržení.

Skrytí verze WP patří k technikám “security by obscurity”, ve většině případů skrytí ničemu neublíží, ale nemůžete očekávat, že by přineslo nějakou zásadní ochranu. Existují i placené pluginy, které se snaží info o WP co nejvíce skrývat, ale z principu nemohou fungovat na 100%, proto bych se jim osobně vyvaroval. Pokud pravidelně aktualizujete a vaše verze je aktuální, nemáte důvod tento fakt skrývat - to že máte vše aktuální reálné útočníky spíše odradí.

Další zajímavé zdroje:

Update:

WPscan již implementoval novou techniku zjišťování verze WordPress do nové verze tohoto nástroje.

Provedl jsem opakované scanování českých WP webů pro zjištění aktuální verze s použitím nové metody popsané v tomto článku. Navíc jsem svou databázi rozšířil na více než 88 000 funkčních českých WP webů.

Výstupy:

Komentáře

Přidat komentář

K článku prozatím nebyly přidány žádné komentáře.