Milion adresów spamu w indeksie Google. Jak je usunąć i czego nie robić

Wpisałem w robots.txt jedną linijkę, `Disallow: /`, i przez mniej więcej minutę czułem ulgę. Strona małej firmy, którą opiekujemy się na naszym serwerze, przez kilka tygodni karmiła robota Google spamem, a ja właśnie zamknąłem mu drzwi przed nosem. Potem dotarło do mnie, co zrobiłem. Zamknąłem drzwi, za którymi leżała kartka „ta strona już nie istnieje”. Robot nie wejdzie, więc kartki nie przeczyta. A skoro nie przeczyta, prawie milion śmieciowych adresów zostanie w wyszukiwarce na długo. Linijkę skasowałem.

Ta minuta to dobry skrót całego tematu. Sprzątanie indeksu po włamaniu rządzi się logiką, która jest odwrotna do intuicji: żeby Google o czymś zapomniał, musisz go do tego czegoś wpuścić. W tym tekście opisuję, jak usuwaliśmy z wyszukiwarki 993 752 adresy, których właściciel strony nigdy nie stworzył, co działa, co tylko wygląda na działanie i czego nie robić, nawet jeśli w panice wydaje się rozsądne. Prowadzę agencję AI i automatyzacji dla MŚP, więc piszę z perspektywy kogoś, kto opiekuje się kilkudziesięcioma stronami klientów, a nie z perspektywy pozycjonera z korporacji. Klienta nie wymieniam, domeny też nie.

Spis treści

Skąd na stronie małej firmy prawie milion obcych adresów?

Krótko, bo samo włamanie opisałem już osobno. Atakujący dostał się do WordPressa, dopisał kilka linijek do konfiguracji serwera i od tego momentu strona prowadziła podwójne życie. Ludzie widzieli nudną, pustą stronę. Robot Google dostawał setki kilobajtów spamu i linków. Ta technika nazywa się cloaking i o tym, jak strona klienta przez miesiąc serwowała spam do Google, napisałem trzy dni temu. Jak infekcja odtwarzała się sama z bazy danych i z ukrytych katalogów, rozłożyłem na części w tekście o anatomii infekcji WordPressa.

Tu interesuje mnie tylko skutek, który zostaje po sprzątnięciu serwera. Spamowe adresy miały prostą budowę: strona główna z doklejonym parametrem złożonym z jednej litery i liczby. Liczba się zmieniała, więc wariantów mogło być dowolnie dużo. Logi serwera trzymały się tylko 11 dni, więc widziałem wąskie okienko przed odcięciem strony. W tym okienku robot Google pobrał takie adresy 1 113 410 razy. Unikalnych było 993 752.

Zatrzymaj się przy tej liczbie. To nie są adresy, które Google gdzieś kiedyś widział. To adresy, które w ciągu niecałych dwóch tygodni aktywnie pobierał, czyli traktował jako warte odwiedzenia. Ile z nich trafiło do indeksu, a ile tylko przeszło przez robota, z zewnątrz nie da się policzyć dokładnie. Ale nawet kilka procent z miliona to dziesiątki tysięcy stron z obcą treścią, podpisanych nazwą małej polskiej firmy.

Dla porównania: robot Binga zajrzał w tym czasie niecałe dwa tysiące razy, Yandex 23 razy. Problem był praktycznie wyłącznie googlowy. I wyłącznie po stronie Google trzeba było go rozwiązać.

Dlaczego blokada w robots.txt nie usuwa spamu?

Bo robots.txt nie mówi „zapomnij”. Mówi „nie wchodź”. To dwie zupełnie różne prośby, a w panice łatwo je pomylić.

Pomyśl o listonoszu, który od tygodni dostarcza listy pod adres, gdzie dawno nikt nie mieszka. Chcesz, żeby przestał. Masz dwie możliwości. Możesz przykleić na drzwiach kartkę „adresat wyprowadził się na stałe”. Listonosz podejdzie, przeczyta, odnotuje u siebie i z czasem przestanie przychodzić. Albo możesz postawić przed furtką tabliczkę „wstęp wzbroniony”. Listonosz posłusznie się zatrzyma. Ale kartki na drzwiach nie przeczyta, więc w jego spisie adres zostanie aktywny. Będzie wracał pod furtkę, patrzył na tabliczkę i odchodził, nie wiedząc nic nowego.

