Incydent: osierocony kontener mongo-drill z kopią produkcyjnej w3_db dostępny z internetu bez uwierzytelniania — 2026-10-01 → 2026-10-08
| Pole | Wartość |
|---|---|
| ID | INCIDENT-2026-10-08-MONGO-DRILL-EXPOSURE |
| Severność | P1 Security — ekspozycja kopii danych produkcyjnych (nieuwierzytelniony MongoDB, port publiczny) |
| Status | ZAMKNIĘTY (containment i usunięcie wykonane 2026-10-08); działania naprawcze w toku (#7609) |
| Okno ekspozycji | 2026-10-01 03:08 UTC → 2026-10-08 ok. 18:35 UTC (ok. 7 dni 15,5 h) |
| Wykryto | 2026-10-08, ok. 18:25–18:35 UTC, przy analizie alertu HostSwapNearlyExhausted (#7529) |
| System | bms-4 (OVH ns3101999, 54.36.123.110) |
| Decyzja o zgłoszeniu | Nie zgłaszamy — decyzja właściciela z 2026-10-08 (patrz „Decyzja”) |
| Issue | #7609; wcześniejsza ta sama klasa: #6354 |
Notatka przygotowana dla właściciela i na potrzeby ewentualnego audytu/DPO. Zawiera fakty z logów i decyzje; wnioski prawne (czy zdarzenie jest naruszeniem ochrony danych podlegającym zgłoszeniu) są decyzją właściciela, nie autora notatki.
Streszczenie
Kwartalny test odtwarzania backupu MongoDB (p24-mongodb-restore-drill.service) uruchomił się
2026-10-01 03:05 UTC na bms-4. Skrypt scripts/mongodb-restore-drill.sh utworzył kontener
mongo-drill-1439728 (mongo:7.0) z mongod --bind_ip_all, bez --auth, z opublikowanym portem
0.0.0.0:27019->27017, i przywrócił do niego kopię produkcyjnej bazy w3_db. O 04:05:49 UTC systemd
zabił jednostkę po przekroczeniu TimeoutStartSec (odtwarzanie w3_db trwało 3397 s, w4_db jeszcze
nie ruszyło). Pułapka EXIT skryptu nie zadziałała przy SIGTERM, więc kontener został osierocony i
działał 7 dni, dostępny z internetu. Porty publikowane przez Dockera omijają reguły ufw
(łańcuch iptables DOCKER), więc zapora hosta go nie chroniła.
Zakres danych
- Kontener zawierał przywróconą kopię
w3_dbz backupuw3_db-2026-06-15.mongodump.gz(20 461 721 dokumentów). Nazwy kolekcji widoczne w logu odtwarzania sugerują dane osobowe klientów (m.in.users,businessaddressbooks,office-phone-numbers,office-billings). Zawartość nie była sprawdzana — to ocena z nazw kolekcji. w4_dbnie została odtworzona w kontenerze (przerwanie przez timeout), więc nie była w nim obecna.- Dodatkowo w
/tmpbms-4 leżały dwa archiwa z uprawnieniami0644(czytelne dla wszystkich lokalnych użytkowników hosta):w3_db-2026-06-15.mongodump.gz(7,68 GB) iw4_db-2026-06-15.mongodump.gz(2,93 GB). To ekspozycja lokalna (konta na hoście, m.in.claude-runner,claude-runner-2), nie sieciowa. Oba pliki usunięto.
Oś czasu (UTC)
| Czas | Zdarzenie |
|---|---|
| 2026-10-01 03:05 | Start kwartalnego drilla (timer p24-mongodb-restore-drill.timer). |
| 2026-10-01 03:07:45 / 03:08:12 | Utworzenie i start kontenera mongo-drill-1439728, port 27019 opublikowany na 0.0.0.0. |
| 2026-10-01 04:04:56 | Zakończone odtwarzanie w3_db (0 błędów); start w4_db. |
| 2026-10-01 04:05:49 | systemd zabija jednostkę (start operation timed out, Result=timeout). Kontener zostaje. |
| 2026-10-08 ok. 18:25–18:35 | Analiza alertu swap na bms-4 wykazuje kontener 7 dni po starcie; test TCP z zewnątrz do 54.36.123.110:27019 kończy się sukcesem; lokalnie listDatabases bez logowania zwraca admin, config, local, w3_db (tylko nazwy baz). |
| 2026-10-08 ok. 18:35 | Kontener zatrzymany przez właściciela (docker stop, dane zachowane). Wg logu workera okno ekspozycji kończy się 18:35; komentarz na #7609 podaje przybliżone „~18:50”. Port 27019 zamknięty — potwierdzone testem z zewnątrz i ss. |
| 2026-10-08 19:54 | Worker infra-task (#7609): przegląd logu połączeń (tylko adresy IP), docker rm -v, usunięcie /tmp/mongo-drill-1439728 wraz z dwoma archiwami, wpis audytowy w infra_operations. |
Dowody z logu połączeń
Źródło: docker logs mongo-drill-1439728 | grep -i 'connection accepted' wykonane przed usunięciem
kontenera; analizowano wyłącznie adresy IP (bez odczytu treści).
- 42 zaakceptowane połączenia: 16 lokalnych (
127.0.0.1, kontrole integralności drilla) oraz 26 z 20 różnych publicznych adresów IP. - Adresy zewnętrzne (liczba połączeń × IP):
- po 2:
9.234.18.247,20.38.35.135,185.108.70.109,159.223.126.161,146.190.66.99,142.93.11.107 - po 1:
87.236.176.246,87.236.176.199,67.205.130.212,40.76.136.72,20.38.35.88,20.168.121.140,20.163.11.221,20.106.172.110,20.102.99.117,20.102.90.23,172.172.161.215,137.184.64.184,134.33.97.72,134.122.117.196
- po 2:
- Atrybucja zakresów (wg workera, nie weryfikowana whois): 20.x, 40.x, 172.172.x — Azure; 142.93,
146.190, 159.223, 137.184, 134.122, 67.205 — DigitalOcean. Niesklasyfikowane:
9.234.18.247,134.33.97.72,185.108.70.109,87.236.176.199,87.236.176.246. Profil (liczne zakresy chmurowe, pojedyncze połączenia) jest typowy dla internetowych skanerów MongoDB.
Ograniczenia dowodów
mongodprzy domyślnym poziomie logowania nie zapisuje zapytań ani komend; do logu trafiają połączenia i operacje wolniejsze niż 100 ms (Slow query). Brak śladów odczytu w logu nie jest dowodem, że odczytu nie było — szybkielistDatabases/findnie zostawiają wpisu.- Instancja nie wymagała uwierzytelniania, więc każde z 26 połączeń zewnętrznych mogło wykonać dowolne polecenie.
- Kontener i jego logi zostały usunięte (
docker rm -v); analiza nie może być powtórzona. Zachowane są tylko liczby i lista IP z komentarza na #7609 oraz ta notatka.
Decyzja
Decyzja właściciela (2026-10-08): incydentu nie zgłaszamy (nie zgłaszamy go do organu nadzorczego ani do osób, których dane dotyczą).
Uzasadnienie podane przez właściciela: w logach MongoDB nie ma śladów wycieku (nie stwierdzono odczytu danych). Uzupełnienie właściciela (2026-10-08, wieczorem): zapytania do baz są logowane w serwisie do logowania, a dane są tam przechowywane przez dwa dni; na tej podstawie właściciel potwierdza, że wycieku danych nie było.
Zastrzeżenie oceniającego: patrz „Ograniczenia dowodów”. Brak wpisów w logu jest zgodny z samym
skanowaniem, ale nie wyklucza odczytu. Dwa fakty ograniczają też uzupełnienie właściciela:
(1) retencja serwisu logowania (2 dni) obejmuje co najwyżej ostatnie 2 z 7 dni ekspozycji
(2026-10-01 → 2026-10-08), więc pierwsze ok. 5 dni (do ok. 2026-10-06) nie mają w nim żadnego
pokrycia, niezależnie od zawartości; (2) kontener drilla uruchomiono bez opcji logowania komend
(mongod --bind_ip_all, domyślny poziom logowania, bez profilera), więc jego mongod sam z siebie
zapisuje połączenia i operacje wolniejsze niż 100 ms, a nie wszystkie zapytania; jednorazowa
próba odpytania Mezmo (2026-10-08 wieczorem) nie zwróciła żadnych linii dla frazy mongo-drill,
a kolejne zapytanie zostało odrzucone limitem (HTTP 429), więc nie udało się potwierdzić, że logi
tego kontenera w ogóle trafiały do serwisu. Wniosek oceniającego: brak dowodów odczytu, ale
potwierdzenie „nie było wycieku” nie wynika z dostępnych logów dla całego okna ekspozycji.
Decyzja o niezgłaszaniu opiera się na ocenie właściciela, a odpowiedzialność za nią spoczywa na nim. Ta notatka jest zapisem podstawy decyzji na wypadek
późniejszej weryfikacji. Gdyby pojawiły się nowe informacje (np. ślady użycia danych z kopii),
decyzję należy ponownie ocenić; punktem odniesienia dla ewentualnego terminu 72 h jest moment
stwierdzenia ekspozycji, tj. 2026-10-08 ok. 18:25–18:35 UTC.
Przyczyny
- Bezpośrednia: kontener drilla uruchomiony z
--bind_ip_all, bez--authi z portem opublikowanym na0.0.0.0(domyślne zachowanie Dockera omijaufw). - Utrwalenie:
TimeoutStartSecjednostki krótszy niż rzeczywisty czas drilla (~57 min tylko dlaw3_db) oraz brak sprzątania przy SIGTERM (pułapka tylko naEXIT). - Brak wykrycia: nie było przeglądu osieroconych kontenerów
mongo-drill-*; wcześniejsza naprawa #6354 usunęła skutek, nie zabezpieczyła przed powtórzeniem. AlertHostSwapNearlyExhaustedzwrócił uwagę dopiero pośrednio. - Dodatkowo: archiwa dumpów w
/tmpz uprawnieniami0644.
Działania
Wykonane (2026-10-08): zatrzymanie i usunięcie kontenera, zamknięcie portu 27019, usunięcie dwóch
archiwów z /tmp, wpis audytowy, przegląd logu połączeń (IP).
W toku (#7609, kod): publikacja drilla wyłącznie na 127.0.0.1 lub brak publikacji portu, --auth,
etykieta p24.drill=1, dłuższy TimeoutStartSec, sprzątanie przy SIGTERM (ExecStopPost= lub trap
TERM/INT/EXIT), prywatny katalog 0700 na archiwa, codzienny sweep osieroconych kontenerów z alertem
(Discord + GH issue), testy. Po zmergowaniu: ponowne wykonanie drilla Q4 2026 (kwartalna weryfikacja
DR nie została dotąd ukończona — w4_db nie była odtworzona) i zapis wyniku.
Obserwacja poboczna (osobny temat): skrypty w /opt/p24-infra/scripts/ należą do claude-runner z
zapisem dla grupy, a część z nich jest uruchamiana jako root przez timery/crony. Do oceny osobno.