Wystartowała Akademia NIS2/KSC2! Można jeszcze dołączyć do końca lipca!
Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!
Bezpłatne szkolenie: AI dla admina. Top 5 zadań, które zrobisz szybciej
Wystartowała Akademia NIS2/KSC2! Można jeszcze dołączyć do końca lipca!
Konferencja Mega Sekurak Hacking Party w Krakowie – 26-27 października!
Bezpłatne szkolenie: AI dla admina. Top 5 zadań, które zrobisz szybciej
Doświadczyłem prawdziwego incydentu bezpieczeństwa na moim prywatnym MacBooku (architektura Apple Silicon), używanym codziennie do pracy zawodowej. Dzielę się tą historią nie dla dramatyzmu, lecz dlatego, że atak był dobrze przygotowany, wieloetapowy i łatwo można było dać się nabrać – nawet doświadczonemu, technicznemu użytkownikowi.
Atak nie zaczął się od złośliwego oprogramowania (malware). Zaczął się od interakcji na LinkedIn. Przebieg wyglądał wiarygodnie i znajomo.
Kontakt zaczął się od ogłoszenia o pracę, które precyzyjnie odpowiadało mojemu profilowi. Po pierwszej odpowiedzi przyszły pytania wstępne, a po nich kolejne wiadomości uzupełniające – wszystko w tempie typowym dla profesjonalnego procesu rekrutacyjnego, bez ponaglania i bez luk w komunikacji. Ostatnim krokiem było zaproszenie na rozmowę kwalifikacyjną.
Na tym etapie nic nie wyglądało na pośpieszne, podejrzane ani nietypowe technicznie. To ważne: atakujący zainwestował czas w zbudowanie wiarygodności.
Ostatnim krokiem przed incydentem było zaproszenie na rozmowę zawierające pozornie wiarygodny, „bezpieczny” link do spotkania w Webex, hostowany pod strukturą domeny opatrzoną marką Cisco, np.:
hxxps[:]//cisco[.]us-webexmeet[.]com/pedestal/j.php?MTID=mcb19f0c7[…]a0ceda29013

Na pierwszy rzut oka link prowadzi do portalu z certyfikatem TLS (HTTPS), sam URL nawiązuje do brandingu Cisco/Webex i ma całkiem realistyczną strukturę subdomeny. Na pierwszy rzut oka można pominąć typowe red flagi, bo atak bardzo przypomina poprawny przepływ biznesowych spotkań.
To dokładnie ten moment, w którym wykorzystano zaufanie. Link ostatecznie prowadził do pobrania pliku DMG dla systemu macOS, przedstawionego jako komponent Webex wymagany do udziału w spotkaniu.
Pobrany plik DMG wyglądał profesjonalnie i wiarygodnie. Jednak zamiast standardowego instalatora, instruował użytkownika, aby:
„Przeciągnij do terminala (Drag into Terminal)”

Ten pojedynczy krok powoduje, że mechanizm Gatekeeper nie jest angażowany w wykonanie skryptu, ponieważ wykonanie odbywa się przez powłokę a nie LaunchServices. To dzięki temu nie zobaczymy okna Gatekeepera, mówiącego o zablokowaniu wykonania, mimo obecności atrybutu com.apple.quarantine na pobranym z internetu pliku.
Z perspektywy bezpieczeństwa to ogromny sygnał alarmowy – ale przedstawiony w kontekście „bezpiecznego, firmowego procesu rozmowy kwalifikacyjnej” może okazać się przekonujący.
Sam instalator nie wykonywał prawie żadnych widocznych działań. Jego jedynym faktycznym zadaniem było zapewnienie trwałości (persistence) na poziomie użytkownika poprzez utworzenie LaunchAgent:

