9 kroków do zabezpieczenia strony WordPress

2 grudnia, 2022

Spis treści: Jak zabezpieczyć stronę opartą o WordPress?

WordPress to najpopularniejszy system zarządzania treścią. Korzystając z podobnych rozwiązań, możemy w łatwy sposób uruchomić witrynę internetową. W przypadku zaawansowanych projektów WordPress pozwala na szerokie możliwości dostosowania do potrzeb, również z użyciem wielu wtyczek. Dzięki niskiemu progowi wejścia i łatwej instalacji jest polecany dla mniej technicznych osób, które potrzebują strony internetowej.

Do hostowania dużych serwisów opartych o WordPress często używa się rozbudowanej infrastruktury, na którą może składać się serwer pełniący funkcję load balancer, przynajmniej dwa serwery hostujące kod, osobne serwery baz danych oraz dedykowany storage na dane. Natomiast w przypadku stron generujących mniejszy ruch, hosting będzie najlepszym wyborem.

W najpopularniejszym podejściu do hostowania strony za całość konfiguracji działania serwera odpowiada dostawca. Klientów końcowych powinno interesować jedynie utrzymanie swojej witryny. Dlatego hostingi cieszą się popularnością, również z uwagi na mniejszy koszt w stosunku do serwerów VPS czy serwerów dedykowanych, na których najczęściej jego właściciel jest odpowiedzialny za całokształt. W tym poradniku zamierzam przedstawić szereg dobrych praktyk możliwych do zastosowania w środowiskach z ograniczonym dostępem, które zwiększą ogólny poziom zabezpieczeń WordPressa.

Uważaj, komu zlecasz opiekę nad stroną i jaki hosting wybierasz

Pierwsza rzecz z tym związana jest już na poziomie zlecenia stworzenia i hostowania strony. WordPress, pomimo ogólnej prostoty, wymaga odpowiedniego dobrania motywu i wtyczek, a następnie wprowadzenia zmian w wyglądzie strony. Część zmian może wymagać edycji plików CSS, JS czy nawet PHP, co nie dla każdego będzie łatwym zadaniem. Klientowi końcowemu zależy wyłącznie na możliwości dodania wpisów na stronie, zgodnie z jego wyobrażeniami, dlatego prace programistyczne są zlecane podwykonawcom.

Tutaj problemem mogą być licencje na płatne motywy czy wtyczki. Jeśli konto dla płatnej wtyczki, motywu, zostanie powiązane z adresem zleceniobiorcy, z czasem mogą pojawić się problemy. Załóżmy, że działalność gospodarcza zleceniobiorcy zostanie zawieszona, a wraz z nią klient końcowy utraci dostęp do firmowej poczty lub nawet domeny. W takim wypadku trzeba będzie poświęcić więcej czasu na odnowienie licencji czy zgłoszenie problemu do producenta danego motywu, szablonu, hostingodawcy. Dlatego w miarę możliwości warto licencje obsługiwać adresem e-mail klienta, a nie osób trzecich.

Podobna sytuacja może wystąpić z hostingiem na koncie zleceniobiorcy. Twórca strony może zaoferować hosting u dostawcy, u którego tę usługę wykupił, ponieważ jego konto obsługuje wiele domen. Zleceniodawcy nie mają dostępu do panelu Zleceniobiorcy, dlatego należy rozważyć, czy i komu powierzamy outsourcing nad stroną internetową.

Używaj protokołu HTTPS

Oczywiste jest, że współcześnie szyfrowanie połączenia to standard. Domeny z certyfikatem SSL wyglądają na bardziej wiarygodne, również dlatego, że przeglądarki nie wyświetlą ostrzeżenia przy nazwie domeny w pasku adresu, jeśli korzysta ona z SSL. Na hostingu z reguły instalacja SSL ogranicza się do wybrania odpowiedniej opcji w panelu usługi. Można też użyć Cloudflare, co zapewni dodatkową warstwę ochrony, ponieważ adres IP serwera będzie „ukryty” za siecią CDN.

