CVE-2025-12735 — expr‑eval: RCE przez nieograniczone funkcje w evaluate()

securitybeztabu.pl 5 godzin temu

TL;DR

Biblioteka expr‑eval (oraz fork expr‑eval‑fork) pozwala — z powodu niewystarczającej walidacji wejścia — przekazać do evaluate() spreparowany obiekt zmiennych/kontekstu i wywołać dowolne funkcje, co w środowisku Node.js może prowadzić do zdalnego wykonania kodu (RCE). Fork został załatany (v3.0.0); w oryginalnym repo trwa proces patchowania (PR #288, brak wydania). Priorytet: krytyczny dla backendów Node i funkcji serverless korzystających z expr‑eval.

Krótka definicja techniczna

CVE‑2025‑12735 to luka typu CWE‑94 (Improper Control of Generation of Code / Code Injection) w bibliotece expr‑eval, która umożliwia przekazanie własnych funkcji w obiekcie variables/context do evaluate(). Brak restrykcji/allowlisty funkcji pozwala w Node.js dotrzeć do API procesu (np. pośrednio do child_process) i doprowadzić do wykonania komend systemowych.

Gdzie występuje / przykłady platform

  • Aplikacje Node.js (monolity i mikroserwisy) — API, boty, serwery WWW.
  • Serverless: AWS Lambda/Azure Functions/Cloud Run z runtime Node.
  • Kontenery/Kubernetes: obrazy z zależnością expr-eval.
  • Przeglądarka: wpływ ograniczony (brak process/require), przez cały czas możliwe nadużycia logiki/dane.
  • Fork: expr-eval-fork — załatany w 3.0.0.

Szczegółowy opis techniki (jak działa, cele, skuteczność)

expr-eval parsuje i ocenia wyrażenia matematyczne. Luka polega na tym, iż funkcje dostępne w czasie ewaluacji nie były odpowiednio ograniczone i można je było wstrzyknąć poprzez obiekt zmiennych (evaluate(vars)), co narusza założenia „bezpiecznej alternatywy dla eval”. W środowisku Node.js skutkiem jest możliwość eskalacji do prymitywów wykonania (np. wywołania interpretera lub komend systemowych), gdy aplikacja przekazuje niezaufane wyrażenia/zmienne do parsera. CERT/CC odnotował wprowadzenie łat poprzez PR #288 (allowlista funkcji, mechanizm rejestracji), a GitHub Advisory formalnie klasyfikuje słabość jako CWE‑94. expr‑eval‑fork 3.0.0 zawiera poprawkę; w oryginalnym repo brak wydanego release’u w momencie publikacji.

Zakres wersji (według GH Advisories):

  • expr-eval ≤ 2.0.2 — podatne; brak opublikowanej wersji naprawczej.
  • expr-eval-fork ≤ 2.0.2 — podatne; naprawiono w 3.0.0.

Ocena ryzyka: CISA‑ADP ocenia na CVSS 9.8 (sieć, brak uprawnień/UI), GitHub na 8.6 (CVSS v4.0); różnica wynika z przyjętego modelu wektorów i założeń dot. kontekstu wykonania.

Artefakty i logi (co szukać)

WarstwaŹródło / IDNa co patrzećPrzykład / wskazówka
WindowsSecurity EID 4688, Sysmon EID 1Dziecko procesu node.exe → cmd.exe/powershell.exe; nietypowe -c//cParentImage = \node.exe, Image = \cmd.exe, CommandLine zawiera /c
Sysmon EID 3Nowe połączenia sieciowe z procesu aplikacji NodeNietypowe dest. IP/AS, brak w allowliście egress
Sysmon EID 11/13Tworzenie/zmiana plików/kluczy rejestru przez node.exeDrop plików w temp/autoruns
Linuxauditd (EXECVE), journaldnode uruchamia sh/bash/python z parametrem -c/usr/bin/node … → /bin/sh -c …
Container/K8sK8s audit (create na pods/exec, ephemeralcontainers)Próby ucieczki/utrzymania kontroli po RCEUżytkownik SA aplikacji inicjuje pods/exec
Cloud (AWS)CloudTrailNietypowe UpdateFunctionCode, CreateFunction, modyfikacje env/secrets przez role aplikacjiKoreluj z IP/UA i oknem incydentu
M365/Entra (po wtórnej kompromitacji)Unified Audit LogConsent to application”, „Add service principal”, „Add app role assignment to service principalWeryfikuj nieoczekiwane zgody/role w czasie incydentu

Detekcja (praktyczne reguły)

Sigma (Windows / Sysmon — „Node → shell”)

title: Suspicious Shell Spawned by Node.js (possible expr-eval abuse) id: 7b3fbf8c-2c7a-4d37-9b7a-ef3a6c1b57a8 status: experimental logsource: product: windows category: process_creation detection: parent_node: ParentImage|endswith: '\node.exe' child_shell: Image|endswith: - '\cmd.exe' - '\powershell.exe' cli_flags: CommandLine|contains: - ' /c ' - ' -c ' condition: parent_node and child_shell and cli_flags fields: - Image - CommandLine - ParentImage falsepositives: - Legit. task runners/installer scripts level: high tags: - attack.t1059.003 - attack.t1059.001 - attack.t1203 - attack.t1190

Splunk (Sysmon EID=1)

index=your_sysmon_index EventCode=1 ParentImage="*\\node.exe" | search Image="*\\cmd.exe" OR Image="*\\powershell.exe" | search CommandLine="* /c *" OR CommandLine="* -c *" | stats count min(_time) max(_time) by Computer, User, ParentImage, Image, CommandLine

KQL (Microsoft Defender for Endpoint)

DeviceProcessEvents | where InitiatingProcessFileName =~ "node.exe" | where FileName in~ ("cmd.exe","powershell.exe","bash","sh") | where ProcessCommandLine has_any (" /c ", " -c ") | summarize cnt=count(), firstTime=min(Timestamp), lastTime=max(Timestamp) by DeviceName, FileName, ProcessCommandLine, InitiatingProcessCommandLine

CloudTrail (CloudWatch Logs Insights)

fields @timestamp, eventSource, eventName, userIdentity.type, userIdentity.arn, sourceIPAddress | filter eventSource="lambda.amazonaws.com" and eventName in ["UpdateFunctionCode","CreateFunction","UpdateFunctionConfiguration"] | sort @timestamp desc

Cel: wychwycić nieoczekiwane zmiany kodu/konfiguracji funkcji wykonywane przez role/podmioty powiązane z usługą korzystającą z expr-eval.

Elastic EQL

process where process.parent.name == "node" and process.name in ("cmd.exe","powershell.exe","sh","bash","python") and process.args in ("-c","/c","-e")

Heurystyki / korelacje

  • SBOM/SCA telemetry: stwierdzona zależność expr-eval (<=2.0.2) lub expr-eval-fork (<=2.0.2) + anomalia „Node → shell”.
  • Wzorce ruchu: nagły egress z procesu aplikacji (nowe domeny/ASN) w pobliżu czasu wywołań evaluate().
  • Zmiany w infrastrukturze: CloudTrail UpdateFunctionCode/modyfikacje env/secret po zdarzeniach aplikacji.
  • M365/Entra: niespodziewane „Consent to application” / „Add service principal” po incydencie (możliwa eskalacja OAuth).

False positives / tuning

  • Legit. narzędzia Node uruchamiające powłokę (instalatory, task‑runnery) — obwiedniaj detekcję listą dozwolonych ścieżek/usług, oknem czasowym (CI/CD), użytkownikiem i komendami (blokuj -c poza maintenance).
  • Środowiska dev — wydzielone indeksy/logsource, niższy poziom alertowania.
  • Serwisy, które w ogóle nie powinny odpalać powłoki — alert krytyczny.

Playbook reagowania (IR)

  1. Triaging: korelacja alertu (Node→shell / CloudTrail / M365) + potwierdzenie zależności w SBOM (npm ls expr-eval).
  2. Izolacja: odłącz instancję/poda (K8s: kubectl cordon/drain serwis, tymczasowe NetworkPolicy egress‑deny).
  3. Ograniczanie szkód: rotacja secretów/tokenów używanych przez serwis; w chmurze — blokada roli/aplikacji zaufania.
  4. Forensyka: zachowaj dysk/pamięć, eksportuj dzienniki (Sysmon/auditd/CloudTrail/M365 UAL).
  5. Eradykacja:
    • Migracja do expr-eval-fork 3.0.0 lub wdrożenie łatki po publikacji release oryginału; tymczasowo usuń/wyłącz niestandardowe funkcje i wdroż allowlistę funkcji.
  6. Weryfikacja: testy regresji, monitoring post‑incident (szczególnie „Consent to application” w M365).
  7. Lessons learned: reguły pre‑commit/CI (npm audit, SCA), polityki review zmian zależności.

Przykłady z kampanii / case studies

Na dzień 11 lis 2025 brak potwierdzonej eksploatacji „in the wild”; Tenable klasyfikuje CVE jako „not exploited (being monitored)”. Rekomendowane jest pilne łatanie/migracja.

Lab (bezpieczne testy)

A. Weryfikacja zależności

# sprawdź wersję npm ls expr-eval expr-eval-fork # o ile obecne i podatne, przygotuj hotfix/migrację (fork 3.0.0)

B. Generowanie sygnałów do reguł (symulacja „Node → shell”)bez użycia luki:

# Linux node -e "require('child_process').spawn('/bin/sh',['-c','echo ok'],{stdio:'inherit'})" # Windows (PowerShell) node -e "require('child_process').spawn('cmd.exe',['/c','echo ok'])"

Następnie zweryfikuj dopasowania: Sysmon EID=1, auditd EXECVE, oraz reguły Sigma/SPL/KQL.

C. K8s/CloudTrail

  • W K8s odpal kubectl auth can-i dla SA serwisu i potwierdź brak uprawnień do pods/exec.
  • W AWS przepuść kontrolowany UpdateFunctionConfiguration (np. dummy tag), aby potwierdzić zadziałanie zapytania CloudWatch Insights.

Mapowania (Mitigations, powiązane techniki)

Mitigations (ATT&CK):

  • M1038 Execution Prevention (application allowlisting, blokada interpreterów w usługach).
  • M1054 Software Configuration (wyłącz/ogranicz niestandardowe funkcje, hardening konfigu).
  • M1045 Code Signing (wymuszaj podpisy/CI deklaratywny deployment).
  • M1047 Audit (regularny audyt zależności i uprawnień).

Powiązane techniki: T1190, T1203, T1059(.003/.004/.007)

Źródła / dalsza literatura

  • NVD: opis, CVSS CISA‑ADP 9.8, referencje (w tym PR #288, npm). (NVD)
  • CERT/CC VU#263614: opis wektora, stan łat (PR #288), identyfikatory (GHSA). (CERT Coordination Center)
  • GitHub Advisory (GHSA‑jc85‑fpwf‑qm7x): zakres wersji podatnych i wersje naprawcze (fork 3.0.0), CWE‑94, CVSS v4.0. (GitHub)
  • PR #288 (silentmatt/expr‑eval): propozycja poprawki (allowlista, testy), status Open. (GitHub)
  • BleepingComputer — materiał prasowy o RCE i rekomendacji migracji do forka. (BleepingComputer)
  • Tenable Research — status „not exploited” (monitorowane). (Tenable®)
  • ATT&CK v18 — wersjonowanie i strony technik. (MITRE ATT&CK)

Checklisty dla SOC / CISO

SOC (operacyjna)

  • Aktywuj/zweryfikuj telemetry: Sysmon (Win), auditd (Linux), K8s Audit, CloudTrail.
  • Wdroż reguły: Sigma/KQL/SPL/EQL z tej noty.
  • Przekrój SBOM/SCA: znajdź expr-eval/expr-eval-fork ≤ 2.0.2.
  • Koreluj „Node → shell” oraz nietypowy egress z procesów aplikacji.
  • Monitoruj M365 UAL pod kątem „Consent to application”/„Add service principal”.

CISO / AppSec (strategiczna)

  • Migracja: expr-eval-fork 3.0.0 lub oczekuj na oficjalny release oryginału (po weryfikacji PR #288).
  • Polityki wejścia: zakaz ewaluacji niezweryfikowanych wyrażeń; allowlista funkcji.
  • CI/CD: blok w PR na dodanie podatnych wersji (SCA), podpisy artefaktów (M1045).
  • Least privilege dla ról chmurowych usług korzystających z expr‑eval; segmentacja egress.
  • Plan IR: playbook z rotacją sekretów i sanityzacją środowiska po incydencie.

Uwaga dot. łat: wg GHSA fork expr‑eval‑fork ma poprawkę w 3.0.0; w oryginalnym expr‑eval trwa proces patchowania (PR #288, w momencie pisania Open). Planiści powinni rozważyć pilną migrację do forka i later ew. powrót po publikacji stabilnego wydania z łatą.

Idź do oryginalnego materiału