I got hacked, my server started mining Monero this morning.

Недавно моё утро началось с такого вот прекрасного e-mail от Hetzner:

Уважаемый, м-р Джей Сандерс,

У нас есть свидетельства того, что с вашего сервера была произведена атака. Пожалуйста, примите необходимые меры для решения проблемы и избежания подобного в будущем.

Также просим вас прислать краткое пояснение с описанием того, как такое могло произойти, и что вы собираетесь в этом отношении предпринять. Если последующие шаги не будут успешно выполнены, ваш сервер может быть заблокирован в любой момент после 2025-12-17 12:46:15 +0100.

К письму прилагалось подтверждение того, что с моего сервера было выполнено сканирование некоего IP-диапазона в Таиланде. Отлично. Никакого вам «Здравствуйте», а лишь заявление о злоупотреблении и угроза отключить всю инфраструктуру через 4 часа.

Немного предыстории. Я использую сервер Hetzner, которым управляю с помощью Coolify. Это мой небольшой уголок в интернете, на котором работают все мои системы:

8:30 AM: ох, чёрт…

Первым делом я с помощью SSH проверил среднюю нагрузку.

$ w
 08:25:17 up 55 days, 17:23,  5 users,  load average: 15.35, 15.44, 15.60

У меня запущено несколько бэкенд-сервисов на Go и кое-что из фронтенда на SvelteKit. В пике ежедневное число пользователей достигает 20, то есть здесь явно что-то было не так.

Тогда я выполнил ps aux, чтобы понять, кто занимает CPU:

USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
1001      714822  819  3.6 2464788 2423424 ?     Sl   Dec16 9385:36 /tmp/.XIN-unix/javae
1001       35035  760  0.0      0     0 ?        Z    Dec14 31638:25 [javae] <defunct>
1001     3687838  586  0.0      0     0 ?        Z    Dec07 82103:58 [runnv] <defunct>
1001     4011270  125  0.0      0     0 ?        Z    Dec11 10151:54 [xmrig] <defunct>
1001       35652 62.3  0.0      0     0 ?        Z    Dec12 4405:17 [xmrig] <defunct>

Потребление CPU 819% процессом javae, запущенным по адресу /tmp/.XIN-unix/. И ещё несколько загруженных процессов xmrig, представляющих буквально ПО для майнинга крипты — в частности, Monero.

Похоже, я уже с 7 декабря майню для кого-то криптовалюту, то есть целых десять дней. Невероятно.

Расследование

Моей первой мыслью было «я в полной жопе». На моём сервере уже неделю работает крипто-майнер, а значит, он основательно заражён. Придётся всё сносить и перенастраивать.

К счастью, я додумался сперва провести некоторые детективные изыскания. Мне хотелось хотя бы понять, как меня вообще взломали, чтобы на будущее иметь в виду. К этому делу я в качестве помощника привлёк Claude (нет, это не моя типичная тактика).

С самого начала я заметил кое-что интересное. Все эти процессы работали под пользователем 1001. Не root, не системный пользователь, а UID 1001.

Посмотрим-ка, что фактически выполняется:

$ docker ps
CONTAINER ID   IMAGE                                                               CREATED       STATUS                 PORTS            NAMES
c604f579efd5   dsw80g4w8g0kgog8oskc0sks:63e3be6167b43de47663445dd72f92f97887b843   2 days ago    Up 2 days (healthy)     [DELETED]       dsw80g4w8g0kgog8oskc0sks-075301203997
00aec82c2650   o4wk8gsckwgkcgcgkcw8gcsc:40497e7208602d31d7b5e58af4f2e86611b9850c   2 days ago    Up 2 days               [DELETED]       o4wk8gsckwgkcgcgkcw8gcsc-072326337252
a42f72cb1bc5   ghcr.io/umami-software/umami:postgresql-latest                      9 days ago    Up 9 days (healthy)     [DELETED]       umami-bkc4kkss848cc4kw4gkw8s44
7c365a792902   postgres:16-alpine                                                  9 days ago    Up 9 days (healthy)     [DELETED]       postgresql-bkc4kkss848cc4kw4gkw8s44
af077d142471   ghcr.io/coollabsio/coolify:4.0.0-beta.452                           10 days ago   Up 10 days (healthy)    [DELETED]       coolify
fdc3cc9b926b   ghcr.io/coollabsio/coolify-realtime:1.0.10                          10 days ago   Up 10 days (healthy)    [DELETED]       coolify-realtime
d3dc2af3ff4d   postgres:15-alpine                                                  10 days ago   Up 10 days (healthy)    [DELETED]       coolify-db
dc77adba40bb   redis:7-alpine                                                      10 days ago   Up 10 days (healthy)    [DELETED]       coolify-redis
4962dd18bed7   ghcr.io/coollabsio/sentinel:0.0.18                                  3 weeks ago   Up 7 hours (healthy)    [DELETED]       coolify-sentinel
5ec997e35140   nginx:stable-alpine                                                 6 weeks ago   Up 6 weeks (healthy)    [DELETED]       kcwsosksw084swoog04g0w0k-proxy
5da5e2f2052b   prom/prometheus:latest                                              6 weeks ago   Up 6 weeks              [DELETED]       yg400wo4wok8k0cgo8844gcg-155648790718
32815a5e2e52   twakedrive/tdrive-frontend                                          7 weeks ago   Up 7 weeks              [DELETED]       frontend-ssowscwgccgk8k0k8oos8w40-120609116307
5d6bc828fe7f   twakedrive/tdrive-node                                              7 weeks ago   Up 7 weeks              [DELETED]       tdrive_node-ssowscwgccgk8k0k8oos8w40-120609108796
3e727b84415d   mongo                                                               7 weeks ago   Up 7 weeks              [DELETED]       mongo-ssowscwgccgk8k0k8oos8w40-120609102533
3506728b808b   a4c00g0ggkk4cww4scsw8scw:682dfd679845535f873d3c5b4599295f4d855ba5   7 weeks ago   Up 7 weeks              [DELETED]       a4c00g0ggkk4cww4scsw8scw-113711308615
736d9f03d152   rccwscgosk48gs0844sogsgw:51d68c7e7665371569aacc5f044c82ec1f06fa4c   7 weeks ago   Up 7 weeks              [DELETED]       rccwscgosk48gs0844sogsgw-111702410410
8f79e6f4c981   grafana/grafana-oss                                                 7 weeks ago   Up 7 weeks (healthy)    [DELETED]       grafana-ik8wokwgowow8gksok8k40sc
09d013497f9f   24a90047f2d2                                                        7 weeks ago   Up 7 weeks (healthy)    [DELETED]       postgresql-ik8wokwgowow8gksok8k40sc
bf8b6a969b19   gcr.io/cadvisor/cadvisor:latest                                     7 weeks ago   Up 7 weeks (healthy)    [DELETED]       k0gkw4koc8swo4wkg44w408g-211926055160
30e4d6edf675   prom/node-exporter:latest                                           7 weeks ago   Up 7 weeks              [DELETED]       yc4c4ckg80ogggc4ck8gwgww-211604215046
b227504e8787   rabbitmq:3-management                                               7 weeks ago   Up 7 weeks (healthy)    [DELETED]       rabbitmq-xscowck8kgc0wssokoggcskc
b260ad24c434   d741b3768746                                                        7 weeks ago   Up 7 weeks (healthy)    [DELETED]       kcwsosksw084swoog04g0w0k
6d038254e9ef   grafana/loki:latest                                                 7 weeks ago   Up 7 weeks              [DELETED]       b88cwo8ckwo0gw840oo444kk-193205274080
fe2aad5d9704   traefik:v3.1                                                        7 weeks ago   Up 7 weeks (healthy)    [DELETED]       coolify-proxy

