Wróć

Jak prawie dałem się zhakować "rekruterowi".

1 września 2025

Dostałem wiadomość na LinkedInie, która wyglądała dość standardowo, ale oferta była wyjątkowo kusząca.

Napisal niejaki Fabrizio Michele Bressan. Project Manager.

Screenshot profilu Fabrizio na LinkedIn Profil rekrutera. Wyglądał całkiem profesjonalnie, prawda? Zdjęcie na wygenerowane przez AI, ale ostatnio sporo osób robi sobie takie "profesjonalne" headshoty, więc początkowo nie wzbudziło to moich podejrzeń.

Brzmiało to jak złoty strzał. Firma? PokerStars. Projekt? Web3 games. Stawka? $80 - $100 za godzinę. Dla freelancera brzmi jak marzenie. Fabrizio był bardzo konkretny: CV, skill test, rozmowa z technicznym, NDA i jedziemy z koksem. Szybka piłka.

Pierwsza wiadomość od rekrutera Pierwszy kontakt. Brzmi zachęcająco, konkretnie i profesjonalnie.

Szczegóły oferty pracy Stawka $80-100/h i praca zdalna przy Web3. Brzmi prawie zbyt dobrze, żeby było prawdziwe... i było.

Przesłałem CV. Po chwili odpowiedź:

"CV jest świetne, łap zadanie testowe". Link do repozytorium na Bitbucket. Zadanie: naprawić/rozwinąć backend.

Wysłanie CV i otrzymanie linku do zadania Moment przekazania "zadania rekrutacyjnego". Zwróćcie uwagę na presję czasu i prośbę o "ping" przy starcie.

Pobieram projekt

W końcu udało mi się pobrać repozytorium. Początkowo były problemy z dostępem (link nie działał), ale Fabrizio szybko to ogarnął.

Widok repozytorium na Bitbucket Tak wyglądało repozytorium. Na pierwszy rzut oka - standardowy projekt.

Zwyczajny projekt Next.js... prawie.

Struktura plików wyglądała totalnie standardowo. server, src, package.json, jakiś README.md. Wyglądało to na zwykły sklep/grę w klimatach Web3. Co prawda bardzo niechlujnie napisaną, no ale jednak.

Struktura plików i README README wyglądało wiarygodnie, instrukcje uruchomienia, opis projektu.

Plik package.json Zależności w package.json też nie budziły podejrzeń na pierwszy rzut oka. React, Next.js, biblioteki krypto.

Zazwyczaj w tym momencie większość z nas robi jedną rzecz: npm install && npm start

NIE RÓBCIE TEGO. Nigdy.

Zanim odpaliłem cokolwiek, postanowiłem przejrzeć kod. Mam taki nawyk, że sprawdzam package.json i dziwne pliki w folderach. I wtedy mnie zmroziło.

Co znalazłem w kodzie? (Analiza techniczna)

Zamiast naprawiać bugi, znalazłem Backdoora.

W pliku server/middlewares/validator/index.js (brzmi niewinnie, prawda? Walidacja danych...) znalazłem taki kwiatek:

Złośliwy kod z eval() To jest ten moment. Funkcja, która pobiera kod z internetu i wykonuje go przez eval(). Backdoor w czystej postaci.

Co to robi?

  1. Łączy się z domeną chainlink-api-v3.com. To nie jest oficjalna domena Chainlinka. To tzw. typosquatting – domena, która udaje legitną.
  2. Wykorzystuje eval(). Kod pobiera treść z internetu (ukrytą w odpowiedzi błędu HTTP, bardzo sprytne) i natychmiast wykonuje ją na urządzeniu.
  3. Dzieje się to automatycznie przy starcie serwera (IIFE).

Gdybym wpisał npm start, haker miałby w tym momencie pełny dostęp do mojego komputera. Mógłby wyciągnąć klucze prywatne do portfeli krypto, hasła z przeglądarki, klucze SSH. Wszystko.

To nie był koniec. W pliku fileRemover.js znalazłem zakomentowany kod, który wyglądał na próbę steganografii – wyciągania złośliwego kodu ukrytego w pliku graficznym .png.

Podejrzany kod w fileRemover.js Zakomentowany fragment sugerujący próbę ukrycia złośliwego kodu w obrazku tła.

A we frontendzie (faucet/index.tsx) skrypt zbierał moje IP i lokalizację, wysyłając je na zewnętrzny serwer.

Kod zbierający dane użytkownika Frontend po cichu wysyłał moje IP i lokalizację do API atakującego.

Sprawdzam, co siedzi w środku

Dla pewności postanowiłem sprawdzić ten ich "API". Oczywiście wszystko robiłem już na maszynie wirtualnej, żeby nie ryzykować infekcji mojego głównego systemu.

Najpierw spróbowałem zwykłego zapytania curl. Serwer nie zwracał nic ciekawego.

Terminal - curl bez odpowiedzi Próba połączenia curlem bez odpowiednich nagłówków. Serwer milczy, udaje, że nie istnieje.

Ale kiedy ustawiłem User-Agent na taki, jakiego używa biblioteka axios (czyli udawałem, że jestem odpalonym skryptem Node.js) – serwer "wypluł" ładunek. Złośliwy skrypt JavaScript.

Terminal - curl z odpowiedzią malware Bingo. Po zmianie User-Agent serwer myśli, że jestem ofiarą i wysyła złośliwy skrypt.

Finał rozmowy

Wiedziałem już, że to wałek. Ale postanowiłem pociągnąć grę. Napisałem do Fabrizio po 30 minutach: "Skończyłem projekt, możemy się zdzwonić, żeby pokazać rozwiązanie?".

Jego odpowiedź? "Sure. I will contact technical manager". Zero zdziwienia, że zrobiłem "skomplikowane zadanie" w 30 minut. Chodziło tylko o to, żebym uruchomił kod.

Wnioski dla Was

To był scam celowany w programistów ("Job Offer Scam"). Jest coraz popularniejszy, zwłaszcza w branży krypto/web3.

  1. Nie ufaj rekruterom znikąd, zwłaszcza jeśli oferują gigantyczne stawki i od razu wysyłają pliki/repozytoria.
  2. Analizuj kod przed uruchomieniem. Zawsze. Szukaj eval, exec, child_process, dziwnych requestów sieciowych przy starcie serwera.
  3. Używaj maszyny wirtualnej. Jeśli naprawdę musisz zrobić zadanie rekrutacyjne z nieznanego źródła – postaw Sandboxa albo VM-kę bez dostępu do Twoich prywatnych plików.

Uważajcie na siebie. Fabrizio (czy jak mu tam naprawdę na imię) wciąż pewnie szuka "talentów". Nie dajcie się złowić.