Robots.txt to ta tabliczka przy furtce. Kod 410, o którym za chwilę, to kartka na drzwiach. Jeśli postawisz tabliczkę, kartka przestaje mieć znaczenie, bo nikt jej nie przeczyta.

Google pisze o tym zresztą wprost w swojej dokumentacji: strona zablokowana w robots.txt może nadal pojawiać się w wynikach wyszukiwania, jeśli robot wie o niej z innych źródeł, choćby z linków. Pojawia się wtedy bez opisu, z adnotacją, że brak informacji o stronie. W przypadku spamu linków prowadzących do tych adresów było mnóstwo, bo atakujący po to je tworzył, żeby gdzieś je podlinkować. Blokada w robots.txt zamraża więc stan indeksu dokładnie w tym momencie, w którym jest najgorszy. Dlatego mówię, że Disallow spamu nie usuwa, tylko go konserwuje.

Analogia, którą znam z pracy z AI

Przy modelach językowych jest podobny problem i ludzie wpadają w niego tym samym odruchem. Jeśli model nauczył się z danych czegoś, czego nie powinien, to odcięcie mu dostępu do tych danych niczego nie zmienia. Wiedza siedzi już w środku. Żeby model przestał to powtarzać, trzeba mu dać nowy sygnał: inne dane, korektę, przykład właściwej odpowiedzi. Z indeksem Google jest tak samo. Zabranie robotowi dostępu nie kasuje tego, co już zapamiętał. Kasuje dopiero nowa informacja, którą robot sam zobaczy.

Co robot musi zobaczyć, żeby adres wypadł z indeksu?

Musi przyjść pod ten adres i dostać jasny sygnał, że strony nie ma. Masz do wyboru kilka takich sygnałów i nie wszystkie są sobie równe.

404 czy 410?

Kod 404 znaczy „nie znaleziono”. Kod 410 znaczy „usunięto na stałe i nie wróci”. Oba mówią robotowi, że pod adresem nic nie ma. Google oficjalnie twierdzi, że w dłuższej perspektywie traktuje je podobnie, a różnica w tempie wypadania z indeksu jest niewielka. Ja przy spamie zawsze wybieram 410, z dwóch powodów. Po pierwsze, jest jednoznaczny - 404 bywa skutkiem literówki albo chwilowego błędu, 410 jest deklaracją. Po drugie, jest czytelny dla ludzi, którzy za pół roku będą przeglądać konfigurację. Widząc regułę „ten wzorzec adresów zwraca 410”, nikt nie będzie się zastanawiał, czy to błąd.

Noindex

Znacznik noindex w nagłówku strony mówi „ta strona istnieje, ale nie pokazuj jej w wynikach”. Działa świetnie dla stron, które mają istnieć, ale nie mają być w Google - koszyk, panel logowania, wersja testowa. Dla spamu to zły wybór, bo zostawia przy życiu coś, co nie powinno żyć. Uwaga przy okazji: noindex działa tylko wtedy, gdy robot może stronę pobrać. Zablokowana w robots.txt strona z noindex to ta sama pułapka co wcześniej, robot znacznika nie zobaczy. A wpisywanie noindex do samego robots.txt Google przestał honorować jeszcze w 2019 roku, choć w poradnikach wciąż to krąży.

Dlaczego nie przekierowanie na stronę główną

To jest bardzo częsta rada na forach: „przekieruj wszystkie śmieciowe adresy na stronę główną, to nie stracisz ruchu”. Nie rób tego. Masowe przekierowanie tysięcy niezwiązanych adresów na jedną stronę Google rozpoznaje jako tak zwany miękki 404 - stronę, która udaje, że istnieje, a w praktyce nie ma treści, której szukał robot. W najlepszym razie Google to zignoruje i potraktuje jak 404, tylko wolniej. W najgorszym łączysz w oczach wyszukiwarki swoją stronę główną z milionem adresów pełnych spamu. Nie ma tu żadnego ruchu do uratowania, bo ruch na te adresy pochodził od ludzi szukających podróbek, a nie twoich usług.

