ApostropheCMS: Usuwanie składowych prototypu przez wykluczenie w projekcji w @apostrophecms/db-connect powoduje odmowę usługi dla całego procesu
Podsumowanie
@apostrophecms/db-connect zawiera wbudowaną w pamięci emulację MongoDB używaną przez adaptery SQLite, PostgreSQL oraz multipostgres. Funkcja pomocnicza unsetNestedField przechodzi po kontrolowanej przez atakującego ścieżce z kropkami bez walidacji segmentów i wywołuje delete na rozpoznanej właściwości. Uwierzytelniony użytkownik o niskich uprawnieniach (dowolna rola posiadająca view-draft, którą ma każdy edytor i współpracownik; ograniczona do dowolnego zalogowanego użytkownika, gdy włączone jest guestApiAccess) może wysłać żądanie GET REST dla typu piece, którego konstruktor zapytań project zawiera klucz wykluczający, taki jak constructor.prototype.hasOwnProperty. W adapterze SQLite lub PostgreSQL klucz ten trafia do unsetNestedField, co prowadzi do rozwiązania Object.prototype i usunięcia współdzielonej metody środowiska uruchomieniowego. Ponieważ metoda ta jest współdzielona w całym procesie Node, jej usunięcie uniemożliwia obsługę żądań dla każdego najemcy i użytkownika aż do restartu procesu, powodując trwałą odmowę usługi pojedynczym żądaniem.
Przyczyna błędu
Konstruktor zapytań projekcji oczyszcza wyłącznie wartości projekcji, a nigdy klucze, w wyniku czego dowolny klucz zawierający kropki trafia do warstwy bazy danych. W adapterach SQLite i PostgreSQL projekcja wykluczająca jest stosowana w JavaScripcie przez applyProjection, która dla każdego wykluczonego pola wywołuje unsetNestedField(result, field). unsetNestedField dzieli pole na . i iteruje po powstałych segmentach bez żadnych zabezpieczeń: w przeciwieństwie do pokrewnej funkcji setNestedField nie blokuje nawet dosłownego __proto__, a żadna z funkcji pomocniczych nie blokuje constructor ani prototype. Ponieważ obiekt roboczy jest zwykłym obiektem wygenerowanym przez JSON.parse(JSON.stringify(doc)), jego właściwość constructor odwołuje się do globalnego Object, więc ścieżka constructor.prototype.<member> dociera do współdzielonego Object.prototype i usuwa konfigurowalną metodę bazową.
Affected functions (repository-relative paths):
- unsetNestedField packages/db-connect/lib/shared.js:119-129 (no segment guard; delete on resolved property)
- applyProjection packages/db-connect/lib/shared.js:164-216 (exclusion branch calls unsetNestedField per excluded key)
Reachability driver (consumer on a SQL adapter):
- project.launder / project.finalize packages/apostrophe/modules/@apostrophecms/doc-type/index.js:2003-2103
- getRestQuery packages/apostrophe/modules/@apostrophecms/piece-type/index.js:1139-1157
- SQLite adapter applyProjection call packages/db-connect/adapters/sqlite.js:906,980
Wpływ
Wymagania wstępne: uwierzytelnione konto z uprawnieniem view-draft (dowolna rola edycyjna; dowolny zalogowany użytkownik, gdy włączone jest guestApiAccess: true) oraz konfiguracja korzystająca z adaptera SQLite, PostgreSQL lub multipostgres. Domyślny adapter mongodb przekazuje projekcję do natywnego sterownika MongoDB i problem go nie dotyczy. W tych warunkach pojedyncze spreparowane żądanie GET usuwa wybraną przez atakującego współdzieloną metodę prototypu (na przykład Object.prototype.hasOwnProperty, toString lub składową Array.prototype). Wykazaną konsekwencją jest trwała odmowa usługi w całym procesie: po usunięciu metody standardowe wywołania, takie jak obj.hasOwnProperty(...), zgłaszają błędy w całym Apostrophe, jego zależnościach i sterowniku bazy danych, przez co proces Node nie może obsługiwać żądań do momentu restartu.
Proof of Concept
The finding was reproduced by executing the shipped helper directly against the published db-connect source; a live consumer requires a SQLite or PostgreSQL adapter, an authenticated view-draft session, and at least one matching document.
- Uwierzytelnij się jako dowolny użytkownik z
view-draftw witrynie, której adapterem bazy danych jestsqlite,postgreslubmultipostgres. - Wyślij żądanie odczytu REST dla typu piece z projekcją wykluczającą, której klucz celuje we współdzieloną metodę prototypu.
- Zaobserwuj, że kolejne żądania kończą się niepowodzeniem w całym procesie z powodu usunięcia współdzielonej metody.
GET /api/v1/@apostrophecms/article?project[constructor.prototype.hasOwnProperty]=0
Cookie: <authenticated view-draft session>
safe benign exclusion {title:0} leaves Object.prototype.hasOwnProperty intact
VULNERABLE exclusion projection deleted Object.prototype.hasOwnProperty (callableBefore=true, brokeEveryObject=true)
VULNERABLE exclusion projection deleted an arbitrary Object.prototype method (__pocMarker)
Łańcuch ataku
- Ekspozycja: Uwierzytelniony użytkownik
view-draftwywołuje punkt końcowy GET REST typu pieceGET /api/v1/@apostrophecms/<piece-type>. - Kontrola: Ciąg zapytania
project[constructor.prototype.hasOwnProperty]=0jest przetwarzany przezqs(przy wyłączonymallowDots) na pojedynczy własny klucz z dosłownymi kropkami:{ 'constructor.prototype.hasOwnProperty': '0' }. - Ścieżka:
getRestQuerynajpierw stosuje konstruktory zapytań;project.launderkopiuje klucz dosłownie i rzutuje tylko wartość nafalse;project.finalizepomija fałszywą wartość za pomocąif (!val) continuei zachowuje klucz; kursor zapisuje go jako projekcję. - Blokada: Nadpisanie uprawnień
publicApiProjectiondziała tylko wtedy, gdycanAccessApi(req)ma wartość false, więc jest pomijane dla uwierzytelnionego wywołującego; brak listy dozwolonych, weryfikacji segmentów czy ochrony prototypu. - Prymityw: Na adapterze SQLite lub PostgreSQL
applyProjectionwybiera gałąź wykluczenia i wywołujeunsetNestedField(result, 'constructor.prototype.hasOwnProperty'), co prowadzi do rozwiązaniaObject.prototypei wykonaniadelete Object.prototype.hasOwnProperty. - Wynik: Współdzielona metoda prototypu zostaje usunięta dla całego procesu Node, uniemożliwiając obsługę żądań do czasu restartu.
Analiza mechanizmów ochronnych
Przeanalizowano mechanizmy ochronne i żaden z nich nie blokuje tej ścieżki. Konstruktor projekcji launder oczyszcza tylko wartości i zachowuje dowolne klucze. Obejście uprawnień publicApiProjection jest uzależnione od !canAccessApi(req), więc nie jest aktywowane dla uwierzytelnionego użytkownika view-draft. Pętla po kluczach finalize kończy działanie przedwcześnie przy fałszywych wartościach. unsetNestedField nie posiada walidacji segmentów: ani constructor, ani prototype nie są blokowane, a ścieżka constructor.prototype.<member> omija nawet częściowe sprawdzenie __proto__. Ponieważ obiekt roboczy pochodzi z JSON.parse(JSON.stringify(doc)), jego constructor to globalny Object, a ponieważ Object.prototype.hasOwnProperty jest konfigurowalna, operacja usuwania kończy się sukcesem. Wcześniejsza poprawka prototype pollution dodała walidację {__proto__, constructor, prototype} tylko w apos.util.set/get w osobnym pakiecie apostrophe, pozostawiając db-connect bez ochrony.
Podatne wersje
Ecosystem: npmPackage: @apostrophecms/db-connectConfirmed affected range: >= 1.0.0, <= 1.0.2Latest release checked: 1.0.2 (npm registry)Fix status: not fixed
Niezabezpieczona funkcja unsetNestedField oraz wywołanie gałęzi wykluczenia applyProjection są identyczne binarnie w wydaniach stabilnych 1.0.0, 1.0.1 oraz 1.0.2. Adaptery SQLite i PostgreSQL wywołują applyProjection dla każdego zwróconego dokumentu. Wersje przedpremierowe (1.0.0-alpha.1, 1.0.0-alpha.2, 1.0.2-alpha.0) zawierają ten sam kod. Podatność dotyczy wyłącznie instalacji z adapterem SQLite, PostgreSQL lub multipostgres; domyślny adapter mongodb nie jest podatny. Pakiet apostrophe deklaruje zależność @apostrophecms/db-connect@^1.0.1, która wskazuje na podatną wersję 1.0.2.
Sugerowane rozwiązanie
Należy zagwarantować, że niezaufane ścieżki pól nie będą miały dostępu do współdzielonych obiektów prototypu. Zarówno unsetNestedField, jak i setNestedField w packages/db-connect/lib/shared.js powinny odrzucać ścieżki zawierające segmenty __proto__, constructor lub prototype, na wzór zabezpieczenia unsafePathSegments w pakiecie apostrophe (apos.util.set/get). Alternatywnie funkcje mogą operować wyłącznie na własnych właściwościach (np. poprzez sprawdzenia Object.prototype.hasOwnProperty lub dostęp przez Map). Jako doraźne obejście można korzystać z domyślnego adaptera mongodb lub ograniczyć dostęp do punktów końcowych REST wyłącznie do w pełni zaufanych ról.
Zgłoszone przez zx (GitHub: @manus-pi).
Co trzeba zrobić
Zaktualizuj pakiet apostrophe do wersji 4.33.0 lub nowszej oraz @apostrophecms/db-connect do wersji 1.1.0 lub nowszej. Jako tymczasowe obejście można przełączyć się na domyślny adapter mongodb lub ograniczyć dostęp do końcówek REST do zaufanych ról.
Czego dotyczy
Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.
| Platforma | Paczka | Podatne wersje | Poprawka w wersji |
|---|---|---|---|
| Paczka npm | apostrophe | < 4.33.0 | 4.33.0 |
| Paczka npm | @apostrophecms/db-connect | < 1.1.0 | 1.1.0 |
Odnośniki
- https://github.com/apostrophecms/apostrophe/security/advisories/GHSA-j5rq-xfvr-p969
- https://github.com/apostrophecms/apostrophe/commit/9500b8b0e1d630d5e07fbb5fd2c25ed0943845ce
- https://github.com/apostrophecms/apostrophe/commit/f84fd41cbf6c22eb8d0008fc9c25df1f7130b350
- https://github.com/apostrophecms/apostrophe
- https://github.com/apostrophecms/apostrophe/releases/tag/@apostrophecms/db-connect@1.1.0
- https://github.com/apostrophecms/apostrophe/releases/tag/apostrophe@4.33.0
- Wektor CVSS
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:H- Słabość (CWE)
CWE-1321, CWE-400- Platforma
- npm
- Paczka
apostrophe, @apostrophecms/db-connect- Ujawniono
- 20.10.2026
- Aktualizacja
- 20.10.2026 21:23
Źródła i licencje · Redakcja lub tłumaczenie: DockRay. Zachowano prawa źródeł i obowiązujące licencje.
OSV / GitHub Advisory Database - GHSA-j5rq-xfvr-p969 - CC BY 4.0
Historia podatności: apostrophe
Wszystkie opisane podatności tej paczki (Paczka npm), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.
- Wszystkich wpisów
- 27
- Pierwsza → ostatnia
- 09.2020 10.2026
- Bez poprawki
- 4
- Wykorzystywana w atakach
- 0
Rozkład istotności
- Krytyczna 2
- Wysoka 8
- Średnia 13
- Niska 4
Ujawnienia w latach
- 2020: 2
- 2021: 2
- 2022: 0
- 2023: 0
- 2024: 0
- 2025: 0
- 2026: 23
-
ApostropheCMS: Usuwanie składowych prototypu przez wykluczenie w projekcji w @apostrophecms/db-connect powoduje odmowę usługi dla całego procesu ten wpis
Dowiedz się, które podatności dotyczą Twojej aplikacji
Po podłączeniu integracji DockRay i włączeniu raportowania oprogramowania DockRay porównuje zgłoszone wersje komponentów ze znanymi podatnościami i powiadamia o potwierdzonych dopasowaniach. Zakres zależy od obsługiwanej technologii i dostępnych biuletynów.