Jeśli serwis dotychczas był dostępny wyłącznie po protokole HTTP, po aktywacji HTTPS powinno się ustawić ten protokół w adresach podanych jako Adres WordPressa (URL) i Adres witryny (URL). Te opcje znajdują się w Ustawienia -> Ogólne.

HTTPS dla Wordpress

Warto również dodać przekierowanie na HTTPS na poziomie serwera. Zwykle na hostingach działa serwer Apache, co oznacza możliwość dość szerokich zmian w jego konfiguracji (per katalog ze stroną) w pliku .htaccess. Wystarczy dodać jedną regułę:

				
					RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI}

				
			

Jeżeli używamy Cloudflare lub innego serwera pośredniczącego w ruchu, to wtedy wymuszamy HTTPS na poziomie tego serwera (w innym przypadku pojawi się pętla przekierowań) i koniecznie dodajemy poniższy warunek do pliku wp-config.php:

				
					if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') { $_SERVER['HTTPS'] = 'on'; }
				
			

W przypadku braku tej instrukcji przekierowanie na HTTPS zadziała, natomiast część zasobów wciąż będzie pobierana z użyciem protokołu HTTP, co doprowadzi do tzw. mixed content jawiącym się błędami w konsoli przeglądarki:

konsola przegladarki mixed content

Zadbaj o aktualizacje wtyczek, motywu i core WordPressa

Kolejna podstawowa porada to zadbanie o aktualność wersji WordPress, wtyczek i motywów. Dzięki temu strona będzie „odporna” na wykryte podatności. Niektóre zmiany mogą mieć też wpływ na poprawę wydajności.

Podobne zalecenie dotyczy wersji interpretera PHP, jeśli oczywiście wszystkie używane moduły są kompatybilne z nowymi wydaniami. Dnia 8 grudnia 2022 roku zostanie wydany PHP 8.2.

Należy pamiętać, że aktualizacje mogą spowodować błędy w działaniu, dlatego zawsze powinniśmy posiadać kopie zapasowe całej witryny.

Wykonuj i sprawdzaj regularnie kopie zapasowe

Może się wydawać, że to prosty temat, ale w przypadku hostingów, nie zawsze. Większość usługodawców zapewnia własne kopie zapasowe, co na pewno jest dobrym rozwiązaniem. Jednak o kopie powinniśmy zadbać również po naszej stronie. Do tej kwestii należy odpowiednio podejść. Przede wszystkim ogranicza nas pojemność i limity wykonywania procesów na hostingach.

Najważniejsze dane do backupowania to baza danych i katalog /wp-content/uploads, gdzie zapisywane są przesyłane media. Polecam wykorzystać dostępne wtyczki, jak chociażby Duplicator, który sprawdza się także podczas migracji serwisu na inny serwer, czy UpdraftPlus dedykowany dla kopii zapasowych. Zalecam też w pliku .htaccess czy pliku INI (w zależności od konfiguracji hostingu) ustawić wyższy max_execution_time dla PHP i wtedy rozpocząć wykonywanie kopii.

				
					max_execution_time = 30 (lub więcej)
				
			
updraft

Dodam, że dużym ułatwieniem w zadaniu utrzymania serwisu jest zastosowanie CI/CD (Continuous Integration, Continuous Deployment), co z reguły dotyczy dużych projektów. W takim podejściu kod cały czas znajduje się w repozytorium. Po dodaniu nowych funkcjonalności w kodzie przez programistów jest on wysyłany na serwer hostujący stronę. Odpowiednio zaprojektowany proces zmieni wyłącznie zawartość kodu, dane przesłane przez użytkownika pozostają nienaruszone. Wtedy wystarczy skupić się praktycznie wyłącznie na kopii bazy danych i przesłanych plików (nie są one przechowywane w repozytorium). Dzięki CI/CD odtworzenie witryny po awarii ogranicza się do ponownego przesłania kodu i przywrócenia bazy danych oraz różnych mediów.

