Jeśli skimmer kart wraca do sklepu WooCommerce po usunięciu, atakujący ma nadal dostęp, a najprostszy dostęp to konto z uprawnieniami administratora, którego nie widać w panelu. W sklepie, który sprzątaliśmy, było 7 takich kont. Na liście użytkowników miały rolę „Klient”, ale w tabeli wp_usermeta każde miało nadane bezpośrednio 187 uprawnień, czyli poziom administratora. Żeby je znaleźć, trzeba czytać uprawnienia z bazy, a nie nazwę roli w panelu. Poniżej opisujemy, jak przebiegło sprzątanie, ile trwało i co zmieniliśmy, żeby skimmer nie wrócił po raz kolejny.
Co się stało w tym sklepie?
Sklep na WooCommerce został ponownie zainfekowany skimmerem typu Smilodon, czyli skryptem z rodziny Magecart, który przechwytuje dane kart wpisywane na stronie płatności. Wcześniejsze czyszczenie usunęło kod skimmera. Nie usunęło drogi, którą atakujący go wgrał, więc po jakimś czasie skimmer był z powrotem.
Tą drogą były konta. Lista administratorów w panelu wyglądała normalnie, a podejrzane konta stały na liście jako zwykli klienci.
Jak konto z rolą „Klient” może mieć prawa administratora?
WordPress trzyma role i uprawnienia użytkownika w jednym polu: wp_capabilities w tabeli wp_usermeta. To serializowana tablica, w której obok nazwy roli mogą stać pojedyncze uprawnienia, np. manage_options, edit_plugins czy create_users. WordPress sprawdza przy każdej akcji, czy użytkownik ma konkretne uprawnienie, i nie obchodzi go, z jakiej roli ono pochodzi.
Lista użytkowników w panelu pokazuje tylko nazwę roli. Konto z wpisem „customer” plus 187 uprawnień nadanych bezpośrednio wyświetla się jako „Klient”. Filtr „Administrator” go nie pokaże. Zwykły klient WooCommerce ma w praktyce jedno uprawnienie, read, więc różnica jest ogromna, tylko trzeba zajrzeć do bazy.
Jak sprawdzić, czy w sklepie są ukryci administratorzy?
Najpierw lista kont z rolami, tak jak widzi je WP-CLI:
wp user list --fields=ID,user_login,user_registered,rolesTo pokaże to samo co panel, czyli nazwy ról. Ukryte konta wyjdą dopiero w zapytaniu na uprawnienia. To zapytanie zwraca konta, które mają uprawnienia typowe dla admina, a nie mają roli administratora (prefiks tabel może być inny niż wp_):
SELECT u.ID, u.user_login, u.user_registered, LENGTH(m.meta_value) AS dlugosc
FROM wp_users u
JOIN wp_usermeta m ON m.user_id = u.ID AND m.meta_key = 'wp_capabilities'
WHERE m.meta_value NOT LIKE '%"administrator"%'
AND (m.meta_value LIKE '%manage_options%'
OR m.meta_value LIKE '%edit_plugins%'
OR m.meta_value LIKE '%create_users%')
ORDER BY dlugosc DESC;Kolumna dlugosc pomaga przy dużej bazie klientów. Pole zwykłego klienta ma kilkadziesiąt znaków, a pole z setką uprawnień kilka tysięcy. Pojedyncze konto sprawdzisz też tak:
wp user list-caps 123 | wc -lWynik w okolicach jednego czy dwóch to klient. Wynik w setkach to konto, które może wszystko. Każde trafienie wyjaśnij, zanim cokolwiek usuniesz. Niektóre wtyczki legalnie dodają pojedyncze uprawnienia wybranym kontom.
Masz ten sam problem? Sprawdzimy konta po uprawnieniach, stronę kasy i pliki sklepu, zanim skimmer wróci. Opisz sytuację →
Ile trwało sprzątanie i czy sklep musiał być wyłączony?
Samo sprzątanie zajęło około 16 minut, a sklep był niedostępny dla klientów przez około 2 minuty. Przestój da się tak skrócić, jeśli listę kont do usunięcia, lokalizacje kodu skimmera i zmiany w konfiguracji przygotujesz przed dotknięciem produkcji. Krótkie wyłączenie sklepu na czas usuwania kont i kodu sprawia, że atakujący nie zrobi nic z jeszcze aktywnej sesji w trakcie sprzątania.
Po usunięciu kont warto wylogować wszystkie sesje (np. przez zmianę kluczy salts w wp-config.php) i zmienić hasła administratorów oraz dostęp do bazy.
Jak zabezpieczyć WooCommerce, żeby skimmer nie wrócił?
W tym sklepie wdrożyliśmy dwie zmiany w samym WordPressie:
- DISALLOW_FILE_MODS. Jedna linia w wp-config.php wyłącza instalację i aktualizację wtyczek oraz motywów, a także edytor plików w panelu. Nawet jeśli ktoś przejmie konto admina, nie wgra kodu przez przeglądarkę. Aktualizacje trzeba wtedy robić przez WP-CLI lub wdrożenie.
- 2FA dla administratorów. Samo hasło przestaje wystarczać do wejścia na konto z pełnymi prawami.
// wp-config.php
define('DISALLOW_FILE_MODS', true);Dlaczego kopie bazy były do pobrania mimo reguł w .htaccess?
Bo serwer działał na nginx, a nginx nie czyta plików .htaccess. Katalog z kopiami bazy był „zabezpieczony” regułą deny w .htaccess, która na Apache by zadziałała. Na nginx była zwykłym plikiem tekstowym, a kopie bazy, z danymi klientów i hashami haseł, dało się pobrać publicznie.
Najprościej trzymać kopie poza katalogiem publicznym. Jeśli muszą zostać w nim, blokadę trzeba wpisać w konfiguracji nginx:
location ~* \.(sql|sql\.gz|zip|tar|tar\.gz)$ {
deny all;
}Po zmianie sprawdź z zewnątrz, czy plik kopii zwraca 403 albo 404, a nie 200. Ten sam problem dotyczy wszystkich reguł z poradników „zabezpiecz WordPressa przez .htaccess”: na nginx nie robią nic.
Dlaczego alert z monitoringu nie dotarł?
Monitoring w tym sklepie był, ale jego alert nigdy nie dotarł do odbiorcy. Z punktu widzenia właściciela sklepu monitoringu nie było. Przyczyną może być lokalna poczta serwera, filtr antyspamowy albo nieaktualny adres, i z zewnątrz żadnej z nich nie widać, dopóki alert nie jest potrzebny.
Dlatego raz na jakiś czas wywołaj alert celowo, np. podrzucając nieszkodliwy plik testowy, i sprawdź, czy wiadomość przyszła tam, gdzie powinna. Więcej o monitoringu strony płatności, CSP i wymaganiach PCI DSS 4.0 piszemy w artykule jak sprawdzić, czy checkout nie kradnie kart.
Kiedy zlecić sprzątanie sklepu po skimmerze?
Gdy skimmer wrócił choć raz. To znaczy, że poprzednie czyszczenie zostawiło dostęp, a każdy dzień działania skimmera to kolejne karty klientów. ASAPDevs robi usuwanie malware i audyt bezpieczeństwa sklepu: od kont i uprawnień w bazie, przez stronę kasy, po monitoring z przetestowanym alertem. Sklepy bierzemy też w stałą opiekę WooCommerce, a gdy sklep trzeba ratować od razu, działa pogotowie IT. Jeśli malware w Twoim WordPressie odtwarza się z kilku miejsc naraz, przeczytaj też, dlaczego malware wraca po usunięciu.
