CVE-2025-14847 (MongoDB Server) — wyciek pamięci heap przez zlib w protokole MongoDB

securitybeztabu.pl 7 godzin temu

TL;DR

CVE-2025-14847 to podatność w MongoDB Server związana z obsługą zlib w kompresji sieciowej protokołu MongoDB: niespójne pola długości w nagłówkach skompresowanych wiadomości mogą doprowadzić do zwrócenia fragmentów niezainicjalizowanej pamięci heap do klienta bez uwierzytelnienia.
Dla SOC oznacza to: jeżeli instancja MongoDB jest wystawiona na Internet, atakujący może „wyciągać” z odpowiedzi wrażliwe fragmenty pamięci procesu (potencjalnie dane aplikacyjne/sekrety zależnie od tego, co akurat było w RAM). Priorytet: patch do wersji naprawionych lub czasowo usuń zlib z kompresorów.

Krótka definicja techniczna (1 akapit)

CVE-2025-14847 to błąd klasy CWE-130 polegający na niewłaściwej obsłudze niespójnych parametrów długości w zlib-compressed protocol headers MongoDB, co umożliwia zdalnemu, nieautoryzowanemu klientowi odczyt niezainicjalizowanej pamięci heap poprzez odpowiedzi serwera.

Gdzie występuje / przykłady platform (Windows, AD, AWS, Azure, GCP, K8s, ESXi, M365)

Windows (self-hosted):

  • mongod.exe/mongos.exe uruchomione jako usługa (często port 27017) — ryzyko rośnie, gdy bind/listen jest „na świat” i gdy zlib pozostaje włączony (domyślnie jest).

AD (Active Directory):

  • Bezpośrednio „nie dotyczy” (to nie jest podatność AD), ale realnie MongoDB bywa konsumowane przez aplikacje domenowe; wyciek pamięci może pośrednio ujawnić np. tokeny/sekrety aplikacyjne trzymane w RAM.

AWS (EC2 / EKS / self-managed):

  • EC2 z Security Group otwierającą 27017/27018 do 0.0.0.0/0 → klasyczny scenariusz T1190.
  • EKS: MongoDB jako StatefulSet; ekspozycja przez Service type=LoadBalancer/Ingress/NodePort zwiększa ryzyko.

Azure (VM / AKS):

  • VM z publicznym IP + NSG pozwalający na 27017; AKS analogicznie jak EKS.

GCP (Compute Engine / GKE):

  • Publiczny endpoint + reguły FW do 27017; w GKE ekspozycja przez Service LB.

Kubernetes (K8s):

  • Szczególnie ryzykowne: publiczny LoadBalancer dla MongoDB lub brak NetworkPolicy dla namespace z bazą.

ESXi:

  • Pośrednio: gdy MongoDB stoi na VM — liczą się zasady ekspozycji/segmentacji sieci, snapshoty do IR itp.

M365:

  • Zwykle „nie dotyczy” (chyba iż logi/alerty spływają do Sentinel/MDE; sama podatność jest po stronie serwera MongoDB).

Ważne operacyjnie: MongoDB informował, iż Atlas fleet został spatchowany i „nie ma dowodów” na wykorzystanie ani kompromitację danych klientów; dotyczy to jednak usług zarządzanych — self-hosted musi być zaktualizowany osobno.

Szczegółowy opis techniki (jak działa, cele, dlaczego jest skuteczna)

Negocjacja kompresji i dlaczego zlib ma znaczenie

MongoDB wspiera kompresję ruchu między klientem a serwerem (OP_COMPRESSED). Domyślnie zarówno mongod, jak i mongos mają ustawione kompresory sieciowe na snappy,zstd,zlib (w tej kolejności).
CVE-2025-14847 dotyczy ścieżki obsługi zlib: spreparowane (niepoprawne) nagłówki skompresowanych wiadomości z niespójnymi długościami mogą doprowadzić do sytuacji, w której serwer zwraca w odpowiedzi fragmenty niezainicjalizowanej pamięci heap.