Strona z odpowiedzią 200 i pustą treścią

Ostatnia pułapka to sytuacja, w której po sprzątnięciu serwera spamowe adresy zaczynają pokazywać stronę główną, bo WordPress ignoruje nieznany parametr i po prostu wyświetla to, co ma pod głównym adresem. Kod odpowiedzi 200, czyli „wszystko w porządku, tu jest strona”. Robot widzi wtedy milion adresów, które działają i mają identyczną treść. Spam znika, ale zostaje milion duplikatów. Dlatego reguła 410 musi łapać wzorzec spamowych adresów jawnie, a nie liczyć na to, że strona „jakoś” zwróci błąd.

Jak to zrobiliśmy, po kolei

Kolejność jest tu ważniejsza niż same kroki, więc opiszę ją tak, jak szła.

Najpierw kopia wszystkiego, zanim cokolwiek zmieniliśmy: katalog strony, około 1,4 GB, i osobno baza danych. Sprawdzona odczytem, nie tylko „skopiowana bez błędu”. Bez tego nie ma śledztwa, a bez śledztwa nie wiesz, czy po sprzątnięciu infekcja nie wróci tą samą drogą.

Potem odcięcie strony. Nie przez kasowanie plików, tylko przez przestawienie w konfiguracji serwera katalogu, z którego strona jest serwowana, na osobny, z prostą stroną przerwy technicznej. Jedna linijka, odwracalna w minutę. Cloaking umarł w tym samym momencie, bo plików, które go realizowały, serwer po prostu przestał czytać.

Trzeci krok to reguła dla spamowych adresów. Każde zapytanie o stronę główną z tym konkretnym parametrem dostaje odpowiedź 410. Wszystko inne idzie normalnie. Reguła jest wąska celowo - nie chcieliśmy przypadkiem zwracać 410 dla adresów, które mają prawo istnieć. Do tego plik mapy strony, którym atakujący podsuwał robotowi swoje adresy, zaczął zwracać 404.

Czwarty krok to ten, w którym prawie się przewróciłem, czyli robots.txt. Po cofnięciu odruchowej blokady plik został otwarty. Robot ma wchodzić pod spamowe adresy tak często, jak chce, bo każda wizyta to jedno przeczytanie kartki „usunięto”.

Na koniec weryfikacja z zewnątrz, nie z serwera. To samo polecenie co przy diagnozie: zapytanie raz jako przeglądarka, raz z podpisem robota Google. Obie odpowiedzi miały identyczne 658 bajtów strony przerwy technicznej. Spamowy adres z dowolną liczbą zwracał 410. Mapa strony zwracała 404. Wtedy dopiero uznałem ten etap za zamknięty.

Gdybyś chciał zrobić coś podobnego u siebie, reguła w pliku .htaccess na typowym serwerze z Apache albo LiteSpeed wygląda mniej więcej tak (litera i nazwa parametru zależą od tego, co zostawił atakujący):

RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)l=[0-9]+ [NC]
RewriteRule ^$ - [G,L]

Flaga `G` oznacza właśnie „gone”, czyli 410. Zanim to wkleisz, sprawdź, czy twoja strona sama nie używa takiego parametru, bo zablokujesz sobie coś legalnego. To jest moment na pięć minut ostrożności, nie na szybkie kopiuj-wklej.

Narzędzie do usuwania w Search Console. Plaster, nie lekarstwo

W Google Search Console jest zakładka „Usunięcia”. Wygląda jak odpowiedź na wszystkie problemy: wpisujesz adres, klikasz, adres znika z wyników. Jest nawet opcja usunięcia wszystkich adresów zaczynających się od podanego ciągu, co przy spamie z jednym wzorcem brzmi kusząco.

Tylko że to narzędzie niczego nie usuwa z indeksu. Ukrywa adresy w wynikach wyszukiwania na mniej więcej pół roku. Jeśli w tym czasie robot nie zobaczy pod tymi adresami 404 albo 410, po pół roku wrócą, jakby nic się nie stało. Narzędzie kupuje czas, w którym prawdziwe sprzątanie ma szansę zadziałać. Samo nie sprząta.