Poniższy zrzut ekranu przedstawia katalogi i pliki utworzone przez narzędzie Deployer, które ułatwia automatyzację wdrożeń aplikacji internetowych. W katalogu wordpress/shared znajdują się dane, pozostające pomiędzy kolejnymi wydaniami oznaczonymi numerami w katalogu releases. Za każdym razem tworzone jest dowiązanie symboliczne do tych danych. Dodatkowo widoczne dowiązanie o nazwie current oznacza zwykle najnowsze wydanie. Taki układ umożliwia wdrażanie nowych wersji bez żadnych przestojów, a w razie błędów pozwala na sprawny powrót do działającej aplikacji.

deployer

Usuń niepotrzebne wtyczki i motywy

WordPress zawiera domyślnie zainstalowane motywy i wtyczki, a nawet przykładową stronę, wpis i komentarz. Raczej nie są potrzebne, dlatego nie ma sensu, aby je przechowywać. Nie oszczędzimy w ten sposób dużej ilości miejsca, natomiast warto trzymać porządek na swoim miejscu pracy.

Nie należy nigdy instalować wtyczek czy motywów z różnych niezaufanych źródeł. Warto też sprawdzać, kiedy instalowane rozwiązanie było ostatnio uaktualniane oraz czy jest popularne i zawiera pozytywne recenzje.

Przy okazji wspomnę o możliwości kompresji dodawanych treści graficznych. Mniejszy rozmiar pliku oznacza zmniejszony czas ładowania strony, co ma szczególne znaczenie, jeśli nie korzystamy z zaawansowanych rozwiązań cache, jak Varnish.

Zabezpiecz logowanie do panelu administratora

Domyślnie panel znajduje się pod adresem <domena>/wp-login.php. Do zabezpieczenia logowania do panelu administratora można zmienić tę nazwę za pomocą wtyczki WPS Hide Login. Zmiany dokonujemy w menu Ustawienia -> Ogólne.

wps hide login

Inna możliwość to ustawienie autoryzacji HTTP na tym adresie. Można tego dokonać w pliku .htaccess:

				
					SetEnvIf Request_URI ^/wp-login.php auth=1
AuthUserFile /home/users/avlab/folder/.htpasswd
AuthName "Authorization required"
AuthType Basic
Order Allow,Deny
Satisfy any
Allow from all
Require valid-user
Deny from env=auth

				
			

W pliku .htpasswd zapisujemy poświadczenia. Ten plik nie powinien być zapisany w katalogu głównym strony. Jego zawartość można utworzyć, korzystając z dostępnych generatorów (np. tego).

Efekt w przeglądarce:

basic auth

Można również zezwolić na dostęp do panelu admina wyłącznie wybranych adresóom IP:

				
					<Files wp-login.php>
deny from all
allow from 192.168.1.100
</Files>
				
			

Opisując sposoby blokowania zasobów w .htaccess, wspomnę też o pliku xmlrpc.php. O zagrożeniach wykorzystania mechanizmu, za który on odpowiada, pisaliśmy w tym artykule.

Blokada ogranicza się do tej zawartości:

				
					<Files xmlrpc.php>
deny from all
</Files>
				
			

Oprócz wymienionych metod należy pamiętać o używaniu mocnych haseł. Istnieje też opcja dodania 2FA do logowania, np. poprzez wtyczkę miniOrange 2 Factor Authentication.

Monitorowanie hostingu, dostępności strony internetowej

Ciągłość działania naszych serwisów powinna być monitorowana. Dostępny jest szereg bezpłatnych i komercyjnych usług do tego służących. Zwykle ich działanie sprowadza się do weryfikowania odpowiedzi na wysyłane co określony czas zapytania. Jeśli kod odpowiedzi oznacza błąd, to z reguły otrzymujemy stosowne powiadomienie na e-mail, wiadomość od bota np. na Microsoft Teams czy zwykły SMS.

