During the course of our work, Nettitude have identified a stored Cross-Site Scripting (XSS) vulnerability within the CrushFTP web interface.

CrushFTP is a file transfer server which supports multiple file transfer protocols, and provides a web interface for users to manage their files, as well as for administrators to manage and monitor the service.


Within the /WebInterface/UserManager page of the web interface, there is an option to create a new user. Although client-side sanitization of input prevents the creation of a user whose username contains special characters, the same is not true for the server-side validation of the given data. An attacker who intercepts and modifies the traffic before the username is added to the application’s backend can create a user that contains JavaScript or HTML within the username property.

As shown below, there is a list of the most visited users displayed at the top of the page.

Graphical user interface, application Description automatically generated

The list consists of <a> HTML tags that contain each username. The double-quote character is not properly sanitized inside the <a> tag allowing the insertion of JavaScript or HTML payloads within a username field, leading to cross-site scripting. In addition to this, the payload would also be executed when an attempt is made to delete the user. This is because the pop-up message that appears for confirmation does not encode usernames upon output, thus allowing crafted JavaScript or HTML payloads to be executed within the web browser.


CrushFTP stores the details of registered users within the filesystem in the users/MainUsers directory. The contents of this directory are shown below, with the users crushadmin, default, and TempAccount each having their own directory.

Text Description automatically generated

The user’s directory contains a file called user.XML, which contains the data associated with the account. This is where information such as the username, password, etc, is stored in XML format.

Text Description automatically generated

When attempting to create a user, after a request to check if the username already exists, the application performs a POST request towards the /WebInterface/function/ endpoint. The command used within the request is setUserItem which creates the user folder in the application’s backend containing the given information.

Text Description automatically generated

The text highlighted below in red is the name of the directory that will be created for the user, while the text highlighted in blue is the username that will be saved within their user.XML file. Nettitude modified this request, placing the value random_user1 within the username POST parameter and random_user2 within the username parameter in the XML data.

Text Description automatically generated

The new user then appeared within the users panel on the left hand side of the page.

From this, it was clear that the web application indexes the username by the name of the directory created for the user, and not by the username that is added in the user.XML file. Nettitude reproduced the previous steps, but this time replacing the username parameter with random_user"<img+src%3d1+onerror%3d"alert(1)">. This payload is designed to display a JavaScript alert when rendered within a web browser.

Text Description automatically generated

The application failed to validate the integrity of the data server-side, and the user’s folder was created with the payload included, as shown below.

Text Description automatically generated

After the operation was completed, the newly created user appeared within the users panel.

A picture containing table Description automatically generated

The mostVisitedLinks list was also populated with the most visited users’ profiles.

Since the username had been tampered with and no output encoding was performed prior to adding the username to the user attribute of the <a> object, the double-quote of the user attribute was escaped, and the <img> tag that was injected in the username was rendered within the page.

Given that an invalid image source was used within the payload, this meant that the onerror JavaScript event was triggered and the script executed.

Graphical user interface, application Description automatically generated

If an attempt was made to delete the user, the payload would fire again in the pop-up window that appears.

Graphical user interface, application, website Description automatically generated

Graphical user interface, application Description automatically generated

The impact of a cross-site scripting attack can vary depending on the payload used, but it can usually be exploited for theft of information such as session cookies or other sensitive data, or to conduct unauthorised actions on behalf of an affected user. In this instance it may be exploited for privilege escalation or account takeover.


This vulnerability affected CrushFTP prior to version 9.4.0_15. Any later versions are no longer affected by this vulnerability, as the vendor was informed and performed the necessary actions to remediate the issue.

Multiple parts of the source code contribute to the payload’s execution in various fields, but the main reason behind the vulnerability is the incorrect sanitization of the username as it is processed within the backend. This, can be found in the setUserItem function inside the crushftp/server/AdminControls.class file.

Graphical user interface Description automatically generated with medium confidence

No input filtering was performed on the username, so special characters entered in the username field are not removed or sanitized in any way. In addition to this, no output encoding was performed when the data was displayed within the affected page itself. Proper output encoding, in combination with a strong content security policy, should always be used to mitigate the risk of cross-site scripting.


  1. Discovery by Nettitude: 19 November 2021
  2. CVE Assigned: 19 November 2021
  3. Vendor informed: 04 March 2022
  4. Vendor fix released: 08 March 2022