Co realnie wycieka z heap i jak to eskaluje ryzyko

Ponieważ mowa o pamięci procesu, w praktyce „to, co wycieknie”, zależy od:

  • obciążenia bazy (zapytania/odpowiedzi, BSON, bufory),
  • bibliotek i alokacji w danym buildzie,
  • tego, co aplikacje trzymają w pamięci (np. fragmenty dokumentów, metadane sesji, czasem sekrety).

Oficjalny wektor CVSS od CNA wskazuje wysoki wpływ na poufność i brak wpływu na integralność/dostępność (C:H / I:N / A:N).

Dlaczego to pasuje do ATT&CK T1190

Jeżeli MongoDB jest publicznie wystawione (Internet-facing), to atakujący wykorzystuje błąd w usłudze nasłuchującej na gnieździe TCP — to klasyczny model Exploit Public-Facing Application (T1190) w taktyce Initial Access (nawet jeżeli „efektem” jest wyciek informacji, a nie RCE).

Artefakty i logi (tabela — EID, CloudTrail events, K8s audit, M365 operations)

Obszar obserwacjiWindows EID (przykłady)CloudTrail (AWS)K8s AuditM365 operationsCo zbierać / na co patrzeć
Ekspozycja portu MongoDB (27017/27018)Sysmon EID 3 (NetworkConnect), Windows Filtering Platform 5156AuthorizeSecurityGroupIngress, ModifySecurityGroupRules, RevokeSecurityGroupIngresspatch/create Service (LoadBalancer/NodePort), Ingress, NetworkPolicyN/ASkoki nowych źródeł łączących się do 27017; ruch z Internetu do DB zamiast z warstwy app
Start procesu MongoDB i parametry ryzykaSysmon EID 1 (ProcessCreate), Security 4688N/Acreate/patch Deployment/StatefulSet (args/env/config)N/ACzy mongod/mongos startuje z --bind_ip_all / 0.0.0.0 oraz czy wymuszasz wyłączenie zlib
Zmiany konfiguracji kompresjiEID 1/4688 + (opcjonalnie) audyt plików mongod.confN/Azmiany ConfigMap/Secret montowanych do podaN/ACzy net.compression.compressors przez cały czas zawiera zlib (domyślnie zawiera)
„Skany” i bursty połączeń do MongoDBSysmon EID 3 + firewall(opcjonalnie) GuardDuty/VPC Flow Logs poza CloudTrailN/AN/AWysoka liczba krótkich połączeń, nietypowe geolokacje/ASN, brak auth events (bo pre-auth)
Działania IR/patchEID 1/4688 (restart usługi), systemd logsStartInstances/StopInstances (jeśli robisz)rollout restart, delete podN/AOkno zmian + walidacja, iż wersja/kompresja jest zgodna z polityką

Detekcja (praktyczne reguły)

Sigma (gotowa reguła)

Cel: wykryć hosty, na których MongoDB jest uruchamiane w sposób zwiększający ekspozycję na CVE-2025-14847 (publiczny bind i/lub jawnie włączone zlib).
Uwaga: to jest detekcja „posture / hardening”, nie sygnatura exploit payload.

