Powrót do bloga

CVE-2026-XXXXX — Persistent XSS w Zextras Carbonio WebMail — funkcja Print

4 sierpnia 2026 Grzegorz Tworek 7 min czytania

Jak podczas testu penetracyjnego infrastruktury odkryłem podatność Persistent XSS w funkcji drukowania wiadomości Zextras Carbonio WebMail — nazwy uczestników korespondencji trafiają do szablonu wydruku bez escapowania, a okno wydruku nie ma nagłówków CSP.

Persistent XSS w Zextras Carbonio WebMail — funkcja Print

Persistent Cross-Site Scripting w funkcji Print aplikacji Zextras Carbonio WebMail (carbonio-mails-ui)

Zextras Carbonio to open-source'owa platforma do współpracy i poczty e-mail (e-mail, kalendarz, pliki, wideokonferencje), rozwijana jako alternatywa dla Zimbry i wdrażana m.in. w administracji publicznej oraz przedsiębiorstwach. Komponent carbonio-mails-ui odpowiada za webowy interfejs poczty.

Kontekst odkrycia

Podatność zidentyfikowałem pierwotnie podczas autoryzowanego testu penetracyjnego infrastruktury klienta korzystającego ze starszej, komercyjnej wersji Carbonio. Aby potwierdzić problem na czystym, publicznie dostępnym środowisku, odtworzyłem go następnie na świeżej instalacji Carbonio Community Edition pobranej bezpośrednio ze strony producenta (carbonio-mails-ui v1.31.4, carbonio-appserver 4.4.4, Ubuntu 24.04 LTS).

Oznacza to, że problem dotyczy zarówno edycji Community, jak i wersji komercyjnych — nie tylko najnowszego wydania. Zgłoszenie przekazałem do zespołu bezpieczeństwa Zextras w ramach responsible disclosure.

Szczegóły podatności

CVE ID CVE-2026-XXXXX — w trakcie przydzielania (MITRE CNA-LR)
Typ CWE-79: Stored (Persistent) Cross-Site Scripting
Produkt Zextras Carbonio WebMail (carbonio-mails-ui)
Testowana wersja v1.31.4 (Carbonio CE) oraz wcześniejsze wersje komercyjne
Komponent Funkcja Print (podgląd wydruku wiadomości)
Wektor ataku Sieciowy (dostarczenie przez e-mail)
Interakcja użytkownika Wymagana (jedno kliknięcie: Print)
CVSS 3.1 8.1 HIGH
Wektor CVSS 3.1 AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N
Status Naprawione przez producenta w Carbonio 26.03.0

Analiza techniczna

Przyczyna źródłowa

Funkcja Print buduje stronę HTML zawierającą metadane wiadomości. Nazwy wyświetlane uczestników korespondencji (fullName dla pól From, To, CC, BCC, Reply-To) są interpolowane bezpośrednio do szablonu wydruku bez kodowania encji HTML. Co znamienne — pole Subject w tym samym szablonie jest poprawnie escapowane funkcją _.escape() z biblioteki lodash. To wskazuje, że deweloperzy byli świadomi ryzyka injection, ale nie zastosowali tej samej ochrony do pól z nazwami uczestników.

Dodatkowo okno wydruku otwierane jest przez window.open("","_blank"), co tworzy dokument about:blank renderowany przez document.write() — bez żadnych nagłówków odpowiedzi HTTP, a więc bez Content-Security-Policy. Brak CSP oznacza nieograniczone wykonanie wstrzykniętego kodu JavaScript.

Kluczowa obserwacja: selektywne escapowanie to częsty antywzorzec — wystarczy, że jedno pole w szablonie zostanie pominięte, by cały mechanizm ochrony przestał działać. Kodowanie wyjścia (output encoding) musi być stosowane konsekwentnie do każdej wartości pochodzącej od użytkownika, niezależnie od tego, jak „niewinne" wydaje się dane pole.

Payload

"<img src=x onerror=alert(document.domain)>" <[email protected]>

Payload umieszczany jest w nazwie wyświetlanej nadawcy (From display name). W normalnym widoku wiadomości jest bezpiecznie wyświetlany jako tekst — dopiero użycie funkcji Print powoduje jego wykonanie w kontekście uwierzytelnionej sesji ofiary.

Zextras Carbonio Print XSS PoC — alert wyswietlajacy document.domain w oknie wydruku

Proof of Concept — okno wydruku renderuje payload z pola From. Alert wyświetla document.domain, potwierdzając wykonanie JavaScript w origin aplikacji Carbonio

