ApostropheCMS: Nieuwierzytelnione wyczerpanie zasobów poprzez przetwarzanie aposBigUpload przed uwierzytelnieniem w @apostrophecms/import-export
Podsumowanie
Potencjalna podatność na odmowę usługi bez uwierzytelnienia występuje w ścieżce przesyłania importu podzielonego na fragmenty (chunked import), używanej przez @apostrophecms/import-export.
Podatne ścieżki API importu wywołują:
self.apos.http.bigUploadMiddleware()
zanim właściwa procedura obsługi importu przeprowadzi weryfikację uwierzytelnienia.
Ponieważ do bigUploadMiddleware() nie przekazano wywołania zwrotnego authorize, nieuwierzytelnione żądania mogą dotrzeć do operacji aposBigUpload start, chunk oraz end, zanim późniejsza weryfikacja req.user odrzuci import.
W rezultacie nieuwierzytelniony zdalny atakujący może utworzyć stan przesyłania po stronie serwera, zapisać dane fragmentów do magazynu przesyłania, wywołać przetwarzanie plików tymczasowych oraz zainicjować kontrolowane przez atakującego operacje czyszczenia, zanim uwierzytelnienie zostanie wyegzekwowane.
Komponent dotknięty podatnością
Pakiet:
@apostrophecms/import-export
Potwierdzona wersja podatna:
3.6.2
Potencjalne wcześniejsze wersje podatne:
Problem może dotyczyć wcześniejszych wydań 3.x, w których obecna implementacja importu oparta na big-upload się znajduje. Dokładna wersja wprowadzająca nie została jeszcze w pełni zweryfikowana; zaleca się, aby opiekunowie projektu potwierdzili zakres podatnych wersji.
Typ podatności
Główny:
CWE-400 — Niekontrolowane zużycie zasobów
Powiązane:
CWE-306 — Brak uwierzytelnienia dla funkcji krytycznej
CWE-770 — Przydział zasobów bez limitów lub dławienia
Szczegóły techniczne
Ścieżka importu stron rejestruje następujący łańcuch middleware:
packages/import-export/modules/@apostrophecms/import-export-page/index.js
importExportImport: [
self.apos.http.bigUploadMiddleware(),
async (req) => {
return self.apos.modules['@apostrophecms/import-export']
.import(req, self.__meta.name);
}
]
Do bigUploadMiddleware() nie jest przekazywane wywołanie zwrotne authorize.
Implementacja bigUploadMiddleware() jawnie obsługuje wywołanie zwrotne authorize i wykonuje tę autoryzację przed przetworzeniem protokołu aposBigUpload, gdy jest ono dostarczone.
Bez tego wywołania zwrotnego żądania zawierające:
aposBigUpload[type]=start
aposBigUpload[type]=chunk
lub
aposBigUpload[type]=end
są przetwarzane natychmiast.
Właściwe sprawdzenie uwierzytelnienia następuje dopiero później w:
packages/import-export/lib/methods/import.js
async import(req, moduleName) {
if (!req.user) {
throw self.apos.error('forbidden');
}
Oznacza to, że uwierzytelnienie następuje dopiero po tym, jak middleware do przesyłania fragmentów wykonało już pracę po stronie serwera.
Przebieg ataku
1. Start
Nieuwierzytelniony atakujący wysyła żądanie aposBigUpload[type]=start.
Serwer generuje identyfikator przesyłania i zapisuje metadane przesyłania dostarczone przez atakującego, w tym zadeklarowaną liczbę chunks.
2. Fragment (Chunk)
Atakujący może przesyłać dane fragmentu.
bigUploadChunk() kopiuje dane kontrolowane przez atakującego do:
/big-uploads/<id>-<n>-<chunk>
3. Koniec
Atakujący wysyła żądanie aposBigUpload[type]=end.
bigUploadEnd() rozpoczyna przetwarzanie przesyłania i tworzy pliki tymczasowe przed wywołaniem dalszego handlera importu.
Dopiero po zakończeniu tego przetwarzania wykonanie dociera do późniejszej kontroli uwierzytelnienia w import().
4. Wzmocnienie czyszczenia (Cleanup amplification)
Wartość chunks kontrolowana przez atakującego jest również wykorzystywana przez bigUploadCleanupOne():
for (const { chunks } of Object.values(bigUpload.files)) {
for (let i = 0; (i < chunks); i++) {
await ufs.remove(...);
}
}
Podczas inicjalizacji przesyłania nie wydaje się być egzekwowana żadna niska górna granica zadeklarowanej liczby fragmentów.
Pozwala to nieuwierzytelnionemu atakującemu na zwiększenie liczby operacji czyszczenia systemu plików wykonywanych dla danego przesyłania.
Proof of Concept
Poniższe odtworzenie zostało przeprowadzone wyłącznie w odizolowanym środowisku testowym.
Rozpoczęcie przesyłania bez uwierzytelnienia
curl -s -X POST \
'http://localhost:3000/api/v1/@apostrophecms/page/importExportImport?aposBigUpload[type]=start' \
-H 'Content-Type: application/json' \
--data '{"files":{"file":{"name":"evil.tar.gz","size":4,"type":"application/gzip","chunks":1}}}'
Serwer zwraca identyfikator przesyłania pomimo braku uwierzytelnionej sesji w żądaniu.
Przesłanie fragmentu
printf 'PWN!' >/tmp/chunk.bin
curl -s -X POST \
'http://localhost:3000/api/v1/@apostrophecms/page/importExportImport?aposBigUpload[type]=chunk&aposBigUpload[id]=<ID>&aposBigUpload[n]=0&aposBigUpload[chunk]=0' \
-F 'chunk=@/tmp/chunk.bin;type=application/octet-stream'
Żądanie kończy się sukcesem i powoduje wykorzystanie pamięci masowej po stronie serwera.
Finalizacja przesyłania
curl -i -X POST \
'http://localhost:3000/api/v1/@apostrophecms/page/importExportImport?aposBigUpload[type]=end&aposBigUpload[id]=<ID>'
Zaobserwowane zachowanie:
startzwraca kod HTTP 200 i identyfikator przesyłania bez uwierzytelnienia.chunkzwraca kod HTTP 200 i powoduje zapisanie fragmentu po stronie serwera.endostatecznie dociera do dalszego sprawdzenia uwierzytelnienia i zostaje odrzucone.- Jednak przetwarzanie dużego pliku (big-upload) po stronie serwera nastąpiło jeszcze przed tym odrzuceniem.
W odizolowanym środowisku testowym:
chunks=1skutkowało jedną próbą usunięcia w ramach czyszczenia.chunks=50skutkowało 50 próbami usunięcia w ramach czyszczenia.
Dowodzi to, że kontrolowana przez atakującego liczba fragmentów bezpośrednio wpływa na ilość pracy wykonywanej przez serwer przy czyszczeniu.
Wpływ na bezpieczeństwo
Podatność pozwala nieuwierzytelnionemu zdalnemu atakującemu na wywołanie operacji na pamięci masowej i systemie plików po stronie serwera, które powinny być dostępne wyłącznie dla uprawnionych użytkowników importu.
Możliwe konsekwencje obejmują:
- Zużycie przestrzeni dyskowej na przesyłane i tymczasowe pliki.
- Tworzenie stanu przesyłania po stronie serwera przez nieuwierzytelnionych użytkowników.
- Powtarzające się operacje wejścia/wyjścia na systemie plików.
- Wzmocnienie operacji czyszczenia w oparciu o liczbę fragmentów narzuconą przez atakującego.
- Potencjalną degradację wydajności lub odmowę usługi w przypadku powtarzanego lub odpowiednio wzmocnionego ataku.
Przyczyna źródłowa
Uwierzytelnienie jest egzekwowane w dalszym module obsługi importu, a nie przed middleware do obsługi przesyłania fragmentów.
Samo middleware obsługuje już wywołanie zwrotne authorize, stworzone specjalnie w celu uniemożliwienia nieautoryzowanego korzystania z funkcjonalności big-upload.
Sugerowane działania naprawcze
Wymaganie uwierzytelnienia przed przetworzeniem jakiejkolwiek operacji aposBigUpload.
Przykładowo:
- Przekazanie odpowiedniego wywołania zwrotnego
authorizedobigUploadMiddleware()na wszystkich trasach importu. - Odrzucanie nieuwierzytelnionych użytkowników przed operacjami
start,chunklubend. - Wprowadzenie rozsądnych limitów na zadeklarowaną liczbę fragmentów.
- Weryfikacja deklarowanego rozmiaru względem rzeczywiście przesłanych danych.
- Wprowadzenie limitów pamięci i częstotliwości żądań na użytkownika oraz globalnie.
- Zapewnienie, że pliki tymczasowe są usuwane w przypadku niepowodzenia dalszego przetwarzania.
- Dodanie testów regresyjnych potwierdzających, że anonimowe żądania
start,chunkiendsą odrzucane, zanim utworzony zostanie stan przesyłania lub pliki.
Istotny przeanalizowany commit:
d3ff8c9bb001be1acf7fdc3f035190250ac64b45
Podziękowania dla badacza
Kai Zhi
GitHub:
Co trzeba zrobić
Zaktualizuj pakiet apostrophe do wersji 4.33.0 lub nowszej oraz @apostrophecms/import-export do wersji 3.7.0 lub nowszej.
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/import-export | < 3.7.0 | 3.7.0 |
Odnośniki
- https://github.com/apostrophecms/apostrophe/security/advisories/GHSA-86wm-68pq-5jwq
- https://nvd.nist.gov/vuln/detail/CVE-2026-113711
- 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/apostrophe@4.33.0
- Wektor CVSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H- Słabość (CWE)
CWE-400, CWE-770- Platforma
- npm
- Paczka
apostrophe, @apostrophecms/import-export- Ujawniono
- 21.10.2026
- Aktualizacja
- 21.10.2026 16:18
Źródła i licencje · Redakcja lub tłumaczenie: DockRay. Zachowano prawa źródeł i obowiązujące licencje.
OSV / GitHub Advisory Database - GHSA-86wm-68pq-5jwq - 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
- 33
- Pierwsza → ostatnia
- 09.2020 10.2026
- Bez poprawki
- 4
- Wykorzystywana w atakach
- 0
Rozkład istotności
- Krytyczna 2
- Wysoka 9
- Średnia 18
- Niska 4
Ujawnienia w latach
- 2020: 2
- 2021: 2
- 2022: 0
- 2023: 0
- 2024: 0
- 2025: 0
- 2026: 29
-
ApostropheCMS: Nieuwierzytelnione wyczerpanie zasobów poprzez przetwarzanie aposBigUpload przed uwierzytelnieniem w @apostrophecms/import-export 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.