Kiedy więc warto po nie sięgnąć? Gdy spam jest widoczny dla twoich klientów tu i teraz. Ktoś wpisuje nazwę twojej firmy i w pierwszych wynikach widzi buty wojskowe po portugalsku. Wtedy ukrycie ich na pół roku ma sens wizerunkowy, nawet jeśli technicznie nic nie zmienia. Ale tylko w parze z regułą 410 na serwerze. Nigdy zamiast niej.

Druga rzecz w Search Console, którą trzeba sprawdzić, to raport „Ręczne działania” i „Problemy z bezpieczeństwem”. Jeśli Google wykrył włamanie albo cloaking sam, może tam wisieć ostrzeżenie albo kara obejmująca całą domenę. Takie rzeczy nie znikają same po sprzątnięciu. Trzeba złożyć prośbę o ponowne rozpatrzenie i opisać, co zostało zrobione. Krótko i konkretnie: co znaleziono, co usunięto, jak zamknięto drogę wejścia. Google czyta te prośby i lepiej działa na nie rzeczowy opis niż przeprosiny.

I trzecia, oczywista, a często pomijana: jeśli strona w ogóle nie jest podpięta pod Search Console, to podepnij ją przed czymkolwiek innym. Bez tego nie widzisz ani skali problemu, ani tego, czy sprzątanie działa.

Ile to trwa i skąd wiedzieć, że idzie w dobrą stronę?

Tu muszę cię rozczarować, bo ten tekst nie kończy się wykresem, na którym milion spada do zera w tydzień. Tak to nie działa.

Google nie odwiedza wszystkich adresów jednakowo często. W ostatnich jedenastu dniach przed odcięciem robot pobierał spamowe adresy ponad sto tysięcy razy na dobę, bo strona podawała mu coraz to nowe linki i coraz to nową treść. Kiedy zaczęła odpowiadać 410, przestała być ciekawa. Robot przychodzi rzadziej, bo nie ma po co. Każdy adres musi zostać odwiedzony przynajmniej raz, żeby wypaść, a przy milionie adresów niskiej wartości to rozkłada się na tygodnie i miesiące. Najczęściej odwiedzane znikają szybko. Ogon tych, które robot widział raz, może wisieć długo.

Szczerze? To jest najbardziej frustrująca część całej sprawy. Serwer naprawiasz w jeden dzień. Na indeks czekasz miesiącami i nie masz nad tym tempem żadnej kontroli.

Dlaczego nie ufam operatorowi site:

Pierwszy odruch to wpisać w Google `site:domena-firmy.pl` i patrzeć na liczbę wyników. Ta liczba to szacunek, a przy dużych wartościach potrafi skakać o rząd wielkości z dnia na dzień. Do sprawdzenia, czy spam w ogóle jest widoczny i czy jest w pierwszych wynikach, wystarczy. Do mierzenia postępu się nie nadaje.

Co mierzyć zamiast tego

Dwa źródła, oba twarde. Pierwsze to raport indeksowania stron w Search Console, w którym widać, ile adresów Google uznał za „nie znaleziono” i ile wciąż trzyma jako zaindeksowane. Ten raport aktualizuje się z opóźnieniem, ale pokazuje trend.

Drugie to logi serwera. Policz, ile razy dziennie robot Google pyta o spamowe adresy i jaką odpowiedź dostaje. Jeśli wszystkie odpowiedzi to 410, reguła działa. Jeśli liczba zapytań powoli spada, Google uczy się, że tam nic nie ma. Jeśli nagle rośnie, a odpowiedzi zmieniają się na 200 - to znaczy, że infekcja wróciła i trzeba wrócić na serwer, a nie do Search Console.

Tu wraca lekcja, którą zapłaciłem przy śledztwie. Logi trzymały się 10 - 11 dni i tylko dlatego mam jakiekolwiek liczby, że ktoś przyszedł na czas. Gdybyśmy zaczęli tydzień później, nie wiedziałbym nawet, że chodzi o milion adresów. Przy stronach, za które odpowiadasz, retencję logów warto wydłużyć dziś, zanim będzie potrzebna. To kosztuje trochę miejsca na dysku, a oszczędza zgadywania.

Mapa strony z usuniętymi adresami