uptime alert

Czy korzystać ze wtyczek do zabezpieczania WordPress?

Część osób używa różnych wtyczek mających chronić naszą witrynę. Osobiście nie wydaje mi się, że ma to większy sens, ponieważ w przypadku WordPress bezpieczeństwo możemy zwiększyć, wykonując zupełnie podstawowe kroki. Również hostingodawcy korzystają z różnych metod ochrony, takich jak ModSecurity czy własne systemy firewall. Bardziej uzasadnione jest monitorowanie i dbanie o stan witryny zamiast nadmiernego zaufania do wybranej wtyczki z kategorii „security”.

Narzędzie WPScan: sprawdź podatności WordPress

WPScan to narzędzie do testowania bezpieczeństwa serwisów opartych o WordPress. Na podstawie zebranych wyników możemy wprowadzić konieczne zmiany w celu poprawy stanu zabezpieczeń. WPScan najprościej uruchomić jako kontener Docker.

				
					docker pull wpscanteam/wpscan
docker run -it --rm wpscanteam/wpscan --url https://blog.local --random-user-agent
				
			

Przykładowy rezultat skanowania:

				
					[+] URL: https://blog.local/ [10.0.0.215]
[+] Started: Wed Nov 30 16:14:41 2022

Interesting Finding(s):

[+] Headers
| Interesting Entry: Server: nginx/1.18.0 (Ubuntu)
| Found By: Headers (Passive Detection)
| Confidence: 100%

[+] robots.txt found: https://blog.local/robots.txt
| Interesting Entries:
| - /wp-admin/
| - /wp-admin/admin-ajax.php
| Found By: Robots Txt (Aggressive Detection)
| Confidence: 100%

[+] XML-RPC seems to seems be enabled: https://blog.local/xmlrpc.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%
| References:
| - http://codex.wordpress.org/XML-RPC_Pingback_API
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_ghost_scanner/
| - https://www.rapid7.com/db/modules/auxiliary/dos/http/wordpress_xmlrpc_dos/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_xmlrpc_login/
| - https://www.rapid7.com/db/modules/auxiliary/scanner/http/wordpress_pingback_access/

[+] WordPress readme found: https://blog.local/readme.html
| Found By: Direct Access (Aggressive Detection)
| Confidence: 100%

[+] The external WP-Cron seems to be enabled: https://blog.local/wp-cron.php
| Found By: Direct Access (Aggressive Detection)
| Confidence: 60%
| References:
| - https://www.iplocation.net/defend-wordpress-from-ddos
| - https://github.com/wpscanteam/wpscan/issues/1299

[+] WordPress version 6.1.1 identified (Latest, released on 0001-01-01).
| Found By: Rss Generator (Passive Detection)
| - https://blog.local/feed/, <generator>https://wordpress.org/?v=6.1.1</generator>
| - https://blog.local/comments/feed/, <generator>https://wordpress.org/?v=6.1.1</generator>