Kroki reprodukcji

  1. Zainstaluj Carbonio CE (testowano na Ubuntu 24.04, carbonio-mails-ui v1.31.4)
  2. Wyślij do użytkownika Carbonio wiadomość z payloadem XSS w nazwie wyświetlanej nadawcy (pole From)
  3. Zaloguj się do Carbonio WebMail jako odbiorca
  4. Otwórz otrzymaną wiadomość
  5. Wybierz menu akcji (…) i kliknij „Print"
  6. Otwiera się nowe okno z podglądem wydruku
  7. Payload JavaScript wykonuje sięalert(document.domain) potwierdza wykonanie kodu

PoC (Python)

import smtplib from email.mime.text import MIMEText from email.utils import formataddr msg = MIMEText('<p>Please print this message.</p>', 'html') msg['From'] = formataddr(('<img src=x onerror=alert(document.domain)>', '[email protected]')) msg['To'] = 'victim@carbonio-instance' msg['Subject'] = 'Stored XSS via Print' with smtplib.SMTP('localhost', 25) as s: s.sendmail('[email protected]', ['victim@carbonio-instance'], msg.as_string())

Wpływ (Impact)

Ciasteczka sesyjne są chronione flagą HttpOnly i nie da się ich odczytać przez document.cookie. Jednak payload wykonuje się w tym samym origin co aplikacja Carbonio — przeglądarka automatycznie dołącza ciasteczka do żądań same-origin (fetch, XMLHttpRequest), dając atakującemu pełny dostęp do Carbonio SOAP API bez znajomości wartości ciasteczek.

Odczyt korespondencji

Odczyt wszystkich wiadomości ofiary przez SearchRequest / GetMsgRequest — pełny dostęp do skrzynki.

Wysyłka jako ofiara

Wysyłanie wiadomości w imieniu ofiary (SendMsgRequest) oraz modyfikacja ustawień konta.

Ciche przechwytywanie poczty

Utworzenie reguł przekierowania (forwarding) w celu niewidocznej eksfiltracji całej przychodzącej korespondencji.

Propagacja i lateral movement

Rozprzestrzenienie ataku na kontakty (zachowanie robaka) oraz dostęp do modułów Files, Contacts i Calendar współdzielących origin.

Sugerowana naprawa

Rekomendacja przekazana producentowi:

  • Escapowanie encji HTML nazw wyświetlanych uczestników w szablonie wydruku — tą samą funkcją _.escape() (lodash), która jest już stosowana do pola Subject.
  • Dodanie nagłówka / meta tagu Content-Security-Policy do szablonu HTML wydruku, aby blokować wykonanie inline-skryptów jako zabezpieczenie defense-in-depth.

Oś czasu (Disclosure Timeline)

Data Zdarzenie
2026-03-16 Odkrycie podatności i reprodukcja na Carbonio CE v1.31.4
2026-03-17 Zgłoszenie do zespołu bezpieczeństwa Zextras ([email protected]) z pełnym raportem, PoC i screenshotami
2026-03 Potwierdzenie podatności przez Zextras; poprawka w przygotowaniu (deklarowany termin ~60 dni)
2026-07-28 Wydanie poprawki przez producenta — Carbonio 26.03.0 (changelog: „Stored XSS in Print Email Feature", z podziękowaniem dla Grzegorz Tworek (sec4check))
2026-08 Wniosek o przydzielenie numeru CVE (MITRE CNA-LR)

Wnioski

1. Output encoding musi być konsekwentne

Poprawne escapowanie jednego pola (Subject), a pominięcie innych (nazwy uczestników) w tym samym szablonie to klasyczny błąd. Każda wartość pochodząca od użytkownika wymaga kodowania wyjścia — bez wyjątków.

2. Nietypowe konteksty renderowania są równie ważne

Funkcja „Print" wydaje się drugorzędna, ale renderuje dane użytkownika w oknie about:blank pozbawionym CSP. Podczas pentestingu warto testować wszystkie ścieżki wyświetlania danych — nie tylko główny widok aplikacji.

3. Pola „metadanych" bywają wektorem ataku

Nazwa wyświetlana nadawcy jest w pełni kontrolowana przez atakującego i trafia do wielu widoków. To idealny kandydat na stored XSS, jeśli choć jeden z tych widoków pomija sanityzację.

Referencje

Szukasz podatności w swojej aplikacji?

Profesjonalne testy penetracyjne aplikacji webowych, API i infrastruktury. Identyfikuję podatności zanim zrobią to atakujący — od prostych XSS po złożone chain attacks.

Umów bezpłatną konsultację
Powrót do bloga