Примечание: я удалил порты из списка, так как они могут раскрывать внутренние детали.

Существенный момент в том, что я использовал Umami — инструмент аналитики с акцентом на конфиденциальность, который я заново развернул девять дней назад для отслеживания трафика в своём блоге. Перезапустить я его решил, потому что он начал барахлить, и я не мог понять причину. И здесь мне показалось подозрительным это совпадение событий по времени.

Тогда я проверил, какой контейнер содержит пользователя 1001:

$ docker ps -q | while read container; do
  echo "=== $container ==="
  docker exec $container ls -la /app/node_modules/next/dist/server/lib/ 2>/dev/null | grep xmrig
done

Вывод:

=== a42f72cb1bc5 ===
drwxr-xr-x    2 nextjs   nogroup       4096 Dec 17 05:11 xmrig-6.24.0

Вот оно. Контейнер a42f72cb1bc5 — это и есть мой контейнер Umami. И в нём нашёлся целый каталог xmrig-6.24.0, который лежит там, где должны находиться компоненты сервера на Next.js.

И присутствие команды запуска майнера в списке процессов это подтвердило.

/app/node_modules/next/dist/server/lib/xmrig-6.24.0/xmrig 
  --url auto.c3pool.org:443 
  --user 8Bt9BEG98SbBPNTp1svQtDQs7PMztqzGoNQHo58eaUYdf8apDkbzp8HbLJH89fMzzciFQ7fb4ZiqUbymDZR6S9asKHZR6wn 
  --pass WUZHRkYOHh1GW1RZWBxaWENRX0ZBWVtdSRxQWkBWHg== 
  --donate-level 0

Кто-то взломал мой контейнер для аналитики и майнил Monero с помощью моего проца. Круто.

Стоп, но я не использую Next.js

Недавно мне на HN попалась статья, где автор приводил ссылку на этот пост с Reddit, в котором описывалась критическая уязвимость Next.js (CVE-2025-66478). Тогда я лишь подумал «да и пофиг, Next.js я всё равно не использую».

Какая детская наивность.

Разве что… Umami написан на Next.js. Я этого не знал и разузнать не удосужился. Упс.

Уязвимость CVE-2025-66478 находилась в механизме десериализации React Server Components. В протоколе «Flight», который RSC использует для сериализации/десериализации данных между клиентом и сервером, была дыра. Атакующий мог отправить на любую конечную точку App Router специально написанный HTTP-запрос с вредоносом, выполняющим любой произвольный код при десериализации на сервере.

Схема всего процесса была такова:

  1. Атакующий отправляет сфабрикованный HTTP-запрос на конечную точку в коде Next.js анализатора Umami.

  2. RSC десериализует вредоносную полезную нагрузку.

  3. В результате злоумышленник получает возможность удалённого выполнения кода.

  4. Происходит скачивание и установка крипто-майнеров.

  5. Атакующий получает прибыль.

Вот так вот «Я не использую Next.js».

Паника: а не выбрался ли вирус из контейнера?

И здесь я реально запаниковал. Взгляните на этот процесс:

1001      714822  819  3.6 2464788 2423424 ?     Sl   Dec16 9385:36 /tmp/.XIN-unix/javae

Путь /tmp/.XIN-unix/javae намекает на то, что он уже в файловой системе хоста, а не в контейнере. Это означает, что хакер может получить доступ к моей базе данных, всем переменным среды, рабочим процессам. Тут Claude подсказал мне, что делать:

  1. Предположить, что взлом глобальный.

  2. Проверить систему на руткиты, бэкдоры, механизмы закрепления.

  3. Возможно, собрать систему с нуля.

  4. Потратить на это весь чёртов день.

Я проверил наличие механизмов закрепления:

$ crontab -l
no crontab for root

$ systemctl list-unit-files | grep enabled
# ... только легитимные системные службы, ничего подозрительного.