Cała rzeczywista funkcjonalność była dostarczana później przez zdalny payload, pobierany dynamicznie w czasie wykonywania.
Persystencja została zrealizowana najprostszą dostępną metodą: plistem w ~/Library/LaunchAgents, a więc w kontekście użytkownika, bez potrzeby uzyskiwania uprawnień administracyjnych. Za samo uruchamianie odpowiadał już launchd, czyli natywny mechanizm systemu. Właściwy payload nie był jednak osadzony w instalatorze – jego adres pobierany był z rekordu DNS TXT, a kod trafiał bezpośrednio do osascript z flagą -l JavaScript, czyli wykonywany był jako JXA (JavaScript for Automation). Drugi stopień nie był zatem utrwalany na dysku i istniał wyłącznie w pamięci procesu.
Taka konstrukcja skutecznie omija detekcję opartą na sygnaturach plików, bo poza plistem i samym DMG nie ma czego skanować. Ogranicza też liczbę artefaktów przydatnych w analizie powłamaniowej – co nie znaczy, że znikają one całkowicie: pozostaje plist, atrybut com.apple.quarantine, historia powłoki, wpisy w Unified Log oraz zapytania DNS, o ile są logowane. Rekonstrukcja pełnego przebiegu zdarzeń jest jednak wyraźnie trudniejsza niż w przypadku klasycznego, plikowego malware’u, zwłaszcza jeśli treść rekordu TXT zdążyła się w międzyczasie zmienić.
To nie był atak na jądro systemu ani próba przejęcia konta root. Payload działał wyłącznie w kontekście mojego użytkownika i to w zupełności mu wystarczało. W zasięgu miał klucze prywatne SSH, tokeny Git oraz poświadczenia do usług chmurowych, czyli cały zestaw danych deweloperskich, aktywne sesje przeglądarki i lokalne dane projektów. Innymi słowy: wszystko, czego realnie używam do pracy.
Warto tu obalić jeden mit, w który sam przez chwilę wierzyłem. Menedżery haseł zintegrowane z przeglądarką nie stanowią istotnej przeszkody. Baza Chrome to plik SQLite plus klucz szyfrujący przechowywany w Keychainie, a zrzucenie tego zestawu jest standardową funkcją większości macOS-owych infostealerów. Po uzyskaniu niesandboksowanego wykonania kodu jako zalogowany użytkownik hasła zapisane lokalnie przez Chrome należy uznać za potencjalnie dostępne dla atakującego. Szyfrowanie z kluczem przechowywanym w Keychainie chroni przede wszystkim przed kopiowaniem danych offline i dostępem z innego konta, lecz zwykle nie stanowi silnej granicy bezpieczeństwa wobec malware działającego w tej samej aktywnej sesji użytkownika.
Znacznie ważniejsze jest jednak co innego: w perspektywie najbliższych godzin po infekcji tokeny sesyjne są groźniejsze niż same hasła. Hasło można zmienić i sprawa jest zamknięta. Aktywna sesja albo token OAuth działa dalej, niezależnie od tego, ile razy zmienisz hasło, dopóki nie unieważnisz go jawnie.
Reakcja przebiegła zgodnie ze standardową praktyką incident response. Najpierw natychmiastowa izolacja maszyny od sieci. Potem ręczne zakończenie procesów i usunięcie mechanizmu persystencji przez launchctl bootout. Następnie unieważnienie aktywnych sesji, w moim przypadku Google i Apple ID. Na końcu pełne wyczyszczenie systemu funkcją “Erase All Content and Settings” i odbudowa od zera.
Na Apple Silicon ten ostatni krok jest szybki i przewidywalny, bo klucze woluminu danych są kasowane sprzętowo. W praktyce dostajesz maszynę w stanie fabrycznym w kilkanaście minut. Warto natomiast rozumieć, dlaczego zwykła reinstalacja systemu to za mało: reinstalacja nad istniejącą instalacją nie rusza woluminu danych, a persystencja siedziała właśnie tam, w katalogu domowym użytkownika. Czyszczenie musi obejmować dane, nie tylko system.
Czego bym nie powtórzył: wyczyściłem maszynę, zanim zabezpieczyłem materiał do analizy. Zebranie plisty, zawartości /tmp, historii powłoki i fragmentu Unified Log to kwestia kilkunastu minut, a bez tego zostaje mi wyłącznie opis z pamięci. Nie popełniaj tego błędu.
Osobna sprawa to rotacja poświadczeń, którą łatwo potraktować po macoszemu, bo wipe daje złudne poczucie zamknięcia tematu. Wyczyszczenie laptopa nie unieważnia niczego, co zdążyło z niego wyjść. Klucze SSH trzeba wymienić i usunąć stare wpisy z authorized_keys na zdalnych hostach, tokeny Git i klucze API wygenerować od nowa, przejrzeć przyznane uprawnienia OAuth i logi dostępu do repozytoriów. To jest właściwa robota, a nie sam wipe.
Kilka rzeczy, które chciałbym, żeby ktoś powiedział mi wcześniej.
Współczesny atak nie zaczyna się od exploita, tylko od procesu i zaufania. Tu nie było ani jednej podatności technicznej, była za to poprawnie odegrana rekrutacja. Socjotechnika oparta na ofertach pracy jest skuteczna właśnie dlatego, że realistyczny przebieg rozmowy kwalifikacyjnej systematycznie obniża czujność, a jednocześnie usprawiedliwia dziwne prośby “wymogami procesu”.
Jeśli jakikolwiek instalator prosi o przeciągnięcie czegokolwiek do terminala, przerywasz. Bez wyjątków i bez zastanawiania się, czy tym razem to może mieć sens. To jedyna reguła z tej listy, która wymaga zero wiedzy technicznej i sama w sobie zatrzymałaby cały ten atak.
Nie potrzeba roota, żeby zrobić komuś realną krzywdę. Malware w przestrzeni użytkownika ma dostęp do dokładnie tych danych, na których ci zależy. Payloady pobierane dynamicznie i wykonywane wyłącznie w pamięci to dziś norma, nie egzotyka, więc detekcja oparta na skanowaniu plików ma coraz mniej do roboty.
Incydent skończył się bez potwierdzonych szkód, ale wyłącznie dlatego, że został wcześnie zauważony i szybko obsłużony. Gdybym zorientował się dzień później, ten tekst wyglądałby zupełnie inaczej.
Opisuję to publicznie z prostego powodu: chcę, żeby więcej osób rozpoznawało ten wzorzec, zanim kliknie, i żeby traktowało “profesjonalny kontekst” jako coś, co można podrobić, a nie jako dowód. Jeśli pracujesz na macOS i na co dzień masz pod ręką klucze SSH, tokeny i dostępy do chmury, warto mieć ten przypadek z tyłu głowy.
~Wojciech Wilk (WILQ)