title: MongoDB Server Risky Startup Options (CVE-2025-14847 / zlib / public bind) id: 3f7f2c2e-5b5c-4a6c-9b5e-6b7f9e3a8a21 status: experimental description: > Detects mongod/mongos started with zlib network compression enabled and/or bound to all interfaces, increasing exposure to CVE-2025-14847 (unauth heap memory read via zlib compressed protocol). references: - https://nvd.nist.gov/vuln/detail/CVE-2025-14847 - https://jira.mongodb.org/browse/SERVER-115508 - https://www.mongodb.com/docs/manual/reference/configuration-options/ author: Badacz CVE date: 2025/12/25 tags: - attack.initial_access - attack.t1190 logsource: category: process_creation product: windows detection: selection_image: Image|endswith: - '\mongod.exe' - '\mongos.exe' selection_public_bind: CommandLine|contains: - '--bind_ip_all' - '--bind_ip 0.0.0.0' - 'bindIpAll' - 'bindIp: 0.0.0.0' selection_zlib_cli: CommandLine|contains|all: - 'networkMessageCompressors' - 'zlib' selection_zlib_cfg_hint: CommandLine|contains|all: - 'net.compression.compressors' - 'zlib' condition: selection_image and (selection_public_bind or selection_zlib_cli or selection_zlib_cfg_hint) fields: - Image - CommandLine falsepositives: - MongoDB za reverse-proxy / w prywatnej sieci, gdzie bind na 0.0.0.0 jest akceptowalny - Środowiska, gdzie zlib jest wymagany (wydajność/kompatybilność), ale port nie jest publiczny level: medium

Dlaczego to ma sens: zlib jest domyślnie włączony w mongod/mongos (snappy,zstd,zlib), więc realna mitigacja często polega na jego usunięciu/wyłączeniu.

Splunk (SPL)

A) Wykrywanie nieautoryzowanych źródeł łączących się do MongoDB (logi MongoDB):

index=mongodb sourcetype=mongodb:log ("connection accepted" OR "Connection accepted") | rex field=_raw "from (?<src_ip>\d{1,3}(\.\d{1,3}){3}):(?<src_port>\d+)" | stats count as connections dc(src_port) as uniq_src_ports by src_ip | sort - connections

B) Bursty krótkich połączeń (sygnał skanowania / prób exploitacji pre-auth):

index=mongodb sourcetype=mongodb:log ("connection accepted" OR "end connection") | rex field=_raw "connection accepted from (?<src_ip>\d{1,3}(\.\d{1,3}){3})" | timechart span=5m count by src_ip limit=20

C) (Jeśli masz VPC/NSG/Firewall w Splunku) — inbound na 27017 z Internetu:

index=netflow (dest_port=27017 OR dest_port=27018) action=allowed | stats sum(bytes) as bytes count as flows by src_ip dest_ip dest_port | sort - flows

KQL (Azure / Microsoft Sentinel)

A) Azure Firewall (NetworkRule) — ruch do 27017/27018:

AzureDiagnostics | where Category == "AzureFirewallNetworkRule" | where msg_s has "Dport: 27017" or msg_s has "Dport: 27018" | summarize flows=count() by SourceIP=src_ip_s, DestinationIP=dst_ip_s, bin(TimeGenerated, 5m) | order by flows desc

B) Wykrywanie publicznej ekspozycji przez zmiany NSG (Activity Log):

AzureActivity | where OperationNameValue has_any ("MICROSOFT.NETWORK/NETWORKSECURITYGROUPS/SECURITYRULES/WRITE", "MICROSOFT.NETWORK/NETWORKSECURITYGROUPS/WRITE") | where ActivityStatusValue == "Succeeded" | where Properties has "27017" or Properties has "27018" | project TimeGenerated, Caller, OperationNameValue, ResourceGroup, Resource, Properties | order by TimeGenerated desc

CloudTrail query (AWS CLI/CloudWatch)

A) CloudTrail Lake (SQL) — kto otworzył MongoDB na świat:

SELECT eventTime, userIdentity.arn, sourceIPAddress, eventName, requestParameters FROM <your_cloudtrail_lake_table> WHERE eventName IN ('AuthorizeSecurityGroupIngress','ModifySecurityGroupRules','RevokeSecurityGroupIngress') AND requestParameters LIKE '%27017%' ORDER BY eventTime DESC;

B) AWS CLI (lookup-events) + filtr portów (przykład z jq):

aws cloudtrail lookup-events \ --lookup-attributes AttributeKey=EventName,AttributeValue=AuthorizeSecurityGroupIngress \ --start-time 2025-12-01T00:00:00Z \ --end-time 2025-12-25T23:59:59Z \ --max-results 50 \ | jq -r '.Events[] | select(.CloudTrailEvent | test("27017|27018")) | [.EventTime, .Username, .EventName] | @tsv'