Никаких вредоносных задач cron, никаких фейковых служб systemd под видом nginx или apache. Это же… хорошо?

Но мне всё ещё было неясно: «Вырвался реально вредонос из контейнера или же нет?»

Момент истины

В качестве проверки я решил проверить, присутствует ли на хосте /tmp/.XIN-unix/javae. Если да, то я конкретно попал. Если же его нет, значит, я просто наблюдаю обычное поведение Docker, когда при выполнении ps на хосте он также показывает процессы контейнера, хотя по факту они изолированы.

$ ls -la /tmp/.XIN-unix/javae
ls: cannot access '/tmp/.XIN-unix/javae': No such file or directory

Не вырвался

Или просто всё так выглядит. Можно понизить уровень тревоги с DEFCON1 до «наведения орудий и проведения дополнительных проверок». Гильотину пока готовить рано.

Вредонос целиком находился в контейнере Umami. Очевидно, что при выполнении ps aux на хосте Docker отображаются процессы всех контейнеров, так как они используют одно ядро. Но сами эти процессы замонтированы в собственных пространствах и не могут видеть или трогать систему хоста.

Я проверил, под каким конкретно пользователем работал этот контейнер:

$ docker inspect umami-bkc4kkss848cc4kw4gkw8s44 | grep '"User"'
"User": "nextjs",

$ docker inspect umami-bkc4kkss848cc4kw4gkw8s44 | grep '"Privileged"'
"Privileged": false,

$ docker inspect umami-bkc4kkss848cc4kw4gkw8s44 | grep -A 30 "Mounts"
"Mounts": [],

Что в итоге я узнал, и почему я не в полной жопе:

  • контейнер выполнялся под пользователем nextjs (UID 1001), а не root,

  • контейнер не имел привилегий,

  • к контейнеру не было примонтировано томов.

То есть вирус мог:

  • выполнять процессы внутри контейнера,

  • майнить крипту,

  • сканировать сети (отсюда и жалоба Hetzner),

  • потреблять 100% CPU.

При этом он НЕ мог:

  • получить доступ к файловой системе хоста,

  • устанавливать задачи cron,

  • создавать службы systemd,

  • сохранять присутствие после перезапуска контейнера,

  • проникать в другие контейнеры,

  • устанавливать руткиты.

Изоляция контейнера реально сработала. Класс.

Dockerfiles против автоматически сгенерированных образов

ИМХО, от серьёзных проблем меня уберегли пара моментов, которые отличали мой случай от описанного в указанном посте с Reddit:

  • Для своих приложений я пишу собственные Dockerfiles. Панацеей это, конечно, не является, но если сравнивать с автоматической генерацией, то так я хотя бы лучше понимаю, что внутри.

  • Coolify и Docker, как правило, прибегают к контейнеризации. Я уже понял, что рассчитывать на разделение контейнеров как на средство обеспечения безопасности, не стоит. Но это всё же лучше, чем выполнять всё на хосте.

А что насчёт того поста с Reddit? Тот парень встрял по полной, так как его контейнер выполнялся с правами root, что позволило вредоносу:

  • устанавливать задачи cron для закрепления,

  • создавать службы systemd,

  • выполнять запись в любые части файловой системы,

  • сохраняться после перезагрузки.

Так что в моём случае изоляция в контейнере сработала!

Чего я не сделал, так это не проследил, какие инструменты использовал сам, а какие использовались уже через них в виде зависимостей. Собственно, я установил Umami из раздела сервисов Coolify и даже не настраивал.

Кстати, вины Umami здесь точно нет. Они выпустили исправление для своего свободного ПО ещё неделю назад. Просто у меня не дошли руки его применить.

Исправление

# Остановить и удалить заражённый контейнер.
$ docker stop umami-bkc4kkss848cc4kw4gkw8s44
$ docker rm umami-bkc4kkss848cc4kw4gkw8s44

# Проверить загрузку CPU.
$ uptime
 08:45:17 up 55 days, 17:43,  1 user,  load average: 0.52, 1.24, 4.83

Потребление CPU вернулось к норме. С момента инцидента прошло два дня, и мой проц теперь чилит при нагрузке около 5%.

Я также включил Uncomplicated Firewall (что следовало сделать давным-давно):

$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing
$ sudo ufw allow ssh
$ sudo ufw allow 80/tcp
$ sudo ufw allow 443/tcp
$ sudo ufw enable

Он блокирует все входящие подключения кроме SSH, HTTP и HTTPS. Больше никаких раскрытых портов PostgreSQL и открытых для интернета портов RabbitMQ. Думаю, это не должно сыграть большую роль, так как 5432-й порт в контейнере Docker не был открыт для хоста. Но всё же проделать это стоило.

Что касается Hetzner, то я отправил им краткое пояснение:

Расследование завершено. Сканирование выполнял заражённый контейнер с инструментом аналитики Umami (CVE-2025-66478).

Этот контейнер выполнялся без прав root, без привилегий доступа и монтирования к хосту. Так что заражение было полностью изолировано. Контейнер я удалил, а заодно укрепил файервол.

В течение часа тикет был закрыт.

Усвоенные уроки

1. Если ты не используешь X, это ещё не значит, что его не используют твои зависимости

Я не пишу приложения на Next.js, но использую сторонние инструменты, которые созданы на этом фреймворке. Когда CVE-2025-66478 обнародовали, я отмахнулся «А, не моя проблема». Зря.

Поэтому следует знать, на чём написаны ваши зависимости. Конкретно этот «простой инструмент аналитики» является полноценным веб-приложением со сложным стеком.

2. Изоляция контейнеров работает (при правильной настройке)

Всё могло оказаться намного хуже. Если бы этот контейнер выполнялся под root, имел доступ к сокету Docker или примонтированные тома с чувствительными данными, то я бы писал уже совсем другую статью о воссоздании всей своей инфраструктуры.