Jest jeszcze jedna technika, o której warto wiedzieć, choć nie jest konieczna. Można przygotować tymczasową mapę strony, która zawiera właśnie spamowe adresy, i zgłosić ją w Search Console. Brzmi absurdalnie, bo podsuwasz robotowi śmieci, ale cel jest inny: zachęcić go, żeby odwiedził te adresy szybciej i zobaczył 410. Jeden plik mapy strony mieści do 50 000 adresów, więc przy prawie milionie to około dwudziestu plików. Listę można zbudować z logów. Po kilku tygodniach mapę się usuwa. Traktuję to jako opcję przy dużej skali i przy spamie widocznym w wynikach, a nie jako obowiązkowy krok. Przy mniejszych infekcjach sam 410 wystarcza i robi swoje bez pomocy.

Czego nie robić, nawet jeśli kusi

Zbieram to w jednym miejscu, bo każdą z tych rzeczy widziałem jako radę w internecie albo miałem ochotę zrobić sam.

Nie blokuj spamowych adresów w robots.txt. Pisałem o tym na początku i powtarzam, bo to najczęstszy błąd. Blokada przydaje się dopiero wtedy, gdy adresy faktycznie wypadną z indeksu, i to też nie zawsze.

Nie przywracaj starej strony od razu. To był mój drugi odruch, zaraz po robots.txt: mamy czystą kopię sprzed włamania, wgrajmy ją i po sprawie. Tyle że czysta kopia ma tę samą dziurę, przez którą atakujący wszedł za pierwszym razem. Dopóki nie wiesz, którędy wszedł, przywrócenie strony to zaproszenie do powtórki, a druga infekcja na tej samej domenie to dla Google sygnał dużo gorszy niż pierwsza. Strona przerwy technicznej przez tydzień czy dwa jest mniejszym złem.

Nie przekierowuj śmieci na stronę główną. Opisałem wyżej, dlaczego. Nic nie zyskujesz, możesz stracić.

Nie kasuj domeny i nie przenoś firmy na nową. Przy dużej skali spamu ta myśl przychodzi naturalnie: zacznijmy od zera. Ale stara domena to lata historii, linki od kontrahentów, wpisy w katalogach, adres na fakturach i wizytówkach. Właśnie dlatego atakujący ją wybrał. Spam da się z niej zmyć. Historii nowej domeny nie da się kupić.

Nie zgłaszaj linków przez narzędzie do zrzekania się linków (disavow) na ślepo. To narzędzie służy do sytuacji, w których ktoś linkuje do ciebie ze śmieciowych stron i masz przez to karę ręczną. Tutaj problem nie leży w linkach przychodzących, tylko w adresach na twojej własnej domenie. Masowe zrzekanie się linków bez diagnozy częściej szkodzi, niż pomaga.

Nie licz na to, że Google sam wszystko ogarnie, jeśli nic nie zrobisz. Też słyszałem tę wersję: „zostaw, samo przejdzie”. Nie przejdzie, jeśli serwer dalej odpowiada 200 albo dalej serwuje spam robotowi. Google nie odróżni twojej treści od treści atakującego, jeśli obie stoją pod twoim adresem.

Nie płać firmom obiecującym „usunięcie z Google w 48 godzin”. Nikt poza Google nie ma takiej mocy. Takie firmy w najlepszym razie użyją narzędzia do usuwania, które opisałem wyżej i które masz za darmo, i wezmą za to pieniądze. W najgorszym zrobią coś, co pogorszy sprawę.

Lista dla właściciela firmy

Jeśli prowadzisz firmę na 10 - 50 osób i podejrzewasz, że z twoją stroną dzieje się coś podobnego, oto kolejność, w jakiej bym działał. Część zrobisz sam, część zlecisz komuś, kto prowadzi ci stronę.

