A stored cross-site scripting vulnerability, tracked as CVE-2021-45919, was identified in elFinder File Manager. The vulnerability can result in the theft of user credentials, tokens, and the ability to execute malicious JavaScript in the user's browser.
Any organization utilizing an out-of-date elFinder component on its web application could be affected. Organizations should note that elFinder can integrate into many web applications such as Django, Drupal, Laravel, Roundcube, Subrion, Symfony, Tiki Wiki, Wordpress, XOOPS, Yii & Zenphoto.
Integrations aren't limited to only those web applications, as organizations could deploy the code as they see fit. As a result, the scope of the impact of the elFinder stored XSS vulnerability is not currently known as organizations could potentially deploy it both as an authenticated or unauthenticated component. Organizations with user-permissions-based elFinder deployments or unauthenticated implementations are at a much higher risk of exploitation. So, software engineers should make a determination about the authentication requirements for their integrations.
We identified the vulnerabilities as part of individual security research, and Subrion's Content Management System's (CMS) use of elFinder led to the discovery of this CVE. This writeup identifies a cross-site scripting vulnerability in an additional elFinder version, leading to the revision of the current CVE.
Shout out to Trustwave SpiderLabs and Sakura Samurai member Higinio Ochoa who bravely volunteered to click my elFinder exploitation link multiple times while troubleshooting for this write-up. Additional hat tip to MLT, 0xFFFF member who told me that Subrion would likely be a good CMS to use for my research..
Improper neutralization of input during web page generation leads to cross-site scripting in elFinder file manager versions ≤ 2.1.31. A threat actor can store a cross-site scripting payload in an SVG file that executes upon visiting the location of the stored SVG file.
ElFinder is integrated into the Subrion demo environment. While testing Subrion, an 'Uploads Manager' extension was identified in the 'Content' tab of the 'Admin Dashboard' control panel.
We noticed various file types within the upload manager, and testing indicated that .svg files might not be securely processed. Right-clicking on any of the uploaded files allows the user to click on a button that says 'Get info' which displays the size, path, dimensions, and other elements of the file. The interesting portion was the 'Link' property which provided the path to the location within the application where the uploaded file is stored, allowing direct access to upload files. Direct access to uploaded files makes stored payloads easier to exploit.
By crafting a malicious .svg file, we intended to store a cross-site scripting payload to test the baseline level for exploitation. The following PoC code was utilized:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<script type="text/javascript">
alert("SpiderLabs");
</script>
</svg>
As executed in the first CVE proof of concept, the JavaScript alert function was used for an initial PoC test. After this code was saved into an .svg file, it was uploaded, and the link was copied by right-clicking on the file and grabbing the 'Link' field property. Navigating to the .svg upload destination resulted in a successful JavaScript alert box.
However, simply popping up an alert box cannot express the full capacity of a stored cross-site scripting vulnerability. So we created a new payload to increase the criticality of the stored cross-site scripting vulnerability and demonstrate the execution of commands on both the browser and local network.
The first requirement was to make a more intuitive payload. However, given the nature of the vulnerability, it seemed like a perfect vector of attack for a redirect to a website with embedded JavaScript that would execute a beef cross-site scripting webhook and inject into the user's browser.
When the .svg URL loads, an image is displayed with the text "Page not found, click here to return to homepage.”Taking a look at the payload that was used for this .svg file, we see that there are several various stages:
<svg viewBox="0 0 100 100" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<image width="30" height="10" x="-10" y="10" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAIQUlEQVR4nO3dPXbyOhSF4V3QpqajZATUDIA6U2AKGUWmwAjSZgipU1OnTZv+u4XwCt
[---base64 snipped for clarity---]
R2Zj6wGWzz86Y+chltZ/MNFYBl/DWsDYJTaWz8EwYmwtwOL6R9/YLN4a3gN4cHCMf0kw1bti3W0LvgfGWuJFFzN978EaviQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAJ/wE8tttQUJW4rAAAAABJRU5ErkJggg=="/>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<a xlink:href="http://172.16.111.182:8000/index.html">
<text font-size="3" font-weight="normal" fill="#000000">
<tspan x="1" y="23">
Page not found, click here to return to the homepage.
</tspan>
</text>
</a>
</g>
</svg>
At first glance, this appears to be a fairly standard .svg file However, several variables exist to make this payload something that could potentially end up with many "zombie" machines executing commands on the attacker’s behalf.
First, a base64 image is created within the .svg file:
xlink:href="data:image/png;base64,<--Snip-->
The long base64 string was pulled directly by hosting an image and copying the 'Image Data-URL'. This is accomplished by right-clicking on the image and then clicking on "Inspect.” This action will bring up the snippet of code within the browser's developer tools. Right-clicking that specific piece of code and clicking on 'Copy Image Data-URL' will provide the data to use for the xlink:href variable. In this specific instance, a “frowny-face” emoji seemed like the most appropriate representation for a 404 not found-based error.
The payload’s second component was the text-based social engineering attempt, with a redirect to the "attacker's domain":
<g stroke="none" stroke-width="1" fill="none"
fill-rule="evenodd">
<a xlink:href="http://172.16.111.182:8000/index.html">
<text
font-size="3"
font-weight="normal" fill="#000000">
<tspan x="1" y="23">
Page not found, click here to return to the homepage.
</tspan>
</text>
</a>
</g>
</svg>
Now that the threat actor staged the first portion of the attack, the social engineering attempt had to be polished to highlight the possible outcome of a threat actor determined to exploit victims further. The browser exploitation framework project (BeEF) was utilized to stage a malicious web hook that would be hosted on the attacker's server. In this instance, the HTML code for Subrion's index page was code was placed in an index.html file:
BeEF is then hosted on the same server that the malicious index.html redirects to, and the following snippet of code is then added to the body of the index.html:
At this point, the attacker has all the pieces of the puzzle to execute a successful attack. First, the attacker would host the index.html file on a seemingly legitimate server with a purchased domain that looks similar to the organization they want to exploit. Uploading the above .svg payload, gives the attacker a wide variety of options to exploit users. The threat actor could strategically place the link in a place like website forums, advertising some sort of benefit for using their "link" to sign-up. Confused users will click the 404 back message and potentially become a victim.
In reality, even though it's a stored cross-site scripting payload, an attacker would be more likely to pretext an enterprise employee. As there is far more potential benefit of achieving remote code execution on a host that is possibly connected to an organization's internal network.
An attacker could send a mass phishing email that includes a link to the stored xss payload, which is unlikely to be flagged since it's hosted on the organization's domain. Alternatively, an attacker might set out to target employees via the help desk or perform spear-phishing on high-priority targets. The possibilities are limitless, and the most dangerous part of a stored xss vulnerability is that the attacker will likely achieve exploitation of employees or users who make their way to the stored xss payload on their own.
In the following scenario, let's assume that the attacker has successfully socially engineered an employee via support chat. The attacker sends the .svg payload URL and stated that they were having trouble loading the image because the browser is asking for a plugin update. The employee sees that it's their domain name and doesn't think twice about clicking the link and interacting. The employee clicks the back button and ends up on the malicious index.html page. Using the GUI control panel for BeEF, the attacker now has JavaScript injection on the employee's browser:
The attacker can see the user’s information, including IP address, possible operating system, cookies, and in some cases, geolocation.
In an attempt to know more about the host system, a port scan is conducted via the 'Fetch Port Scanner' Network module. Port 443, 445, and 1723 are identified as open and thus potentially an attack vector.
There are many modules for passive enumeration and other possibilities of privilege escalation. However, the attacker feels confident in this interaction and quickly generates a payload to social engineer the employee into believing that the website is telling that person to update their plugins. The ability to push a fake update alert is powerful in a scenario in which a support employee is trying to help a 'user' or 'customer' fix an issue that they are having:
An exe payload was generated via 'msfvenom', although an hta stager also could have been used.
Next, the attacker starts a reverse shell handler and prepares to pretext the employee further by preparing a 'browser notification' linking to the payload that they generated:
As seen, the attacker utilizes BeEF's social engineering module labeled 'Fake Notification Bar' and pretext by having the browser popup a message stating that plugins are out-of-date and require an update. The attacker then tells the victim/employee through the support chat about the 'Notification' on the website. The conversation might continue with the attacker saying that they downloaded the plugin updater suggested through the web application, but it's not resolving the issue that they are having seeing parts of the website.
The employee states that they do not see the notification, so knowing that the employee has eyes on their bowser, the attacker executes the notification like so:
The employee now sees the plugin bar, and even if it seems weird – the fact that it appears to be coming from their own organizational domain name should increase their level of trust. This results in the employee downloading and running the attacker’s application. The attacker now has a reverse shell on the employee's host system which is joined to the organization's active directory:
The attacker runs a few basic commands to see the user context they are operating as, and the specifics of the host system. Now, the privilege escalation process can begin:
In this demonstration, a seemingly harmless cross-site scripting alert box was escalated into full-blown remote code by pairing it with a little social engineering. While the impact of cross-site scripting vulnerabilities is typically defined as theft of user credentials, execution of external code, or cookie theft, an advanced persistent threat actor with motive knows no bounds. Social engineering is not out of scope for a threat actor and cross-site scripting vulnerabilities could lead to an internal network compromise and further exploitation.