LimeSurvey downgrade attack

Photo by Lisa Fotios from Pexels

So in my quest to quench my thirst for tinkering with things I stumbled on LimeSurvey and decided to take a look at it and see what could be done. To explain what LimeSurvey is the below text has been taken from their page.

LimeSurvey is the tool to use for your online surveys.
Whether you are conducting simple questionnaires with just a couple of questions or advanced assessments with conditionals and quota management, LimeSurvey has got you covered.
LimeSurvey is 100% open source and will always be transparently developed.
We can help you reach your goals.

I registered for a trial account and set everything up on my server that I use for my reviews. The first thing that I found was that there was brute force protection in place but that it could be bypassed by manipulating the Client-IP or X-Forwarded-For headers. This was discovered in version 3.21.1+191210 but is likely to be present in earlier versions as well. It was patched in version 4.1.0+200128 in this commit. It has been assigned CVE-2019–19804. Now of course this can still become a problem depending on how LimeSurvey is setup. Since the code now uses $_SERVER[‘REMOTE_ADDR’] to fetch the IP of the client, it could spell trouble if the application is behind a load balancer or reverse proxy that will not correctly report the client IP. So there’s some room for configuration that should be considered here.

But the main finding that I’ve been playing around with, is a downgrade attack. LimeSurvey has an updater called ComfortUpdate. It’s simply an automatic update tool that an administrator can use to easily update the installation to the latest version. It requires a license key, which I received via my trial account. As you go through the steps of the update, the last step will tell the LimeSurvey installation what version should be downloaded. According to the person I’ve been in contact with at LimeSurvey this is a problem on the ComfortUpdate server, and thus no changes had to be made to the code.

So the last step of the update downloads the update file and installs it, using this request below. I removed the datasupdateinfo to make it a bit more readable.

The version I was on was 191210, and in the request above I have captured the request that the browser sent, and changed the version number to an older version; namely 190918. And the server then responded that the “update” had been successful. The software had been downgraded, which would let an attacker reintroduce previously patched vulnerabilities. For instance, there are older versions that have critical remote code execution flaws that could now be exploited again on a fully patched version of LimeSurvey.

On the 21st of January I got a message from a developer at LimeSurvey stating that the issue had been fixed and that downgrading was no longer possible. As mentioned before he also said that this required no code change. He asked for my address as he wanted to send me a gift as thanks. Exciting! About a week or so later this arrived in the mail. Lovely gesture 💖, and I do like my tea.

But… I still felt like I wanted to verify their fix plus I didn’t feel completely satisfied yet so I wanted to tinker even more with this. I asked nicely if I could get an extension to my license to test their solution, which they gave me. And so I started messing with it again, first testing the same thing to make sure they actually fixed it; which they appeared to have done. One thing that was interesting, and yet another finding was that the ComfortUpdate server had an information disclosure problem. I discovered it when I started looking at the responses that the LimeSurvey got from the update server when it was making faulty requests due to me playing around with the requests to the updater. They display very detailed error messages when failing to find the update file.

The detailed error message came complete with code, full paths to the affected files and so on.
Further down it also included session information and version numbers of the web server and framework.

Another thing to note was that the server supports TLS, but the requests were made in clear text. When capturing the requests from LimeSurvey to the update server (which resulted in the above error message) it was all done in clear text.

I was considering writing a proof-of-concept that intercepted the update file and replaced it with a malicious one, but I think that would be a waste of time to be honest as the problem here should be apparent.

Now, at this point I had been sending quite a few requests to the updater. In fact, I had exhausted my allowed amount of updates (20) for my extended license, and thus I was stopped in my tracks and had to ask for another extension so that I could continue. I felt like I was on to something and so I really wanted to continue. My license key however, had been affected in an interesting way. When I logged in to check my license and how many updates I had left, it said -4 🤔. I reported this at the same time as I asked for an extension and didn’t put much more energy into it. I did a few quick tests just to test if I could affect the number even more or get more access keys even when I wasn’t supposed to be able to. It’s a little bug for sure but it’s hard to say if it could be exploited for anything more than getting a few more requests through than intended.

Luckily I was granted 50 new updates to my license so that I could finish up my testing. At this point I had a pretty clear theory, which was that the server generated the update files on the go and removed them a bit later. It also did not allow the “tobuild” to be lower than “frombuild”, which I assume is the fix made to stop me from downgrading in the first place. So my idea at this point was to pretend to have an older version and “upgrade” to a slightly newer one that had a vulnerability I could use.

When a certain request was made during the update process, the zip file containing the update was generated if it did not already exist, and I had discovered that I could inject parameters into the request that LimeSurvey sent to the update server, effectively changing the outcome of said zip file. By injecting my little payload during the first request of the update process, the ComfortUpdater would be kind enough to bring said injection with it the whole way during the update and thus “infect” all the other requests as well, which made the attack even more successful than I first thought it would be. The below request is the first one where the initial injection takes place. I use Burp Suite Pro for this to intercept the request and simply change the “destinationbuild” parameter with my injected parameters.

So the actual injection here is this:

What happens in the background is that the parameters get put into the request that is sent to the update server. The resulting update URL for the above request looks like this:

This request will be successful and return a valid access key which the application will then use for the rest of the update process. As I mentioned before, the injection is automatically taken along for the ride during the entire update process. The last request that downloads and installs the update zip file looks like this (I removed the datasupdateinfo part because it’s huge):

So, before the update the admin dashboard looked like this (take note of the version down in the right corner).

And after, it looked like this.

Supposedly the new downgraded version has a Remote Code Execution vulnerability that could now be used to gain further access to the system. The downgrade isn’t a perfect attack though. If you downgrade too far you will end up destroying the installation and wont be able to do anything. Yes I tried to see how far down the versions I could go and ended up having to set everything up again.

The vulnerability has been tested on version 2.05+140125, 3.21.1+191210, and 4.1.3+200213. According to my contact at LimeSurvey the fix was made server side on their ComfortUpdater so all versions of LimeSurvey should be fixed. Due to limited time for me to look at this I haven’t had the time to attempt to bypass their fix a third time, but maybe I will try it again in the future ☺.

But for now, that is all.

I program, hack, and write odd stories. I currently work for an IT-security company called Defensify.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store