SecurePwn Part 2: Leaking Remote Memory Contents (CVE-2023-22897)

While my last finding affecting SecurePoint’s UTM was quite interesting already, I was hit by a really hard OpenSSL Heartbleed flashback with this one.

The following exploit works against both the admin portal on port 11115 as well as the user portal on port 443. Since the admin portal might be in a different VLAN, I’m going to demonstrate how to leak memory contents by (ab)using the user portal this time.

Requirements for Successful Exploitation

To exploit this memory disclosure vulnerability, you need to be able to establish an authenticated session with the device (aka, you need credentials). It is totally sufficient to have a low-privileged account on the user portal. The previously important User-Agent and REMOTE_ADDR requirements are not relevant for this exploit to work.

The sessionId must have never been used before – so only the authentication request and nothing further must have happened with it. If the sessionId has been used in any other authenticated request, the exploit won’t work anymore. This turns this bug into an authenticated vulnerability since if you authenticate using a browser, the sessionId is immediately “used” after the login command in different JSON requests.

Leaking Memory Contents

As initially mentioned, the requirement to be successful is an active but unused session on any of the two available portals, i.e. on the user portal:

While fuzzing around the format of the HTTP request, I noticed that any request subsequent to the authentication request (even an empty one) returns some seemingly unreadable content in the sessionid attribute:

Considering that most parts of the UTM are written in C/C++ (Fast-CGI), this immediately rang a lot of alarm bells on my side. When having a look into the hex view of the contents, you could notice that this unreadable string translates to the hex value of 0x556efbf5aba0.

Doesn’t this look like a memory address? When attaching IDA Pro to the relevant process on the device, you can see that it roughly matches the address range of the remote process around the do_authenticate function:

Cool. This by itself means that we have an information leak here that could be useful in terms of i.e. ASLR bypasses. Let’s see what else we could leak using BurpSuite’s intruder:

Yay. Environment variables.

Root-Cause Analysis

I was quite interested in finding the root cause for this bug, and since I love Reverse Engineering and almost all of the UTM is written in C/C++, I decided to bindiff the patched version of the UTM (v12.2.5.1) with the vulnerable version (v12.2.5), and it turns out that we’re dealing with an uninitialized variable here.

The fixed version (on the right) introduced a call to _sp_io_set_sessionid() with its argument set to 0 quite early in the call hierarchy of the spcig.cgi process:

When having a look at sp_io_set_sessionid(), you quickly see that all it does is set a fixed variable to the value of its argument:

This variable is later used in the json_send_response() method responsible for returning the JSON object:

So it appears that json_send_response() was initially referencing an uninitialized variable, which led to the leak of random memory contents.

Good catch 🙂

Vendor Response

I’ve responsibly coordinated both vulnerabilities with the vendor SecurePoint and notified them about both issues on 5th January 2023. They did an amazing job acknowledging the vulnerability and providing a fix within a single business day. I barely see (hardware) vendors reacting so fast. Well done!