Elastic (EQL) przykłady

A) Inbound connections do MongoDB z adresów publicznych (Elastic Defend / endpoint network events):

network where event.type == "start" and destination.port in (27017, 27018) and network.direction == "inbound" and not cidrMatch(source.ip, "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16")

B) Start mongod/mongos z parametrami wysokiego ryzyka:

process where event.type == "start" and process.name in ("mongod", "mongos", "mongod.exe", "mongos.exe") and ( process.command_line like "*bind_ip_all*" or process.command_line like "*bind_ip 0.0.0.0*" or process.command_line like "*networkMessageCompressors*" and process.command_line like "*zlib*" )

Heurystyki / korelacje (co łączyć)

  1. Asset + posture: lista instancji MongoDB + wersja + czy port publiczny + czy zlib wyłączony.
    • zlib jest domyślnie włączony → jeżeli nie zrobiłeś hardeningu, traktuj jak „włączone”.
  2. Netflow/VPC Flow Logs/NSG Flow Logs: wzrost liczby połączeń do 27017 z nietypowych ASN/geo + krótkie sesje.
  3. MongoDB logs: dużo connection accepted bez towarzyszących zdarzeń auth/audit (pre-auth).
  4. Change management: korelacja w czasie z rolloutem poprawek (upgrade/konfig) i spadkiem prób połączeń.

False positives / tuning

Typowe FP:

  • skanowanie wewnętrzne (CMDB, monitoring, VA tools),
  • load balancer / NAT pokazuje jeden adres źródłowy,
  • legalne aplikacje o wysokiej częstotliwości połączeń.

Tuning:

  • allowlist znanych CIDR aplikacji/ETL/backup,
  • alertuj tylko dla źródeł spoza prywatnych zakresów,
  • progi: np. >N nowych IP w 10 minut lub >X połączeń/IP/5 min.

Playbook reagowania

  1. Triage ekspozycji
    • Sprawdź, czy MongoDB jest Internet-facing (SG/NSG/Firewall/Ingress).
    • Jeśli tak: priorytet P1 (T1190).
  2. Weryfikacja wersji
    • Na hoście:mongod --version mongos --version
    • Porównaj z wersjami naprawionymi: 8.2.3 / 8.0.17 / 7.0.28 / 6.0.27 / 5.0.32 / 4.4.30.
  3. Natychmiastowa mitigacja (jeśli nie możesz patchować „teraz”)
    • Wyłącz zlib w kompresji sieciowej, ustawiając kompresory na snappy,zstd albo disabled.
    • Przykład (wariant uruchomieniowy):mongod --networkMessageCompressors snappy,zstd # albo całkowicie: mongod --networkMessageCompressors disabled
  4. Remediacja docelowa
    • Upgrade do wersji naprawionej (jw.).
  5. Hunting / impact assessment
    • Przejrzyj logi połączeń do 27017 (źródła, wolumeny, okna czasowe).
    • Jeśli DB była publiczna: potraktuj to jak incydent „potential data exposure”.
  6. Rotacja sekretów (jeśli ekspozycja była realna)
    • Rotuj hasła użytkowników DB, klucze aplikacyjne, tokeny (w zależności od tego, co mogło znaleźć się w pamięci procesu).
    • Wymuś TLS + auth + segmentację sieci (minimalny blast radius).

Przykłady z kampanii / case studies

  • Brak publicznie potwierdzonych kampanii APT/ransomware wykorzystujących CVE-2025-14847 „w dziczy” na moment publikacji źródeł; MongoDB wskazywał, iż w Atlas „nie ma dowodów” na wykorzystanie ani kompromitację danych i iż flota została spatchowana.
  • Ten CVE jest jednak modelowym przykładem ryzyka T1190 dla baz danych (public-facing socket + bug w parserze/protokole).

