Oczywiście scenariusz wykonywania naprawy może być inny. Przedstawiamy naszą propozycję na oczyszczenie instalacji WP z infekcji przy pomocy komend Linuksa. Na upartego wystarczy nam do tego sama konsola Linux. Np. przy pomocy serwera VPS.
Przeraża Cię ta procedura ? 🙂 Skorzystaj z pomocy specjalisty !
Zawartość artykułu
1. Porównanie wersji z kopii bezpieczeństwa z aktualną wersją plików
Jeśli dysponujemy kopią bezpieczeństwa najlepiej jest dodać ją do repozytorium SVN celem prześledzenia zmian w plikach.
a) Tworzymy repozytorium SVN oraz kopię roboczą:
1 2 3 4 5 6 7 8 |
cd ~ mkdir repozytoria cd repozytoria svnadmin create backup-wordpress cd ~ mkdir workspace cd workspace svn co file:///home/user/repozytoria/backup-wordpress wordpress-infekcja |
(gdzie user – nazwa Twojego użytkownika)
b) Wgrywamy następnie do folderu
1 |
~/workspace/wordpress-infekcja |
Pliki z kopii bezpieczeństwa.
Duże pliki binarne (mp3, mp4, jpg, png, zip, tar) nie są potrzebne do synchronizacji. Najlepiej je usunąć aby przyśpieszyć sobie pracę.
Znajdujemy takie pliki (o wielkości powyżej 500kb)
1 |
find . -type f -size +500k |
i je usuwamy:
1 |
rm /sciezka/do/pliku |
Czytaj jak kopiować i wklejać tekst w konsoli Linux.
Jeśli plik jest to niezbędny plik .js albo .php – zostawiamy go.
Dodajemy wszystkie pliki do kontroli wersji i komitujemy:
1 2 |
svn status | grep "^\?" | sed -e 's/? *//' | sed -e 's/ /\\ /g' | xargs svn add svn ci -m 'wgranie plików z kopii bezpieczeństwa (lub inny dowolny komentarz)' |
c) Pobieramy pliki z zainfekowanej strony do osobnego folderu (tutaj utworzony poniżej folder: wordpress-infekcja), który uprzednio tworzymy:
1 2 3 4 5 |
cd ~ mkdir pliki-stron cd ~/pliki-stron mkdir wordpress-infekcja cd wordpress-infekcja |
d) Gdy już pliki zostaną pobrane dokonujemy synchronizacji:
1 |
rsync -r -t --progress --delete -s --exclude '.svn' ~/pliki-stron/wordpress-infekcja ~/workspace/ |
Nastepnie przeglądamy listę zmian w plikach:
1 2 |
cd ~/workspace/wordpress-infekcja svn st |
Listę dostępnych statusów odnośnie zmienionych plików znaleźć można tutaj : https://linuxporady.pl/lista-statusow-svn-subversion-eng/
Wykonane zmiany w plikach możemy sprawdzić poprzez komendę:
1 |
svn diff /sciezka/do/pliku |
Jednak bardziej pomocne mogą okazać się programy typu Eclipse lub Netbeans z odp. wtyczkami SVN.
Następnie:
Usuwamy złośliwe pliki:
1 |
rm /sciezka/do/pliku |
Leczymy złośliwie zmienione pliki
1 |
svn revert /sciezka/do/pliku |
Przywracamy niezbędne dla działania systemu pliki usunięte (symbol „!” po komendzie svn st) przez hakera:
1 |
svn revert /sciezka/do/pliku |
Po skrupulatnym wykonaniu powyższych czynności nowo powstałe pliki dodajemy do repozytorium:
1 |
svn status | grep "^\?" | sed -e 's/? *//' | sed -e 's/ /\\ /g' | xargs svn add |
Usunięte – wykluczamy z repozytorium:
1 |
svn status | grep "^\?" | sed -e 's/? *//' | sed -e 's/ /\\ /g' | xargs rm -R |
Całość zmian komitujemy:
1 |
svn ci -m 'Nowa kopia robocza (lub inny dowolny komentarz)' |
2. Znalezienie rozmaitych podejrzanych wystąpień w plikach
Każde takie odkrycie badamy z osobna pod kątem czy jest to istotnie zawartość skryptu WP albo modułu, czy fragment złośliwego kodu.
Automatycznie znaleziska są składowane w pliku „zmiany”, który za każdą komendą jest nadpisywany.
a) znalezienie plików które nie mają rozszerzenia PHP a mają znacznik php:
1 |
find -not -iname "*.php" -type f -exec grep -q '<?php' {} \; -print > zmiany |
b) wystąpienia wieloelementowej tablicy _Global:
1 |
find -type f -exec grep -q '\$GLOBAL\S\[$GLOBALS' {} \; -print > zmiany |
c) znalezienie wystąpień tłumionego include. Używamy kilku wariantów wyszukiwania:
1 2 3 |
find -type f -exec grep -q '@include "' {} \; -print > zmiany find -type f -exec grep -q '\@include\ \"' {} \; -print > zmiany |
d) znalezienie wystąpień hexowego wpisywania znaków w PHP:
1 |
find -type f -iname "*.php" -exec grep -q 'chr\(109\)' {} \; -print > zmiany |
tu zamiast 109 możemy użyć innych cyfr
e) znalezienie podejrzanych operacji na zmiennej tablicowej _FILE i funkcji haszującej:
1 2 3 |
find -type f -iname "*.php" -exec grep -q '\$_FILES\[base64_decode' {} \; -print > zmiany find -type f -iname "*.php" -exec grep -q 'gzinflate\(' {} \; -print > zmiany |
f) komendy wyodrębniające podejrzane pod kątem exploitów pliki PHP:
1 |
grep '((eval.*(base64_decode|gzinflate|\$_))|\$[0O]{4,}|FilesMan|JGF1dGhfc|IIIl|die\(PHP_OS|posix_getpwuid|Array\(base64_decode|document\.write\("\\u00|sh(3(ll|11)))' . -lroE --include=*.php* > mozliwe_exploity.txt |
1 2 3 4 |
cd . sploitpattern='r0nin|m0rtix|upl0ad|r57shell|cFaTaLisTiCz_Fx|Tukulesto|99shell|shellbot|phpshell|void.ru|phpremoteview|directmail|bash_history|.ru/|brute *force|multiviews|cwings|vandal|bitchx|eggdrop|guardservices|psybnc|dalnet|undernet|vulnscan|spymeta|raslan58|Webshell' find . -name "*.php" -print0 | xargs -0 egrep -il "$sploitpattern" | sort > mozliwe_exploity.txt |
1 |
grep '((eval.*(base64_decode|gzinflate|\$_))|\$[0O]{4,}|FilesMan|GLOBALS.*exit|JGF1dGhfc|IIIl|die\(PHP_OS|posix_getpwuid|Array\(base64_decode|document\.write\("\\u00|sh(3(ll|11)))' . -lroE --include=*.php* |
g) znalezienie wystąpień includowanego kodu który jest zazwyczaj widoczny w ukrytych (zaczynających się od kropki) plikach PHP udających ikony (rozszerzenie .ico)
1 |
find -type f -exec grep -q 'basename\/\*' {} \; -print > zmiany |
h) znalezienie podejrzanych skrytów o 8-literowej nazwie plików
W niektórych infekcjach – haker umieszcza na serwerze w losowych miejscach pliki o losowej nazwie (to istotne – nazwy są generowane automatycznie i nie mają sensu – to po prostu 8-literowy ciąg znaków). Zazwyczaj są one 8-literowe. Najlepiej wylistować wszystkie takie pliki i znaleźć takie podejrzane wystąpienia:
1 |
find . \( -name "????????.php" \) |
Dla przykładu plik o nazwie typu:
1 2 |
vecqmdgn.php gtyxodmt.php |
może wymagać wglądu – czy rzeczywiście jest częścią webserwisu. Jeśli nie i posiada podejrzany kod. Należy go skasować.
Oczywiście 8-literowy ciąg to nie standard. Jeśli pojawia się dużo plików np. 6-literowych należy odp. zmienić kryteria wyszukiwania.
i) znajdowanie zainfekowanych plików JavaScript wykonujących przekierowanie – brak możliwości zalogowania się do admina albo oglądania strony
więcej na ten temat: https://blog.sucuri.net/2019/11/vulnerable-versions-of-adminer-as-a-universal-infection-vector.html )
1 |
find -type f -name "*.js" -exec grep -q 'document.currentScript.parentNode.insertBefore(s, document.currentScript);' {} \; -print |
Oczywiście ta lista możliwych podejrzanych zmian w plikach nie jest wyczerpująca.
Wszystkie ew. zmiany w plikach musimy zakomitować, aby mieć pewność że dysponujemy aktualną i oczyszczoną kopią roboczą:
1 |
svn ci -m 'Nowa kopia robocza (lub inny dowolny komentarz)' |
j) Wyszukanie plików PHP w folderze ze zdjęciami i próba znalezienia złośliwych skryptów.
Jeśli na serwerze mamy folder ze zdjeciami (np. systemy PrestaShop: /img) a w nim niezliczoną liczbę plików PHP tym prostym zapytniem posortujemy pliki wg rozmiarów i zapiszemy wynik do pliku tekstowego:
1 |
find . -type f -name "*.php" -exec du -h {} \; | sort -h > pliki-php.txt |
W ten sposób plik PHP ze stosunkowo dużym rozmiarem (kilka-kilkanaście kb wielkości) może być potencjalnym plikiem z którego może być przeprowadzony atak.
Dla przykładu, jeśli posiadamy folder ze zdjęciami i w każdym podfolderze jest plik zaślepkowy index.php kierujący do glownej, mozemy łatwo sprwadzic czy któryś z nich nie jest podejrzanie duży i np. w nim znajduje się exploit.
k) znalezienie plików, które były edytowane w przeciągu ostatniego tygodnia:
1 |
find . -type f -name '*.php' -mtime -7 |
Oczywiście zamieniająć cyfrę 7 na np. 14 – wylistujemy pliki z przed 2 tyg. itd.
Analogicznie możemy znaleźć tak pliki ZIP w których czasem hakerzy umieszczają archiwum do wypakowania:
1 |
find . -type f -iname '*.zip' -mtime -7 |
flaga iname nie zwraca uwagi na wielkość liter 😛
3. Aktualizacja i weryfikacja modułów
Należy zaktualizować możliwe najwięcej komponentów w WP. Zatem:
- jądro WordPress
- motywy
- wtyczki
Musimy się także zastanowić czy wszystkie zainstalowane wtyczki są niezbędne do funkcjonowania strony. Niepotrzebne lub podejrzane komponenty należy usunąć.
Po dokonaniu aktualizacji należy uwzględnić zmiany w kopii bezpieczeństwa w SVN. Powtarzamy tutaj proces z pkt. 1 tego artykułu.
4. Ustawienie prawidłowych uprawnień na plikach i folderach.
Następnie całość plików powinna być wgrana przez FTP na serwer docelowy uprzednio po usunięciu zawartości:
1 2 |
find . -type f -exec chmod 644 {} \; find . -type d -exec chmod 755 {} \; |
5. Zmiana haseł powiązanych ze stroną
a) Zmiana wszystkich dostępów FTP (skomplikowane hasło).
Najlepiej jest usunąć wszystkie konta FTP zostawiając tylko jedno, które ma trudne i unikalne hasło.
b) Zmiana wszystkich dostępów CMS.
W dziale użytkownicy w WP należy dokonać przeglądu którzy administratorzy są potrzebni, a którzy nie.
c) Zmiana hasła do bazy danych (skomplikowane, unikalne hasło)
Następnie należy je wprowadzić w pliku
1 |
wp-config.php |
w katalogu głównym
6. Asekuracyjnie. Porównajmy naszą zaktualizowaną wersję strony opartej o WordPress z bazową wersją tego CMS.
Analogicznie jak w pkt. 1:
Upewniamy się, że mamy aktualną wersję kopii roboczej opartej o kopię bezpieczeństwa z SVN:
1 2 3 |
~/workspace/wordpress-infekcja svn st svn up |
Do osobnego folderu wgrywamy aktualną wersję CMS WordPress ze strony: https://pl.wordpress.org/
Tworzymy go w folderze pliki-stron:
1 2 |
cd ~/pliki-stron mkdir wordpress-base/wordpress-infekcja -p |
Następnie synchronizujemy pliki z naszą kopią bezpieczeństwa sprawdzamy zmiany:
1 2 |
rsync -r -t --progress --delete -s --exclude '.svn' ~/pliki-stron/wordpress-base/wordpress-infekcja ~/workspace/ svn st |
Większość wtyczek, motywów itp. będzie usunięta (symbol wykrzyknika). Zapewne nie zawierają się one w podstawowej wersji CMS. Najbardziej kluczowe mogą być podejrzane zmiany w plikach jądra CMS, albo usunięcie plików, które mają łudząco podobną nazwę do składowych plików CMS. Należy przeglądnąć ich zawartość.
7. Dodatkowe zabezpieczenia
Blokowanie wywołań plików php i ukrytych plików php.
W folderze:
1 |
wp-content/uploads |
Umieść plik o nazwie:
1 |
.htaccess |
I zawartości:
1 2 3 4 |
<FilesMatch "\.(php|ico)$"> Order allow,deny Deny from all </FilesMatch> |
Dodatkowo, zgodnie z informacjami zawartymi na stronie: https://perishablepress.com/protect-post-requests/ możemy zupełnie uniemożliwić requesty POST. Czyli jeśli nasza strona nie posiada formularza kontaktowego itp. możemy dodać taką regułę do .htaccess. Jednak uwaga – może to uniemożliwić logowanie do CMS. W takim wypadku na czas logowania należy ją zakomentować:
1 2 3 4 5 |
# deny all POST requests <IfModule mod_rewrite.c> RewriteCond %{REQUEST_METHOD} POST RewriteRule .* - [F,L] </IfModule> |
Widok zakomentowanej reguły:
1 2 3 4 5 |
# deny all POST requests #<IfModule mod_rewrite.c> # RewriteCond %{REQUEST_METHOD} POST # RewriteRule .* - [F,L] #</IfModule> |
8. Sprawdzenie podejrzanych użytkowników bazie danych.
Niekiedy hakerzy przejmują kontrolę nad systemem CMS i za jego pośrednictwem dokonują swoich działań.
Aby się upewnić, że w CMS nie ma takiego backdoora zaloguj się do bazy danych przez program PhpMyAdmin. Dane do zalogowania znajdziesz w pliku:
1 |
wp-config.php |
następnie zaznacz tabelę:
1 |
wp_users |
Jeśli w jej obrębie znajdują się podejrzane konta użytkowników
a) Usuń je – notując ich numery ID
b) Wywołaj komendę:
1 |
DELETE FROM `wp_usermeta` WHERE `user_id` = 2 |
Gdzie 2 – to zanotowany numer ID.
c) zmień hasło do bazy danych i zaktualizuj je w pliku php:
1 |
wp-config.php |
Możesz też wywołać poniższą komendę w SQL (np. w phpmyadmin):
1 |
SELECT * FROM `wp_usermeta` WHERE `meta_key` = 'wp_capabilities' AND `meta_value` LIKE "%administrator%" |
Wskaże ona ID użytkowników w randze admina. Jeśli haker założył dodatkowe konta z takimi użtkownikami – przegladnij je i wykasuj podejrzane konta.
9. Sprawdzenie sytuacji po paru dniach
Należy następnie sprawdzić sytuację na witrynie po paru dniach / tygodniach. Najlepiej dla szybkości pobrać jedynie pliki narażone na atak. Następnie prześledzić ich zmiany przez SVN na identycznej zasadzie jak w pkt. 1 albo 6 niniejszego artykułu:
1 2 |
find -iregex '.*\.\(ico\|php\)$' > pliki tar -czvf pliki.tar.gz -T pliki |
Ewentualnie jak bazujemy na hostingu opartym o Direct Admin dodajmy takie komenty do crona:
1 2 |
find ~/domains -iregex '.*\.\(ico\|php\)$' > ~/domains/pliki tar -czvf ~/domains/pliki.tar.gz -T ~/domains/pliki |
10. Dodanie do CRON polecenia automatycznie usuwającego plik o określonej nazwie
Jeśli plik z exploitem pojawia się zawsze pod specyficzną nazwą np. jest to plik php:
1 |
SHELLcmd.php |
I nie ma na serwerze innego pliku pod tą nazwą. Można po prostu dodatkowo zabezpieczyć się poprzez dodania do CRON automatycznego znalezienia tego pliku i unięcia.
Komenda:
1 |
find -name "SHELLcmd.php" | xargs rm |
CRON ustawiamy aby uruchamiał się co 1 minutę. Np. w Direct Admin wpisujemy w polu minuta:
1 |
*/1 |
11. Popularne dziury w innych systemach CMS.
Jeśli na Twoim serwerze są inne popularne skrypty CMS jak np. Joomla albo PrestaShop przepatrz te strony pod kątem zagrożeń. Dla Joomla wykonaj aktualizację do najnowszej wersji + porównanie plików z plikami z demo tej samej wersji. Dla PrestaShop – podobnie.
Dość popularną dziurą w PrestaShop ostatnimi czasy (szczególnie dla wersji 1.6.x) była często wykorzystywana podatność w module: jmsslider
Więcej informacji znajdziesz tutaj: https://www.joommasters.com/index.php/blog/tutorials-and-case-studies/how-to-fix-security-bug-of-slider-security-breach-of-theme.html