Wpisy
Bezpieczeństwo sklepów e‑commerce — trzy wektory, które widuję w praktyce
Credentials do panelu, skimmer ukryty za „bugiem” checkoutu i injection w polu komentarza — co łączy realne incydenty i jaką checklistę z nich biorę.
Przy sklepach, przy których pracuję, włamania rzadko wyglądają jak w filmie. Nie ma hollywoodzkiego zero-daya na ekranie. Jest sesja w panelu, dziwny checkout, albo próba wstrzyknięcia kodu w pole, którego nikt nie uważa za „powierzchnię ataku”.
Poniżej trzy anonimowe case’y — różne platformy, różne wektory, jeden wspólny wniosek: sygnał biznesowy bywa pierwszym alertem bezpieczeństwa, a po incydencie liczy się nie tylko cleanup, ale dokumentacja (w tym pod RODO). Bez payloadów, bez haseł i bez identyfikatorów klientów.
Zanim przejdę do chronologii: w ekosystemie PHP / e‑commerce te historie rzadko zaczynają się od „magicznego” zero-daya. Najczęściej w tle leży coś z tej listy — brak 2FA w panelu, słabe albo współdzielone poświadczenia (panel, SSH/SFTP, FTP), zaległe update’y core i pluginów/modułów, albo supply chain: niesprawdzona wtyczka / motyw z marketplace’u, który wnosi podatność albo złośliwy kod. Case’y poniżej to konkretne scenariusze na tym podłożu.
Case 1: panel WordPressa, skradzione hasło, malware w pluginach
Średni sklep na WordPress + WooCommerce. Klasyczny setup: dane klientów w zamówieniach, Cloudflare przed hostingiem, panel admina jako główny punkt sterowania.
W nocy atakujący wszedł do panelu, wgrał zestaw typowy dla post-compromise: webshell, plugin utrzymujący ukrytego admina oraz downloader (ten ostatni w logach wyglądał na nieużyty). Aktywność trwała kilkanaście godzin; wykrycie przyszło w południe — nietypowe pliki i zepsuty panel. Cleanup zajął ok. godziny; potem hardening i dokumentacja.
Przyczyna
Najbardziej prawdopodobny wektor: skompromitowane dane logowania (infostealer / wyciek), nie łamanie CAPTCHA. Alternatywa — stary, niezałatany komponent sklepu — była rozważana, ale bez twardego dowodu. Logi WAF/CDN pokazywały aktywność z panelu, w tym ścieżkę uploadu pluginów.
Skutki
- nieautoryzowany dostęp do admina i persistence w
wp-content, - ryzyko dla danych osobowych (potencjalny dostęp istniał),
- zepsuty panel jako paradoksalny sygnał wykrycia — jeden z komponentów przerywał normalne wykonanie kodu.
Co sprawdziłem pod kątem danych klientów
Potencjalny dostęp ≠ automatycznie naruszenie ochrony danych. Ocenę oparłem o logi: brak nietypowych połączeń wychodzących, brak skoku wolumenu, brak ścieżek typowych dla dumpów DB w ruchu atakującego, malware nie wyglądał na celowaną eksfiltrację. Wniosek dokumentacyjny: niskie ryzyko + szybka reakcja → uzasadnienie braku zgłoszenia do UODO (art. 33), ale z notatką, timeline’em i analizą z IOD — nie „zignorujemy temat”.
Przeciwdziałanie
Contain → eradicate → harden → document. Zanim cokolwiek skasuję na żywej instancji, robię szybki snapshot / image (dysk + stan bazy) — materiał pod analizę śledczą i zabezpieczenie przed utratą spójności danych. Dopiero potem: usunięcie artefaktów i konta atakującego, warstwa przed panelem (htpasswd), blokada zapisu w katalogu pluginów, zmiana hasła bazy, update core i pluginów, skaner/WAF z alertami, ukrycie URL logowania, rotacja haseł (w tym htpasswd), 2FA dla adminów, backup 3-2-1 z retencją logów, audyt kont FTP/WP i spisane procedury. Nie zostawiłem tego na „później” — hardening poszedł razem z cleanupem.
Lekcja: większość włamań do sklepów WP, które widuję, to nadal credentials + panel, nie egzotyczny exploit.
Case 2: „bug kodu rabatowego”, a pod spodem Magecart + RCE
Inny sklep — PrestaShop. Zgłoszenie od klienta brzmiało jak pilny ticket UX: kod rabatowy w koszyku od razu przenosi do płatności; część zamówień bez numeru telefonu; „płatność się nie udaje”. Po chwili analizy okazało się, że to nie regres checkoutu.
Co się działo naprawdę
Uproszczony kill chain:
- Rekonesans — nocne skany pod typowe webshelle i ścieżki platformy.
- RCE — aktywny shell w cache znanego modułu (katalog cache z wykonywalnym PHP).
- Eskalacja — lokalizacja pliku konfiguracyjnego → credentials bazy → zapytania KPI (nie pełny dump klientów przez ten kanał).
- Monetyzacja — osobny tor: skimmer udający warstwę płatności (loader w
head+ endpoint „GTM-like” na obcej domenie). Zbierał dane klienta i karty; po kradzieży „płatność fail”, skrypt nie odpalał drugi raz.
Okno skimmera: od wgrania plików do usunięcia — rzędu dni, bo pierwszy sygnał wyglądał jak bug frontu.
Przyczyna / skutki
Przyczyna: przestarzały / podatny moduł + cache traktowany jak bezpieczne miejsce na kod. Skutki: RCE (utrzymanie dostępu, wycena sklepu) i skimmer kart (osobna szkoda). Brak dumpa klientów w SQL nie oznacza braku szkody — karty poszły innym kanałem.
Przeciwdziałanie
Usunięcie skimmera i loaderów, weryfikacja motywów/modułów pod reinfect, patch podatnego modułu, natychmiastowa rotacja hasła DB (credentials już były w rękach atakującego), reset haseł BO, audyt uploadów. Zamiast ślepego kasowania ścieżki shella — honeypot łapiący powroty. Biznesowo-prawnie: okno zamówień pod RODO/UODO, kontakt z operatorem płatności przy wycieku kart.
Lekcja: nietypowy checkout + dziwna walidacja to red flag bezpieczeństwa, nie tylko QA. RCE i Magecart to dwa cele — remediacja musi pokryć oba.
Case 3: injection w komentarzu do zamówienia (custom)
Trzeci przypadek jest prostszy i przez to ważny. W sklepie custom ktoś próbował przez komentarz do zamówienia wstrzykiwać JavaScript, PHP i SQL. Pierwsze payloady wyglądały na probing — sprawdzenie, czy injection w ogóle działa. Część skryptów w ogóle nic nie zrobiła; jedyny, który „przeszedł” zapis, pojawił się w adminie jako tekst — i na tym się skończyło. Nie było tu przypadku: treść komentarza przy renderze w BO szła przez escapowanie HTML (oraz sanityzację przy zapisie). Przeglądarka dostała bezpieczny string, nie wykonywalny kod, więc XSS w panelu nie wystartował.
Przyczyna / skutki / przeciwdziałanie
Przyczyna: pole treści użytkownika traktowane jak niewinne — a trafia do BO. Skutki: przy braku escapowania to klasyczny XSS w panelu (sesja admina, kradzież cookie, dalsza eskalacja). Przeciwdziałanie: escape przy wyświetlaniu, walidacja przy zapisie, CSP tam gdzie ma sens, przegląd wszystkich miejsc, gdzie treść zamówienia ląduje w HTML.
Lekcja: powierzchnia ataku to nie tylko /admin/login. To każde pole, które kiedyś zobaczy pracownik w panelu.
Co łączy te trzy historie
| Case 1 (WP) | Case 2 (Presta) | Case 3 (custom) | |
|---|---|---|---|
| Pierwszy sygnał | zepsuty panel / dziwne pliki | „bug” checkoutu | probing w komentarzu |
| Wejście | credentials → panel | RCE w module/cache | injection w polu BO |
| Cel | persistence / dostęp | skimmer kart + shell | test podatności / XSS |
| Remediacja | cleanup + harden + RODO paper | patch + rotacja secretów + honeypot | escape + walidacja |
Wspólne zasady, które stosuję przy e‑commerce:
- Traktuj dziwny UX jak potencjalny incydent — dopóki nie wykluczysz malware.
- Najpierw kopia forensyczna, potem sprzątanie — snapshot/image żywej instancji (i bazy) przed eradicate; inaczej gubisz dowody i ryzykujesz niespójność danych.
- Credentials są spalone szybciej, niż myślisz — po RCE lub wycieku configa rotuj DB i konta od razu, nie „po sprzątaniu JS”.
- Cache i uploady to kod — jeśli PHP da się tam wykonać, to wektor.
- Każde pole użytkownika w BO to XSS waiting to happen bez escapowania.
- Contain → eradicate → harden → document — bez ostatniego kroku nie masz historii pod IOD / UODO / ubezpieczyciela.
- Próba naruszenia systemu ≠ automatycznie naruszenie danych — ale ocena musi być spisana, nie „na czuja”.
Checklista, którą zostawiam po takich sprawach
- Snapshot / image przed jakimkolwiek cleanupem na produkcji
- 2FA (albo druga warstwa) dla wszystkich adminów — oraz twarde hasła / rotacja SSH·SFTP·FTP
- Regularne update’y core, motywów i modułów — szczególnie tych z cache/upload; wtyczki tylko z zaufanego źródła
- Skaner integralności plików + alerty
- Backup 3-2-1 i retencja logów (access + WAF/CDN)
- Escape/sanitization wszystkich treści użytkownika w panelu
- Rotacja secretów po każdym potwierdzonym RCE / wycieku configa
- Procedura: kto ogłasza incydent, kto spisuje timeline, kto rozmawia z IOD
- Po skimmerze kart: kontakt z operatorem płatności, nie tylko „wyczyść JS”
Podsumowanie
Bezpieczeństwo sklepu to nie jeden produkt WAF i nie jeden plugin. To nawyk: czytać nietypowe zachowanie frontu jako sygnał, zakładać że panel padnie przez hasło, a nie przez zero-day, i po sprzątaniu zostawić papier, nie tylko czysty dysk. Trzy powyższe case’y są zanonimizowane, ale powtarzalne — credentials, Magecart za „bugiem”, injection w niewinnym polu. Takie rzeczy widuję częściej niż spektakularne zero-daye. I właśnie dlatego warto mieć playbook zanim ktoś zadzwoni z „pilnym bugiem w koszyku”.