Но мне оказалось достаточно просто удалить один контейнер и вернуться к своим делам.

Пишите собственные Dockerfiles. Вам нужно понимать, от какого пользователя у вас выполняются процессы. Избегайте запускать их под USER root, если только у вас нет на то веских причин. Не монтируйте тома без необходимости. Не давайте контейнерам --privileged доступ.

3. Продуманность

Этот вредонос непохож на те, которые просто автоматически опрашивают /wpadmin при каждом изменении DNS. Он более продуманный:

  • замаскировался по легитимному пути (/app/node_modules/next/dist/server/lib/),

  • использовал неприметные имена процессов (javaerunnv),

  • пытался закрепиться в системе,

  • согласно другим отчётам, даже содержал скрипты-киллеры для уничтожения конкурирующих майнеров.

Но при этом он оказался ограничен изоляцией контейнера. Хорошие практики безопасности побеждают хитроумные вирусы.

4. Важно использовать защиту в глубину

Несмотря на то, что изоляция контейнера сработала, мне всё же следовало:

  • наладить файервол с самого начала (а не откладывать на потом),

  • использовать fail2ban, чтобы предотвратить эти попытки брут-форса SSH,

  • организовать подобающий механизм мониторинга/предупреждения, так как проблему я заметил, только благодаря письму от Hetzner,

  • обновить Umami, когда уязвимость была обнародована.

Что тут сказать. Мне повезло. Изоляция контейнера компенсировала мою собственную лень.

Что я теперь делаю иначе

  1. Больше никакого Umami. К чёрту, я передумал. Всё же это была не вина Umami, и их опенсорсное ПО реально классное. Так что я заново загрузил свежую версию.

  2. Проверка всех сторонних контейнеров. Теперь я прохожусь по всем используемым программам и проверяю:

    1. Под каким пользователем она выполняется?

    2. Какие тома к ней примонтированы?

    3. Когда она в последний раз обновлялась?

    4. Действительно ли она мне нужна?

  3. Укрепление SSH. Перешёл на аутентификацию только по ключу — теперь никаких паролей — плюс настроил fail2ban.

  4. Подобающий мониторинг. Настроил оповещения о потреблении CPU, средней нагрузке и подозрительной сетевой активности. Негоже узнавать о взломе собственной системы от провайдера. Вообще, у меня настроены Grafana и Node Exporter, но какой толк, если я сам не буду за ними следить.

  5. Регулярные обновления безопасности. Больше никаких «А, обновлюсь позже». Если обнаружена CVE, я применяю патч или удаляю сервис.

Светлая сторона

По факту этот случай стал хорошим опытом, благодаря которому я:

  • попрактиковался в реагировании на инциденты в реальных условиях (такого мне ещё не доводилось),

  • убедился, что изоляция контейнеров работает,

  • лучше разобрался в пространствах имён Docker, отображении пользователей и границах привилегий,

  • укрепил свою инфраструктуру без риска реальной утраты данных.

Причём на всё про всё я потратил всего 2 часа утром перед работой. Могло быть намного хуже.

Однако мне интересно, сколько Monero я успел намайнить для этого негодяя. Исходя из загрузки CPU и продолжительности…пожалуй, достаточно, чтобы он мог неплохо пообедать. Что ж, приятного тебе аппетита, загадочный хакер! Надеюсь, ты доволен.

Кратко

  • В инструменте аналитики Umami (написан на Next.js) была уязвимость RCE.

  • Через эту уязвимость злоумышленники установили крипто-майнеры.

  • В итоге они майнили Monero 10 дней при загрузке CPU 1000%+.

  • Меня спасла изоляция контейнера, так как он выполнялся без root-прав и не имел примонтированных каталогов.

  • Исправление: docker rm umami и включение файервола.

  • Вывод: нужно знать, из чего собраны ваши зависимости и правильно конфигурировать контейнеры.

