While working on a recent customer engagement, I discovered two fascinating and somewhat weird bugs in SecurePoint’s UTM firewall solution. The first one, aka CVE-2023-22620, is rated critical for an attacker to bypass the entire authentication and gain access to the firewall’s administrative panel. Since there is an easy way to get root access from a compromised web account, this essentially means a fully root-level compromised firewall.
The second one, aka CVE-2023-22897 is a heartbleed-like bug that allows the leaking of remote memory contents and is discussed in a second blog post.
Leaking a sessionId
When authenticating against the administrative panel on port 11115 of the UTM:
Then the UTM returns a
sessionId upon a successful authentication:
So far, so good; nothing weird here, but remember that sessionId; it’ll get more interesting.
While playing around with the authentication implementation, I also tried to brute-force my way in, which yielded an exciting result. So when trying to authenticate using any other user with a wrong password, you typically expect the UTM not to return any
sessionId because this must only happen upon successful authentication. Well, it turns out that the UTM sees things differently and happily returns a sessionId:
You might recognize the sessionId here. It is the same that was returned upon the successful authentication of the admin user. While investigating this further, it seems that the
sessionId returned here belongs to the last active (authenticated) user.
So if there is no active user, then the UTM correctly returns no sessionId at all. To successfully exploit this authentication bypass, the attacker must wait for an administrator to log into the UTM.
Quite weird behavior, but there’s more to it.
However, when trying to use this leaked sessionId from a different browser, I recognized that it doesn’t work despite the fact that the sessionId is 100% the one leaked from the admin login:
While using the sessionId from the same browser that the admin also used, does work fine:
So, where’s the inconsistency here? Apparently, it must have something to do with a request header because my IP address to access the UTM didn’t change.
It took me a lot of reverse engineering efforts (yes, they’re using Fast-CGI in 2023) to determine why the leaked sessionId did not work as expected. It turns out that the UTM generates “fingerprints” based on the HTTP_USER_AGENT and REMOTE_ADDR values of the incoming request, which are thrown into an MD5 calculation:
It then fetches everything related to a given
sessionId (including the fingerprint) from its internal SQLite database:
And finally compares the calculated value from the request against the fetched one from the database. If it fails, it syslogs the message “user has valid session but invalid fingerprint, possible break-in attempt!”:
This seems difficult!?
So to be successful, the attacker who wants to break into the UTM must wait for (or trick) an administrator into logging into the UTM. This gets the attacker the sessionId of the administrator. The second factor that the attacker needs to know is the User-Agent string.
However, the User-Agent string can be easily brute-forced, and unless the administrator doesn’t use any customized/random/non-standard User-Agent string, it is even possible to narrow it down quite a bit:
- Firstly, considering that browsers tend to auto-update themselves in most enterprise environments, you could probably rule out most of the strings from old browsers.
- Secondly, firewall administrators tend NOT to administrate their firewalls using mobile browsers, so these could also be ruled out.
- Thirdly, Firefox and Chrome have the largest market share, so the administrator could have used one of them.
These three points narrow the potential list of User-Agents down quite a bit. The attacker still needs to guess the operating system of the administrator, which is often part of the User-Agent string. Still, given the overall reduction in test cases, as discussed, the attacker probably only has a couple of thousand User-Agents to try (luckily, there is no rate limit enabled by default on the LAN/internal side of things), which is a step worth taking compared to the goal of compromising an entire firewall solution.
The last thing the attacker needs to have is the same REMOTE_ADDR. This might be hard to achieve (hence the AC:H CVSS rating) because the attacker needs to either compromise the same machine (IP address) as the previously authenticated user or be lucky that the web interface sits behind a NAT’ed network; thus, everybody shares the same REMOTE_ADDR.
This generally also works across the admin and user panels. So it is also possible to leak the sessionId from a logged-in administrator on port 11115 via the user panel on port 443!