[+] WordPress theme in use: hestia
| Location: https://blog.local/wp-content/themes/hestia/
| Latest Version: 3.0.24 (up to date)
| Last Updated: 2022-09-28T00:00:00.000Z
| Readme: https://blog.local/wp-content/themes/hestia/readme.txt
| Style URL: https://blog.local/wp-content/themes/hestia/style.css?ver=6.1.1
| Style Name: Hestia
| Style URI: https://themeisle.com/themes/hestia/
| Description: Hestia is a modern WordPress theme for professionals. It fits creative business, small businesses (r...
| Author: ThemeIsle
| Author URI: https://themeisle.com
|
| Found By: Css Style In Homepage (Passive Detection)
| Confirmed By: Css Style In 404 Page (Passive Detection)
|
| Version: 3.0.24 (80% confidence)
| Found By: Style (Passive Detection)
| - https://blog.local/wp-content/themes/hestia/style.css?ver=6.1.1, Match: 'Version: 3.0.24'

[+] Enumerating All Plugins (via Passive Methods)
[+] Checking Plugin Versions (via Passive and Aggressive Methods)

[i] Plugin(s) Identified:

[+] contact-form-7
| Location: https://blog.local/wp-content/plugins/contact-form-7/
| Latest Version: 5.6.4 (up to date)
| Last Updated: 2022-10-19T09:20:00.000Z
|
| Found By: Urls In Homepage (Passive Detection)
| Confirmed By: Urls In 404 Page (Passive Detection)
|
| Version: 5.6.4 (90% confidence)
| Found By: Query Parameter (Passive Detection)
| - https://blog.local/wp-content/plugins/contact-form-7/includes/css/styles.css?ver=5.6.4
| Confirmed By: Readme - Stable Tag (Aggressive Detection)
| - https://blog.local/wp-content/plugins/contact-form-7/readme.txt

[+] Enumerating Config Backups (via Passive and Aggressive Methods)
Checking Config Backups - Time: 00:00:02 <=> (137 / 137) 100.00% Time: 00:00:02

  [i] No Config Backups Found.

  [!] No WPScan API Token given, as a result vulnerability data has not been output.
  [!] You can get a free API token with 25 daily requests by registering at https://wpscan.com/register

  [+] Finished: Wed Nov 30 16:14:48 2022
  [+] Requests Done: 172
  [+] Cached Requests: 7
  [+] Data Sent: 55.013 KB
  [+] Data Received: 435.114 KB
  [+] Memory used: 342.496 MB
  [+] Elapsed time: 00:00:07
				
			

Podsumowanie zabezpieczania strony opartej o Wordpress

To jedynie najistotniejsze elementy, na które powinniśmy zwrócić uwagę podczas procesu zabezpieczenia instalacji WordPress. Nic nie gwarantuje pełnego bezpieczeństwa, niemniej ich wdrożenie pozwoli na zwiększenie ogólnego poziomu zabezpieczeń. Trzeba pamiętać, że nie wszystkie opisane podpunkty są możliwe do wprowadzenia, tak samo pewne specyficzne projekty mogą wymagać jeszcze innych metod ochrony.

PODZIEL SIĘ:

Czy ten artykuł był pomocny?

Kliknij na gwiazdkę, aby zagłosować!

Średnia ocena: 5 / 5. Liczba głosów: 7

Jak na razie nikt nie podzielił się opinią.

guest
1 Komentarz
najstarszy
najnowszy oceniany
Inline Feedbacks
View all comments

Wyrażam zgodę na przesłanie oferty drogą telefoniczną przez IT Partners security sp. z o.o. z siedzibą Katowicach ul.Padereskiego 35 na podany przeze mnie adres e-mail zgodnie z ustawą z dnia 10 maja 2018 roku o ochronie danych osobowych (Dz. Ustaw z 2018, poz. 1000) oraz zgodnie z Rozporządzeniem Parlamentu Europejskiego i Rady (UE) 2016/679 z dnia 27 kwietnia 2016 r. w sprawie ochrony osób fizycznych w związku z przetwarzaniem danych osobowych i w sprawie swobodnego przepływu takich danych oraz uchylenia dyrektywy 95/46/WE (RODO).

Wyrażam zgodę na przesłanie oferty drogą mailową przez IT Partners security sp. z o.o. z siedzibą Katowicach ul.Padereskiego 35 na podany przeze mnie adres e-mail zgodnie z ustawą z dnia 10 maja 2018 roku o ochronie danych osobowych (Dz. Ustaw z 2018, poz. 1000) oraz zgodnie z Rozporządzeniem Parlamentu Europejskiego i Rady (UE) 2016/679 z dnia 27 kwietnia 2016 r. w sprawie ochrony osób fizycznych w związku z przetwarzaniem danych osobowych i w sprawie swobodnego przepływu takich danych oraz uchylenia dyrektywy 95/46/WE (RODO).

[ninja_tables id=”27481″]