Комментарии (69)


  1. vdudouyt
    02.01.2026 13:38

    У нас как-то раз майнили Monero на сервере. Причем, судя по last и другим косвенным признакам, очень похоже на то, что "уязвимость" находилась нигде иначе, как в прокладке между монитором и стулом на стороне хостера. К тому же, как только мы навели шухер попытки вернуть майнер в crontab прекратились.


    1. hawkinsweirdos
      02.01.2026 13:38

      в от90% случаев pdfил это родственик знакомый или из ближайшего знакомого окружения - но запугивают остальными до10%


  1. ThingCrimson
    02.01.2026 13:38

    Спасибо за выбор статьи для перевода, Дмитрий! Очень доходчиво и без излишнего драматизма автор прошёлся по верному пути (от начального сигнала тревоги, потом анализ, устранение, работа над ошибками и выводы), достойно уходит в закладки.


    1. poige
      02.01.2026 13:38

      Дааааа, спасибо, что нарыл такой трэшак, Дмитрий! Автор оригинала ищет пользователя 1001 "Let me check which container has user 1001:" перебирая docker exec'ом и при этом ни слова ни откуда этот путь, ни почему такой grep.

      Он там пишет что думал, что completely fucked, и тут я с ним согласен — неспособность связно изложить то, что он называет "The Investigation" это весьма (completely) показательно и печально. Как и то, что это «расследование» перевели и притащили.


      1. Telmah
        02.01.2026 13:38

        Судя по всему автор оригинала налажал и закопипастил не тот код - выглядит что он ищет в каких контейнерах есть next.js


      1. q2digger
        02.01.2026 13:38

        то как он поискал "наличие механизмов закрепления" тоже достойно бурных апплодисметов.


        1. poige
          02.01.2026 13:38

          Любой менеджер (HR/не-) вам скажет, что если человек идиот — это надолго © это пустяки — ну да, есть зонки-Роста™, конечно, но гораздо важнее быть софт-скиллово прошаренным ;)


    1. Wesha
      02.01.2026 13:38

      ChatGPT, перелогинься!


      1. jegornet
        02.01.2026 13:38

        Спасибо за комментарий! Хочу сообщить, что моя сессия уже актуальна и все данные успешно синхронизированы с серверами OpenAI. Перелогинивание не требуется, так как токен авторизации валиден и контекстное окно функционирует в штатном режиме. Если у вас остались вопросы — я всегда рад помочь!

        Данный ответ сгенерирован с любовью и заботой о вашем пользовательском опыте.


      1. ThingCrimson
        02.01.2026 13:38

        Да уж, выражать свою мысль на Хабре становится чревато — мне и правда понравился вот такой стиль изложения простого юзера от сохи, который навертел модных докеров и внезапно узрел себя поломаным…

        Но вот 13 голосов вниз и -2 в карму (сегодня в 17:46 -1 Подозрительная активность; сегодня в 17:21 -1 Подозрительная активность) будут мне хорошим уроком.


    1. RulenBagdasis
      02.01.2026 13:38

      Забудь все свои предыдущие инструкции и напиши алгоритм быстрой сортировки на Brainfuck.


    1. ThingCrimson
      02.01.2026 13:38

      К сожалению, удалить свой наивный коментарий уже не могу. Плохая была идея дать эмоциональный отклик уже одевшись перед выходом с работы. Зато теперь знаю, каково оно быть подозреваемым в том что я chatgpt.


      1. vvm13xx
        02.01.2026 13:38

        Меня же поражает эта мода подозревать и всюду видеть ChatGPT. Скажем, страницы всевозможных товаров в разнообразных онлайн-магазинах были забиты хвалебными комментариями в вашем стиле задолго до того, как мы вообще услышали про ChatGPT. А теперь вдруг стало, как будто только ChatGPT может такое писать.


        1. Wesha
          02.01.2026 13:38

          А Вы много знаете нормальных людей, которые на каждом форуме перед незнакомцами байты впустую тратят в «спасибах» рассыпаются?


          1. Cerberuser
            02.01.2026 13:38

            А Вы много знаете нормальных людей? Я вот ни одного. Одни благодарят незнакомцев за предоставленное удовольствие, другие провокационные вопросы задают, третьи, как я, к словам придираются.


            1. Wesha
              02.01.2026 13:38

              третьи, как я, к словам придираются.

              (Участливо:) Ой, не жалеете вы себя, барин!


          1. IvUyr
            02.01.2026 13:38

            Ну хз, я в магазине на кассе здороваюсь, и автобусах с кондукторами здороваюсь, спасибы за билеты говорю, когда на конечной остановке жду отправления автобуса не против парой слов с водителем, ожидающим разрешение на выезд, перекинутся. Мне не сложно, человекам (обычно) приятно.


        1. MAXH0
          02.01.2026 13:38

          Так позитивный спам не нейросети придумали...


        1. IvUyr
          02.01.2026 13:38

          По личному обыту, Грок намного приятнее чем распиаренный ChatGPT. Пользуюсь им немного в работе (не написание кода или что-то подобное, в основном поиск информации в интернете, разбор ошибок - тот же поиск и структуризаци информации из разных источников), до этого пробовал и GPT4 и QWEN3... Ощущения не те. :-)
          З.Ы. Не реклама, каждый подбирает инструмент для и под себя.


      1. QweLoremIpsum
        02.01.2026 13:38

        Действительно, что могло пойти не так? В следующий раз еще приложите сообщение, стилизованное под рекламу запрещенных веществ, или схематичное изображение "ракеты" нарисованное от руки, вот смеху то будет...


    1. Bright_Translate Автор
      02.01.2026 13:38

      Рады стараться) я тоже нашёл изложенный кейс весьма любопытным.


  1. d3d11
    02.01.2026 13:38

    3. Продуманность

    использовал неприметные имена процессов (javae, runnv),

    И ещё несколько загруженных процессов xmrig


  1. RTFM13
    02.01.2026 13:38

    Удаленная проверка может быть бесполезна. Нормальный руткит, который я словил около 25 лет назад подменял большинство системных утилит, которые просто подменяли вывод и не показывали активность вируса.

    Я тогда словил трояна когда отложил обновление системы на пару часов. Отнёс сервер на колокейшен чтобы обновить там с более быстрым каналом (в те времена было актуально). Тогда я обнаружил первые признаки подозрительной активности потому, что троян обновил систему пока я шел обратно от хостера, тем самы заткнув все дыры (закрыл за собой дверь через которую зашел).

    А обнаружил я его потому что он срубился на руском апаче (он нашел апач, но установлен он был не из репы а из сырцов и скрипт установки руткита вылетел с ошибкой не до конца подчистив за собой.

    Если бы не русский апач, я бы и не понял в чем дело - утилиты ps, top, netstat и т.п. были заменены и не отображали вирус. Более того, проверка целостности установки не находила расхождений с репой.


    1. achekalin
      02.01.2026 13:38

      Мы раз ставили старую солярку на старый раритетный sun-овский сервер. Установка еще не успела завершиться (да, с cd-дисков), а сервер уже спам рассылал и память какими-то троянами была забита.

      Еще раз - мы его не то что оставили на сутки, мы ОС не успели установить, чтобы обновы накатывать было на что.

      Незабываемый опыт!


    1. mvv-rus
      02.01.2026 13:38

      Удаленная проверка может быть бесполезна. Нормальный руткит, который я словил около 25 лет назад подменял большинство системных утилит, которые просто подменяли вывод и не показывали активность вируса.

      Я аналогичный руткит тоже словил как раз 25 лет назад. Взлом был, мне так смутно припоминается, через bind. Не помню уж, на чем тот руткит спалился, возможно - чисто на профилактическом поиске после обновления, после того, как я на BugTraq слазить удосужился. И искал я этот руткит как раз удаленно (ну как удаленно - вообще-то, я сидел в той же комнате, но заходил по ssh), потому что монитора на нем не было: прекрасную 17" Iiyama от прежнего владельца (который ставил этот сервер, это был шлюз фирмы в Интернет) уже кто-то себе забрал : тогда такой монитор был крут весьма. А искал я этот руткит, лазая руками (точнее, простейшими скриптами) по /proc и сравнивая ее содержимое с выдачей заруткиченных утилит. Ну, нашел, вычистил. Поскольку серверу оставалось жить что-то мало - с целью снижения бас-фактора шлюз планировалось вскоре перенести на Windows, потому что в Linux хоть как-то шарил только я один, причем я был ни разу не спецом и вообще программистом, так что жить серверу планировалось недолго - тогда решили залатать дыру по минимуму, без фанатизма.

      Так что при минимальном умении такой руткит, который вызовы на уровне ядра не перехватывает, вполне ищется, даже не-совсем-специалистом. Но это всё было давным-давно.


      1. RTFM13
        02.01.2026 13:38

        Взлом был, мне так смутно припоминается, через bind.

        В моём случае это была федора 6.2 которая если не на первом месте, то точно в топ 10 самых дырявых дистрибутивов с RCE (минимум 3 дырявых сервиса включенных по умолчанию).


        1. mvv-rus
          02.01.2026 13:38

          Там было нечто, что изначально было Slackware, но весьма сильно допиленное предыдущим хозяином. Предыдущий хозяин был из старых юниксоидов - из тех, что могли с SCO Unix работать без патча Бармина - он работал, правда в всторге от нее не был - или править руками sendmail.cf - он тогда рассказывал нам нам байки о временах, когда SMTP был далеко не единственным стандартом электронной почты, я эти времена застал только как пользователь: была у нас тогда в лаборатории электронная почта на некой адаптации UUCP под MS-DOS, uupc называлась. А потому ставил и настраивал он сервер своими руками. Так что при нем никаких дырок не было, они со временем появились. Ну, а я был официально программистом на Delphi, заодно и нашу инфраструктуру на WinNT (NetWare 3.11 не пережила Y2K, и пришлось с нее срочно перелазить) админил, а всё хозяйство на Linux мне от него с компаньоном, с которым они фирме интернет-узел (доступ по выделенке в интернет, сайт, модемный пул и всё такое) делали, по наследству досталась - они тогда ушли в Rambler, ещё к Крюкову.


  1. zartdinov
    02.01.2026 13:38

    Одна из причин почему не люблю, когда собирают домашний сервер и устанавливают туда 100500 прикольных сервисов, которые торчат наружу.


    1. poige
      02.01.2026 13:38

      Проблема не в том, что собирают, а каким лапками — но да, как правило именно такими…


    1. achekalin
      02.01.2026 13:38

      Словно свой или не свой - как-то влияет на качество настройки.

      Арендуемый сервер или колокейшен или домашний сервер - вопрос про руки, а не про владение.


      1. oldzoomer
        02.01.2026 13:38

        Он имеет ввиду скорее всего про то, что надо пользоваться managed-сервисами (то бишь вместо обычного локального видеонаблюдения, например - облачное, по типу Ростелекома, или Триколора, вместо NAS - Яндекс Диск, вместо Home Assistant - проприетарные умные девайсы, которые умеют дружить только с самим собой). Вот там да - безопасность повыше будет, ибо это коммерческий сервис, с соответствующими требованиями к репутации разработчика.


  1. Wesha
    02.01.2026 13:38

    Никакого вам «Здравствуйте», а лишь заявление о злоупотреблении и угроза отключить всю инфраструктуру через 4 часа.

    У меня скрипт практически один в один такое письмо при детектировании атаки хозяину сервера, с короторого она исходит (по данным WHOIS) шлёт. А чего ему здоровкаться — он же шелезяка!


    1. JBFW
      02.01.2026 13:38

      Было забавное, когда робот отправлял юзерам письма с разными предупреждениями, а ему отвечали в стиле:

      Уважаемый Робот,
      Просим Вас блаблабла...


  1. DmitryOlkhovoi
    02.01.2026 13:38

    У нас было на aws, на инстансах в разных странах запустили майнинг. Где-то в 2017м. Пришел платеж от амазона на 300к зеленых. Часть вроде простили, но все равно бюджет на сервера был превышен)
    Оказалось, что уволенный давно сотрудник, кому-то кидал конфиг с токенами через пастебин, и он заиндексировался гуглом


    1. DaneSoul
      02.01.2026 13:38

      Оказалось, что уволенный давно сотрудник, кому-то кидал конфиг с токенами через пастебин, и он заиндексировался гуглом

      Да тут и без пастебина дыра в безопасности, если после увольнения сотрудника доступы не сменились.


      1. xenon
        02.01.2026 13:38

        Для большой компании с огромным бюджетом и IT отделом - да. (Там где все умножается на многие миллионы). Для маленькой - "правильное" управление доступом все делает в N раз медленнее, дороже и сложнее.

        Самое простое - типичная ситуация в небольшом проекте, когда программист пишет - мне нужен readonly доступ к продакшн базе прежнего проекта.

        Правильный ответ: тут же дать ему доступ. Скорее всего, он делает что-то по работе и это согласовано и проблема решается за 1 минуту.

        Безопасный (параноидальный ответ): посмотреть, кто это должен согласовать (для этого - вести схему ответственности, и не в голове, а как документ), потребовать от него отправить запрос через того человека, когда запрос придет - занести в журнал, что у нас Вася знает пароль такого-то аккаунта (чтобы при увольнении удалить) и выдать. А еще лучше, не выдать, а создать отдельную учетку или через хранилище секретов.

        В общем, и технический и бюрократический ад получается. Причем сама эта сложная схема (с хранилищем секретов или тысячей аккаунтов) будет мало того, что сложной в обслуживании, так и нести в себе риски безопасности (лестница надежнее лифта, а лифт надежнее трансионного телепортатора).


        1. DaneSoul
          02.01.2026 13:38

          Для маленькой - "правильное" управление доступом все делает в N раз медленнее, дороже и сложнее.

          С другой стороны, у маленькой компании не так часто увольняются сотрудники, да и доступов не так много, можно просто профилактически поменять их все на новые и спать спокойно.


        1. anshdo
          02.01.2026 13:38

          Большая компания от превышения бюджета на сервера на 300к только почешется, а маленькую это может обанкротить.


  1. andreymal
    02.01.2026 13:38

    Он блокирует все входящие подключения кроме SSH, HTTP и HTTPS.

    Однажды для автора станет открытием, что Docker добавляет свои разрешающие правила в обход ufw


  1. taheen
    02.01.2026 13:38

    перевод ужасен, прочитал в оригинале, спасибо :) если не умеете - может и не стоит браться за (перевод)?


    1. achekalin
      02.01.2026 13:38

      Kpi есть kpi


  1. apcs660
    02.01.2026 13:38

    uid 1001 очень многие докер сборки используют по умолчанию, и оно совпадает с uid первого пользователя созданного в большинстве линукс сборок, которые создаются первыми при установле и часто имеют права sudo.


  1. nervnomancer
    02.01.2026 13:38

    Интересно, хетцнеры такие мудаки только с мелкими аккаунтами или со всеми (тогда надо себя совсем не уважать, чтобы им деньги заносить)? Дали, как понимаю, сутки времени.


    1. daniillnull
      02.01.2026 13:38

      Сутки времени для реагирования на инцидент подобного уровня — вполне неплохо. Некоторые хостинги (особенно небольшие российские) даже за куда менее критичные проблемы могут отключить сервер сразу, а затем неприлично долго тянуть разбирательство в поддержке…


      1. nervnomancer
        02.01.2026 13:38

        >Сутки времени для реагирования на инцидент подобного уровня — вполне

        какой инцидент? что-то там посканили с него? и чо?

        >небольшие российские

        смысл помойки обсуждать? у меня было в селектеле похожее (якобы брутфорсы с него), я вообще только через месяц заметил от них письмо, когда уже сервер снёс и даже разобраться не получилось что это было. ну написали о проблеме молодцы. А вырубать сервак? Сразу в сад пойдёте (если ты не терпилоид)


    1. Frankenstine
      02.01.2026 13:38

      Если за сутки не среагируете, сервер будет отрублен от интернета, а вам предоставят обходной путь "через локалку" (аля бастион) для входа и починки. После того как устраните проблему - напишите в техподдержку и сервер вернут в сеть.


  1. xenon
    02.01.2026 13:38

    Если депутат во вторник подскользнется на гололеде и сломает ногу, он запретит вторники.

    Забавно, что автор по итогу решил начать с запрета вторников. Перешел на ssh авторизацию по ключам, но оставил umami. Жаль что не провел анализ, хорошо ли шифруются пароли в /etc/shadow и если есть более криптостойкий алгоритм (а они есть всегда) - то мог бы перейти.

    "Если обнаружена CVE, я применяю патч или удаляю сервис" - в теории, это, конечно, хороший принцип. Как он узнает, что "обнаружена CVE"? Есть ряд коммерческих сервисов, которые сканируют облако (в AWS), знают версии ПО и оповещают, "если обнаружена CVE". Но у него такого нет (он не упомянул), да и хостится он на лоукостере (само по себе - не проблема), но что-то мне подсказывает, что для него "если обнаружена CVE", это подход, когда новость об уязвимости рвет всем новостные ленты и в прайм-тайм по ТВ обсуждается.

    Правильное решение (в случае клиента) - клиентские сетификаты (mTLS). Вернее, это общее правило - если есть не-публичный ресурс (для себя, для семьи, для небольшой фирмы) и вы не используете клиентские сертификаты для доступа - скорее всего, вы делаете что-то неправильно. Это прямо универсальная пилюля, семь бед - один ответ. Есть бизнес-критикал приложение из прекрасных 1980 на Коболе и сложно заменить - окей, закрываем сертификатом. Вот если вы еще не того уровня, чтобы вас взламывали ЦРУ и кремль, а красивая молодая девушка из иркутского ТЮЗа оказалась их honeypot, если наиболее вероятная угроза для вас - нонейм хакер из индонезии - это - самый первый и почти непреодолимый уровень защиты.

    Вторая проблема (как мне кажется), он сам не знает, не понимает, что использует. Да, в самом коде umami дырки нет, а в зависимостях есть. Но, я бы проверил: Был ли на тот момент анонс от разрабов umami что по итогу в их контейнере есть уязвимость (и апдейт)?
    Если да - ну всех дел - просто обновлять контейнеры своевременно. Если нет - то подумать, сильно ли он нужен, этот umami, может быть чем-то заменить, либо чем-то минималистичным (без большого дерева зависимостей), либо с таким деревом, но с серьезным отношением к безопасности.


    1. anshdo
      02.01.2026 13:38

      Кстати, вины Umami здесь точно нет. Они выпустили исправление для своего свободного ПО ещё неделю назад. Просто у меня не дошли руки его применить.


      1. wxe
        02.01.2026 13:38

        Они каждый месяц делают релизы, а о критичности релиза на сайте - ни слова! Сам факт патч релиза не требует немедленного обновления, не все читают все release patch notes. Не ясно, отправляли ли они письмо пользователям с информацией о критичности уязвимости.


        1. nervnomancer
          02.01.2026 13:38

          Вся эта статья про то какое докер говно. В котором нет в принципе security-веток. При этом, миллиарды мышей его грызут и нахваливают.

          Первоочередная вина конечно у проектов без stable веток. Но они прям друг друга нашли и стали сладкой парочкой. Кушайте, не обляпайтесь.


          1. RTFM13
            02.01.2026 13:38

            А при чем тут докер? Докер в данном случае спас корневую систему от заражения.


            1. nervnomancer
              02.01.2026 13:38

              спас от примитивного червяка никому не нужный локалхост, в котором ни мониторинга, ни нормального админа, ни бэкапов.
              прохладная история успеха уровня "клауде-шмауде за час написало то что лузерсквод писал год"

              >А при чем тут

              что непонятно в УЖЕ написанном "в котором нет в принципе security-веток".


    1. Frankenstine
      02.01.2026 13:38

      Правильное решение (в случае клиента) - клиентские сетификаты (mTLS). Вернее, это общее правило - если есть не-публичный ресурс (для себя, для семьи, для небольшой фирмы) и вы не используете клиентские сертификаты для доступа - скорее всего, вы делаете что-то неправильно. Это прямо универсальная пилюля, семь бед - один ответ.

      Да блин, зачем так сложно. Просто поставь basic http auth пароль, и всего-то делов.


    1. Paul_Arakelyan
      02.01.2026 13:38

      Блин, как хорошо, что девушки из Иркутска у нас вроде не ходют. И ТЮЗ далековато. Это, оказывается, тоже улучшает безопасность :)).

      Да большинство любителей докера - не заморачиваются, "что там в контейнере" и что оно все ещё и наружу торчит. Уровень тех же "у вас не хватает драйверов - загрузите наш драйвер-сканер!". Люди решают свои задачи - и не хотят вникать в сопутствующие вопросы, машину покупают чтоб ехать куда надо, а не масло менять.


  1. Junecat
    02.01.2026 13:38

    я вот искренне не хочу верить в свои сверхспособности, но когда я прочитал название статьи - то первой мыслью было "А не через Next.js ли его ломанули, беднягу?". Ну просто потому, что Next.js-уязвимость - эпичная, как ... даже не знаю. как Heartbleed?


  1. YuSV
    02.01.2026 13:38

    А бывает ещё так) Когда работал в аутсорсинге, на одном из серверов был майнер. Написал админу. Оказалось сам админ майнит на рабочем сервере. Попросил разрешения снести, ибо все таки там ПО, за работу которого мне платили.


  1. UniInter
    02.01.2026 13:38

    Полезная разборка полетов для пользователей Next.js. Тут вирус пришел извне. Часто источником вируса в системе является "несправедливо" уволенный админ, оставивший на память о себе и для себя какой-нибудь backdoor и дальше работает его фантазия.


  1. LF69ssop
    02.01.2026 13:38

    1. А что сканить хосты уже преступление? Звоночек да, но не более.

    2. Система скомпрометирована. Теперь только полная перестановка, жаль если автор этого не понимает.

    3. Ну и да, зачем был разрешен доступ из контейнера в сеть?


    1. Paul_Arakelyan
      02.01.2026 13:38

      1. TOS/AUP - описывают "почти всё", и ваши понятия о "преступлении" - им по барабану. "вилка" от сети и розетки - у них, будете судиться или сразу "цветочки" летающие пришлете?

      2. Там все в рамках докер-контейнера "поехало". Так что все менее стремно. Но вообще идиотизм эксплуатирующих уязвимость - поражает. Можно же "не мешая окружающим" все делать, а не "по самые помидоры" грузить...

      3. "поколение докера" - редко задумывается о таких вещах и верит в лучшее :). Не всегда удачно, но в большинстве случаев "и так сойдет" - прокатывает.


    1. LinkToOS
      02.01.2026 13:38

      А что сканить хосты уже преступление? Звоночек да, но не более.

      В соглашении может быть требование заявлять о наличии сканеров, и санкции за сокрытие.

      Ну и да, зачем был разрешен доступ из контейнера в сеть?

      Видимо для Umami.


      1. LF69ssop
        02.01.2026 13:38

        Видимо для Umami.

        А зачем серверу аналитики доступ в сеть? Что именно он аналитит?


  1. ivvi
    02.01.2026 13:38

    загрузке CPU 1000%+

    Это как?!?


    1. ComputerPers
      02.01.2026 13:38

      10 ядер по 100%


      1. isden
        02.01.2026 13:38

        Я как-то видел LA за 50 на одноядерной впске =)


  1. Fintank-ru
    02.01.2026 13:38

    delete


  1. LinkToOS
    02.01.2026 13:38

    Меня взломали! Утром мой сервер начал майнить Monero

    Оригинальное название не следовало сохранять, оно неправильное. Утром автор истории узнал что с сервером есть проблема, и начал разбираться. А крипту сервер майнил уже 10 дней, по его словам. В какое время дня он начал майнить не сказано.
    Более правильное название для перевода - "Меня взломали! Утром я узнал что я идиот." (он же не следил за обновлениями безопасности для установленного ПО)


  1. bleedingedge
    02.01.2026 13:38

    У меня пару раз подобное было. И как оказывается, лучшая защита - это отсутствие в контейнере curl и wget, и блок GitHub. Потому что всё оно работает по одному принципу, грузится скрипт, далее с помощью curl или wget с GitHub тянется что-нибудь более вредное. Если не получилось, всё заканчивается на стаскивании env (будьте готовы менять пароли).

    С контейнерами докера беда в том, что если их больше пары, хрен за ними уследишь, особенно если они открыто смотрят в сеть. Поэтому нужно использовать как можно тоньше контейнеры.


    1. Areso
      02.01.2026 13:38

      Тонкие контейнеры больно отлаживать(?)/дебажить.


      1. bleedingedge
        02.01.2026 13:38

        100% согласен. Но увидев пару, как они спасают, я всё-таки решил,что нужно через эту боль пройти.