Lab (bezpieczne testy) — przykładowe komendy

  1. Sprawdź, czy serwer przez cały czas pozwala na zlib
    • Ponieważ pole hello.compression pojawia się tylko, gdy kompresja jest używana, wymuś po stronie klienta zlib i zobacz, czy serwer je negocjuje.
    • Przykład:mongosh "mongodb://<host>:27017/?compressors=zlib" --eval 'db.hello()'
    • Jeśli w wyniku pojawia się "compression": ["zlib"], to zlib jest aktywnie używane (czyli mitigacja nie została wdrożona).
  2. Weryfikacja domyślnej listy kompresorów (dla wiedzy operacyjnej)
    • MongoDB domyślnie: snappy,zstd,zlib.
  3. Weryfikacja ustawień w pliku konfiguracyjnymsudo grep -n "compression" -n /etc/mongod.conf sudo grep -n "bindIp" -n /etc/mongod.conf
  4. K8s: sprawdź argumenty/ConfigMapkubectl -n <ns> get sts <mongo-sts> -o yaml | grep -n "networkMessageCompressors" -n kubectl -n <ns> get cm -o yaml | grep -n "net.compression" -n

Mapowania (Mitigations, Powiązane techniki)

ATT&CK (główne):

  • T1190 Exploit Public-Facing ApplicationTA0001 Initial Access

Dlaczego nie „RCE” w mapowaniu?
Opis CNA/NVD mówi o odczycie niezainicjalizowanej pamięci (information disclosure), a wektor CVSS v3.1 ma I:N/A:N — to nie jest opis skutku typu „arbitrary code execution”.

Mitigations (praktycznie):

  • Patch management / szybka aktualizacja wersji naprawionych
  • Ograniczenie ekspozycji (SG/NSG/Firewall/NetworkPolicy), zasada „DB nie jest publiczna”
  • Wyłączenie zlib (czasowo lub polityką) — snappy,zstd albo disabled

Powiązane techniki (łańcuchowo, zależnie od tego co wycieknie):

  • Potencjalnie: nadużycie ujawnionych sekretów → Valid Accounts (T1078) (jeśli wyciek umożliwi logowanie innymi kanałami).
    (To zależne od środowiska; sam CVE nie gwarantuje przejęcia kont.)

Źródła / dalsza literatura

  • NVD: opis, CVSS, wersje podatne, CWE-130 (NVD)
  • MongoDB JIRA SERVER-115508: fix/upgrade + workaround (wyłączenie zlib) (MongoDB Jira)
  • MongoDB Alerts (CVE-2025-14847): oficjalny wpis „Zlib … may allow memory read” + zakresy wersji (MongoDB)
  • MongoDB Docs: domyślne snappy,zstd,zlib (mongod/mongos) (MongoDB)
  • MongoDB Docs: hello.compression (walidacja negocjacji kompresji) (MongoDB)
  • MITRE ATT&CK: T1190 (tactic Initial Access, last modified) (MITRE ATT&CK)
  • MongoDB Community Hub: komunikat o spatchowaniu Atlas + brak dowodów exploitacji (wg MongoDB) (MongoDB)

Checklisty dla SOC / CISO

SOC (operacyjnie, dziś):

  • Zidentyfikuj wszystkie mongod/mongos i ich wersje.
  • Sprawdź ekspozycję 27017/27018 (Internet-facing = P1).
  • Jeśli nie możesz patchować natychmiast: usuń zlib z kompresorów (snappy,zstd lub disabled).
  • Wdróż detekcje: bursty połączeń, nowe źródła, zmiany SG/NSG.
  • Jeśli DB była publiczna: threat hunting + ocena ryzyka wycieku danych.

CISO / Risk:

  • Wymuś politykę: „bazy danych nie mają publicznych endpointów”.
  • SLA na patchowanie krytycznych/High dla usług publicznych.
  • Segmentacja sieci + Zero Trust dla dostępu do DB.
  • Standard hardening MongoDB: auth/TLS, ograniczenia kompresji, monitoring i centralne logowanie.
Idź do oryginalnego materiału