E-Health Issues (3/3) - Severe Vulnerabilities in VITU
During the last year (2025), we conducted a variety of penetration tests on E-Health applications. Shockingly, they all had severe vulnerabilities. This is particularly concerning given the highly sensitive information stored and processed by these applications. This is the final entry in a series of three blog posts in which we will disclose some of the vulnerabilities we identified.
Intro
One of our clients wanted to begin using the web application VITU (Virtuelles Tumorboard) – a process-oriented information and communication platform for the health sector – in production. However, they wanted to assess its security before doing so. Hence, we conducted a web application penetration test. The results revealed multiple severe vulnerabilities, such as almost no authorization checks and multiple instances of stored cross-site scripting.
Fortunately, the vendor, MOLIT Service GmbH, responded quickly and professionally. The vulnerabilities were fixed shortly after they were disclosed.
Overview of the CVEs
A total of 7 CVEs were assigned to the most severe vulnerabilities identified. The affected versions are “v2.2.0-beta.9” and earlier.
| CVE Number | Name | Severity |
|---|---|---|
| CVE-2025-69867 | Broken Function Level Authorization | Critical |
| CVE-2026-36979 | Broken Object Level Authorization | High |
| CVE-2025-69866 | Stored Cross-Site Scripting | High |
| CVE-2025-69865 | Arbitrary File Upload | Medium |
| CVE-2025-69868 | CSV Injection | Medium |
| CVE-2026-36977 | Username Spoofing | Medium |
| CVE-2026-36978 | Server-Side Request Forgery | Low |
Remediation
It is recommended to update VITU to the latest version. All vulnerabilities have been fixed in version v2.2.0-beta.10.
CVEs in Detail
Broken Function Level Authorization
This was the most severe vulnerability. All authorization checks but two were done only client-side. Hence, by doing minor JavaScript changes or by using a HTTP proxy to modify the requests, it was possible to see or modify any data. Well, not any data, because the access to the user and group settings in the admin area was also validated on the server side. But besides that, any functionality could be accessed and used: Organizations, Settings, Super Settings, Evaluation, Audit Log, Authentication Log in the Admin area as well as all Patients, Cases and Conferences. This meant that all the sensible data could be accessed by any authenticated user and the access to the administrative settings could be used to exploit further vulnerabilities, such as stored XSS affecting the whole web application.
In order to trick the frontend and to see the web application like an administrator would, we had to modify two JavaScript functions and one return. There were two functions that checked the role of a user: hasRealmRole and hasResourceRole. Both were modified to always return true: e.hasRealmRole=function(k){return true;},e.hasResourceRole=function(k,$){return true;},. Furthermore, there was another role check (return e.meta.roles != null && !s.value.realmAccess.roles.filter(c => e.meta.roles.includes(c)).length || e.meta.modules != null&&Object.keys(a.value.modules).filter(c => a.value.modules[c]).filter(c => e.meta.modules.includes(c)).length < e.meta.module) which was replaced with a simple return false. These changes tricked the frontend into thinking that the user has all roles, including Administrator.
Figure 1 shows that the user gdata3 has all roles and is able to view the audit log in the admin area. In fact, the user only had the low privilege role “Participant” and escalated their privileges by bypassing the client-side checks.
Broken Object Level Authorization
After reporting the BOLA vulnerability, the vendor implemented server-side authorization checks. However, during the retest it was discovered that users are able to access data from other organizations, even if they should not be able to. The API calls issued by the web applications contained filters for the organizations a user belongs to. These filters could simply be removed in order to access data from all organizations.
Figure 2 shows one of the API calls containing an organization filter issued by the web application. The endpoint returns two patients.
An error was thrown, if the parameter organization.name was removed. However, when it was set to an empty value, all patients were returned. Figure 3 shows that all three patients of the test instance were returned.
This affected all Patient and Case functionalities.
Stored Cross-Site Scripting
There were multiple stored XSS vectors.
- JavaScript Protocol: URLs, which can be e.g. configured in the settings, could use the JavaScript protocol. If a user clicks on one of these URLs, the JavaScript will get executed
- SVG Files: See Arbitrary File Upload
- Matomo: In the administrative settings a Matomo JavaScript file can be specified. This JavaScript file is then included in every response. Due to the BFLA vulnerability, any user could specify a matomo URL pointing to an attacker controlled JavaScript file which gets served to any user visiting the web application. Figure 4 shows the script tag with the matomo URL that is being embedded on every page.
Arbitrary File Upload
No file upload restrictions were enforced. Hence, it was possible to upload any file (.exe, .zip, .svg, … you name it) to cases. Combined with Username Spoofing and BOLA/BFLA, any authenticated user could have uploaded malicious files to any case and spoof themself as another user. Figure 5 shows that it was possible to e.g. upload an exe because there were no restrictions in place.
CSV Injection
Admins can download CSV files containing statistics about held conferences. User controlled values, such as the name of the conference, were embedded directly into the CSV file. This could be abused to achieve Command Execution (Excel) or Data Exfiltration (Google Sheets). Figure 6 shows a payload that leads to the execution of the calculator on Windows systems, if the CSV file is opened with Excel.
Username Spoofing
It’s possible to upload files in certain functionalities as well as to post comments to cases. However, it was possible to spoof usernames and let VITU show arbitrary usernames for the comments/uploaded files. This was because the username to be shown was not taken from the session, but specified via a parameter that could be modified.
Server-Side Request Forgery
When downloading a file from VITU, the API endpoint GET /video-backend/api/vitu/fhir/fetchBinary?binaryURL=foo was used and foo was the URL of the file to be downloaded. This screams SSRF and indeed SSRF was possible. However, there were already checks in place that limit the allowed URLs to the web application’s host, hence the risk was lowered to low.
Timeline
| 2025-11-24 | Start of the 5-day penetration test |
| 2025-12-03 | Reported vulnerabilities to the vendor |
| 2025-01-27 | Conducted a retest - all vulnerability were fixed, however 3 new ones were identified |
| 2025-01-30 | Verified that 2 of the 3 new-found vulnerabilities have been fixed |
| 2025-03-11 | Verified that the last vulnerability has been fixed |