Black Week z sekurakiem! Tniemy ceny nawet o 80%!
Od niewinnego snippetu do RCE – podatność XSS w Open WebUI
Open WebUI to otwartoźródłowa, samodzielnie hostowana platforma AI. Można korzystać z niej na własnym serwerze, ale również lokalnie na urządzeniu. Obsługuje różne interfejsy LLM, takie jak Ollama i API kompatybilne z OpenAI.
TLDR:
- W Open WebUI odkryto podatność XSS (CVE-2025-64495) w funkcji zapisywania promptów.
- Nieprawidłowo sanityzowany HTML pozwalał atakującemu osadzić złośliwy kod, wykonywany po użyciu komendy /.
- XSS mógł prowadzić do odczytania niektórych tokenów JWT, a nawet RCE przez modułowi Functions.
- Wymagane były odpowiednie uprawnienia i włączona opcja Rich Text u ofiary.
W październiku 2025 badacz zgłosił podatność XSS występującą w aplikacji. 21 października została załatana, a 7 listopada udostępniono dokumentację na GitHub. Otrzymała ona numer CVE-2025-64495.
Problematyczna okazała się funkcja zapisywania własnych promptów (snippetów), która umożliwiała wstawianie sformatowanego tekstu. Taka treść była wyświetlana w formacie HTML bez sanityzacji. Każdy użytkownik posiadający uprawnienia do tworzenia promptów może więc umieścić tam złośliwy payload, który mogą uruchomić inni użytkownicy.
Zapisane w ten sposób prompty są dostępne w oknie czatu jako “komendy” po wpisaniu znaku /. W ramach jednej instancji aplikacji (działa ona w modelu self-hosted) taki skrót może być używany przez wielu użytkowników.
Kontrolowany przez użytkownika kod HTML z treści prompta jest przypisywany do zmiennej tempDiv jako innerHTML bez odpowiedniej sanityzacji. Co prawda część znaków jest ograniczona przez metodę parse(), ale nie sanityzuje ona w bezpieczny sposób treści – wskazuje na to dokumentacja biblioteki Marked:

Badacz przedstawił pełny Proof-of-Concept przeprowadzenia przykładowego ataku. Podstawowymi wymaganiami do jego powodzenia jest posiadanie konta użytkownika na danej instancji oraz włączenie opcji “Insert prompt as Rich Text” w ustawieniach aplikacji (domyślnie jest ona wyłączona).

Gdy atakujący zdefiniuje prompt ze złośliwym payloadem XSS, wystarczy że dowolny z użytkowników użyje go w wysyłanej w oknie czatu wiadomości za pomocą komendy /

Dla pokazanego payloadu rezultatem będzie wyświetlenie alertu w przeglądarce użytkownika, ale w tym miejscu może zostać wyświetlona dowolna zawartość w HTML oraz wykonany dowolny kod JavaScript zdefiniowane przez atakującego.
Podatność XSS w tym przypadku nie umożliwia bezpośredniego przejęcia sesji innego użytkownika, pod warunkiem, że używa standardowego loginu i hasła (cookie z tokenem JWT posiada atrybut HttpOnly, więc nie jest dostępne z poziomu JavaScript). Inaczej jest w przypadku uwierzytelniania za pomocą zewnętrznych aplikacji (OAuth), np. Google, GitHub czy firmowa usługa SSO – tam token JWT jest już możliwy do odczytania na frontendzie.

Podatność można było także wykorzystać do zdalnego wykonania kodu (RCE). W Open WebUI istnieje bowiem moduł “Functions”, który umożliwia administratorowi instancji wykonywanie kodu Pythona na serwerze, na którym hostowana jest aplikacja.
Moduł ten dostępny jest przez API, które – co prawda wymaga uwierzytelnienia i odpowiednich uprawnień – ale przyjmie przecież żądanie wykonane wewnątrz aplikacji. Takie żądanie bez problemu można wykonać z poziomu kodu JavaScript:

Parametr credentials z wartością include powoduje, że żądanie będzie tak samo uwierzytelnione, jak gdyby wykonywał je “oficjalny” kod na frontendzie aplikacji. Przeglądarka zalogowanego użytkownika dołączy do niego cookies właściwe dla domeny aplikacji, bo złośliwy kod pojawi się na tej samej oryginalnej stronie.
Nie jest to jednak tak proste, ponieważ wspomniana już metoda marked.parse, neutralizuje część znaków (w tym cudzysłowy). Badacz znalazł jednak sposób na obejście, konstruując payload z użyciem wartości dziesiętnych (przy użyciu funkcji String.fromCodePoint).

Efektem wywołania złośliwego prompta przez administratora instancji jest uzyskanie przez atakującego dostępu (reverse shell) do serwera, na którym hostowana jest aplikacja:

Użytkownik uruchamiający złośliwy prompt (o dowolnej nazwie ustawionej przez atakującego) mógł pewnych przypadkach narazić się na przejęcie tokenu JWT. Gdy jednak prompt został uruchomiony przez administratora, atakujący mógł wykonać dowolną komendę na serwerze.
Taka podatność daje atakującemu wiele możliwości, na szczęście w przypadku Open WebUI wykorzystanie ich nie było takie proste. Domyślnie użytkownicy nie mogą tworzyć własnych promptów, (potrzebne jest uprawnienie USER_PERMISSIONS_WORKSPACE_PROMPTS_ACCESS). Nie mają też włączonego formatowania (Rich Text) dla promptów. Atakujący musiałby więc mieć wskazane uprawnienia, a ofiara musiałaby uprzednio włączyć formatowanie w ustawieniach.
Dodatkowo warto zauważyć, że Open WebUI działa w modelu self-hosted, a więc skala potencjalnego ataku byłaby mocno ograniczona (tylko do użytkowników danej instancji i tylko na instancjach, gdzie administratorzy umożliwili użytkownikom tworzenie współdzielonych promptów).
Administratorom polecamy upewnić się, że ich instancje działają na załatanej wersji (od 0.6.35) – a także na bieżąco dbać o aktualizacje. Dobrą praktyką będzie też ograniczanie uprawnień użytkowników tylko do tych, których faktycznie potrzebują, zwłaszcza że w przypadku opisywanej podatności takie działanie mogło uniemożliwić atak.
Źródło: github.com
~Tymoteusz Jóźwiak