1. Wpisz w Google `site:` i adres swojej strony. Przejrzyj trzy, cztery strony wyników. Obce języki, produkty, których nie sprzedajesz, dziwne adresy z liczbami - to wystarczy, żeby działać. 2. Podepnij stronę pod Search Console, jeśli jeszcze nie jest. Zajrzyj do „Problemów z bezpieczeństwem” i „Ręcznych działań”. 3. Zleć kopię strony i bazy przed jakąkolwiek zmianą. Poproś, żeby ktoś ją otworzył i sprawdził, a nie tylko potwierdził, że „zrobiona”. 4. Odetnij stronę stroną przerwy technicznej, zamiast kasować pliki. 5. Spamowe adresy niech zwracają 410, a robots.txt niech zostanie otwarty. 6. Ustal, którędy wszedł atakujący, i dopiero potem przywróć stronę. Zaktualizuj WordPressa, wtyczki, zmień hasła, przejrzyj konta administratorów w bazie. 7. Jeśli spam jest widoczny dla klientów, użyj narzędzia do usuwania w Search Console jako tymczasowej zasłony. 8. Złóż prośbę o ponowne rozpatrzenie, jeśli Google nałożył ręczne działanie. 9. Mierz postęp w Search Console i w logach, co tydzień, przez kilka miesięcy.

To nie jest lista na jedno popołudnie. Kroki 1 - 5 da się zrobić w dzień. Krok 6 bywa śledztwem na kilka dni. Krok 9 to cierpliwość na kwartał.

Jeśli spojrzysz na tę listę jeszcze raz, zobaczysz, że prawie nic w niej nie jest skomplikowane technicznie. Trudne jest co innego: przez cały proces musisz robić rzeczy wbrew odruchowi. Odruch mówi „zablokuj”, a trzeba wpuścić. Odruch mówi „przywróć szybko”, a trzeba czekać. Odruch mówi „skasuj i zapomnij”, a trzeba najpierw zrobić kopię. Ja sam w tej sprawie miałem dwa takie odruchy w ciągu godziny i oba musiałem cofać. Właśnie dlatego spisuję to wszystko na chłodno, a nie w dniu incydentu.

Słownik pojęć

  • Indeks Google - spis wszystkich stron, które Google zna i może pokazać w wynikach wyszukiwania. Strona może być w indeksie, nawet jeśli dawno zniknęła z serwera, dopóki robot tego nie sprawdzi.
  • robots.txt - plik na stronie z instrukcjami dla robotów, gdzie im wolno wchodzić, a gdzie nie. Steruje odwiedzinami, nie zawartością indeksu.
  • Disallow - polecenie w robots.txt, które zabrania robotowi wchodzić pod wskazane adresy. Nie usuwa ich z wyników wyszukiwania.
  • Kod 410 (Gone) - odpowiedź serwera „strona usunięta na stałe”. Najczytelniejszy sygnał dla robota, że adres ma wypaść z indeksu.
  • Kod 404 (Not Found) - odpowiedź „nie znaleziono”. Działa podobnie jak 410, ale nie mówi, czy brak strony jest trwały.
  • Noindex - znacznik w kodzie strony albo nagłówku odpowiedzi, który mówi „strona istnieje, ale nie pokazuj jej w wynikach”. Działa tylko wtedy, gdy robot może stronę pobrać.
  • Miękki 404 (soft 404) - strona, która odpowiada „wszystko w porządku”, a w praktyce nie ma treści, której się spodziewano. Google traktuje ją jak brak strony, tylko wolniej.
  • Cloaking - pokazywanie robotom wyszukiwarki innej treści niż ludziom. Jedno z najpoważniejszych naruszeń zasad Google.
  • Google Search Console - darmowe narzędzie Google dla właścicieli stron. Pokazuje stan indeksowania, problemy z bezpieczeństwem i kary ręczne.

Masz w Google adresy, których nigdy nie tworzyłeś?

Napisz do mnie na [email protected] i wklej, co pokazuje ci `site:` przy twojej domenie. Często już z tego jednego zrzutu da się powiedzieć, czy to stary śmieć do wyczyszczenia, czy infekcja, która wciąż żyje na serwerze. Od tego zależy, czy zaczynamy od Search Console, czy od śledztwa.

✓ Sprawdzone na
własnej firmie
cybulski.ai JC
You've successfully subscribed to cybulski.ai
Great! Next, complete checkout for full access to cybulski.ai
Welcome back! You've successfully signed in.
Unable to sign you in. Please try again.
Success! Your account is fully activated, you now have access to all content.
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.