Podczas testów penetracyjnych aplikacji webowej wykryliśmy krytyczną podatność w mechanizmie uploadu plików, która umożliwiała zdalne wykonanie kodu (RCE – Remote Code Execution). Backend sprawdzał rozszerzenie pliku, ale nie weryfikował realnego typu i pozwalał zapisać plik w katalogu wykonywalnym. W kontrolowanym scenariuszu umożliwiało to uruchomienie kodu na serwerze aplikacji. Naprawa objęła wielowarstwową walidację typu pliku, storage poza webroot, wymuszoną konwersję oraz twardą politykę wykonywania.

Kontekst: “to tylko upload dokumentów”

Klient prowadził platformę webową z panelem klienta i modułem przesyłania dokumentów: faktury, załączniki, raporty, pliki do zgłoszeń. Funkcja banalna biznesowo, często traktowana jak hydraulika pod zlewem: ma działać i nie zawracać głowy.

Upload plików to jednak jeden z najbardziej zdradliwych elementów aplikacji. Plik to nie tylko plik. To potencjalny program w przebraniu.

Testy miały sprawdzić, czy mechanizm uploadu jest odporny na nadużycia, a nie tylko czy “przyjmuje PDF”.

Problem: walidacja po rozszerzeniu i zła lokalizacja zapisu

Mechanizm walidacji opierał się głównie o:

  • rozszerzenie pliku,
  • deklarowany MIME type z żądania,
  • prostą listę dozwolonych typów.

To brzmi sensownie, ale z punktu widzenia atakującego to jak zamek zrobiony z czekolady w ciepły dzień.

Dodatkowo przesłane pliki trafiały do katalogu dostępnego przez serwer HTTP i interpretowanego przez runtime (np. PHP / interpreter skryptów). To tworzyło warunki idealne: jeśli coś przejdzie filtr, może się wykonać.

Jak pracowaliśmy: upload pod lupą, nie pod wrażeniem

Test uploadu nie polega na wrzuceniu pliku test.pdf i odhaczeniu checkboxa. Sprawdziliśmy:

  • czy backend bada sygnaturę pliku (magic bytes),
  • czy reaguje na podwójne rozszerzenia,
  • czy konwertuje pliki, czy tylko zapisuje,
  • gdzie fizycznie trafia plik,
  • czy da się go później wywołać przez URL.

Testowaliśmy warianty mieszane: poprawne rozszerzenie + niepoprawna zawartość, poprawny MIME + inny realny typ, oraz różne formaty nazw plików.

Odkrycie: obejście filtrów i wykonanie kodu

W kontrolowanym scenariuszu udało się przesłać plik, który:

  • przechodził walidację rozszerzenia,
  • był zapisywany na serwerze,
  • był dostępny pod publicznym URL,
  • był interpretowany jako kod przez runtime.

Uproszczony, zanonimizowany mechanizm

Upload:

POST /api/v1/upload
Content-Type: multipart/form-data

file: raport.pdf.php

Aplikacja sprawdzała, czy nazwa zawiera .pdf, ale nie wymuszała, żeby była to końcówka ani nie badała sygnatury pliku. Po zapisie:

/uploads/raport.pdf.php

Wywołanie przez przeglądarkę powodowało interpretację przez interpreter skryptów. W testowym payloadzie użyliśmy bezpiecznej komendy diagnostycznej, potwierdzającej wykonanie kodu — bez destrukcyjnych działań. Nauka, nie demolka.

Ryzyko biznesowe: RCE to nie jest “średni błąd”

Remote Code Execution to liga ciężka:

  • możliwość wykonania dowolnych komend na serwerze,
  • dostęp do danych aplikacji i konfiguracji,
  • pivot do innych systemów w sieci,
  • pełne przejęcie środowiska aplikacyjnego.

W praktyce to jest scenariusz typu: z błędu w uploadzie robi się incydent infrastrukturalny. Mały formularz, duże konsekwencje. Wszechświat lubi takie ironie.

Remediacja: jak zamknęliśmy temat warstwowo

Tu nie wystarczy jeden filtr. Zastosowaliśmy zestaw zabezpieczeń, które działają razem jak śluza powietrzna.

1) Walidacja realnego typu pliku (magic bytes)
Backend sprawdza sygnaturę binarną pliku, nie tylko rozszerzenie i MIME z nagłówka.

2) Twarda lista dozwolonych typów + wymuszona konwersja
Zamiast “akceptuj i zapisz”, wprowadziliśmy model: przyjmij → zweryfikuj → przekonwertuj do bezpiecznego formatu (np. obraz → re-encode, dokument → render).

3) Storage poza webroot
Pliki nie są zapisywane w katalogu wykonywalnym ani bezpośrednio dostępnym przez HTTP. Dostęp odbywa się przez kontrolowany endpoint po autoryzacji.

4) Losowe nazwy plików i brak kontroli ścieżki przez użytkownika
Brak wpływu użytkownika na finalną nazwę i lokalizację pliku.

5) Blokada wykonywania w katalogach uploadu
Polityka serwera i runtime zabrania wykonywania skryptów w katalogu storage, nawet gdyby coś przeszło filtr.

6) Testy regresji uploadu
Dodaliśmy zestaw testów negatywnych: podwójne rozszerzenia, mieszane typy, fałszywe MIME, payloady hybrydowe.

Retesty potwierdziły, że pliki wykonywalne są blokowane, a upload działa wyłącznie dla rzeczywistych, bezpiecznych typów.

Efekt: upload przestał być punktem wejścia

Po poprawkach mechanizm uploadu stał się przewidywalny i odporny na klasyczne obejścia. Zespół dostał checklistę bezpieczeństwa dla wszystkich przyszłych funkcji przesyłania plików w systemie, co zmniejsza ryzyko powtórki przy kolejnych modułach.

To jest ten moment, w którym zwykły formularz przestaje być tylnymi drzwiami do serwera.

Jak Pentestica może pomóc

Mechanizmy uploadu, importu i załączników to jedno z najczęstszych miejsc krytycznych podatności. Testy penetracyjne powinny sprawdzać je głębiej niż tylko “czy działa”.

W Pentestica testujemy aplikacje web i API pod kątem realnych scenariuszy nadużyć: upload, RCE, deserializacja, autoryzacja, logika biznesowa. Raport zawiera nie tylko błąd, ale też wzorzec naprawy, który da się wdrożyć.

Cyberbezpieczeństwo dla firm - Pentestica

Redakcja Pentestica.pl zespół ekspertów ds. cyberbezpieczeństwa, którzy dzielą się swoją wiedzą i praktycznym doświadczeniem w zakresie testów penetracyjnych, audytów it, regulacji NIS2, MiCA, DORA i nowych technologii. Nasi autorzy to doświadczeni pentesterzy, specjaliści bezpieczeństwa IT oraz konsultanci, którzy z pasją tworzą profesjonalne artykuły, aby przybliżyć Państwu tematykę cyberbezpieczeństwa w praktyce. Znajdą tu Państwo dogłębne analizy zagrożeń, omówienia technik ataków, porady dotyczące ochrony systemów oraz praktyczne wskazówki z zakresu testów penetracyjnych i wdrożeń regulacji. Naszym celem jest dostarczanie rzetelnej i aktualnej wiedzy, która pomoże Państwu lepiej zrozumieć świat cyberbezpieczeństwa i skutecznie chronić swoje zasoby cyfrowe.