CVE-2023-6483: Improper/missing API authentication in ADiTaaS v5.1

Eaton

Key Points / Summary

After the publication of my Honda writeup back in June, I wanted to continue the momentum with automaker hacking so I once again started searching for new automakers to target. In the time I spent looking over the summer, I was successful in uncovering many interesting vulnerabilities, but one of them stood out because the vulnerability had impacts beyond the automaker I had targeted. An IT service desk website I discovered on one of the automaker’s subdomains turned out to be a SaaS platform used by many other companies. This is the story of CVE-2023-6483, an API authentication flaw that made it possible to bypass the login system of ADiTaaS and how responsible disclosure helped avert a potentially disastrous leak of various companies’ data.

In a nutshell, ADiTaaS is an all-in-one SaaS platform geared towards enterprise service management (ESM). Without The buzzwords, it’s basically an IT/support ticket platform that also handles HR, cybersecurity, and much more. Here is a graphic from their website that gives an overview:

On the technical side, the software is an Angular-based frontend with a .NET-based backend. It is sold as a cloud solution but can also be installed by customers to be used on-prem.

Affected Companies/Industries

A wide variety of companies in various industries could have been affected. The companies are primarily located in the US and India.

For more information, you can review the public case studies on the ADiTaaS website.

The login bypass

When searching for vulnerabilities online, I always look for React or Angular websites. When I find one, it’s exciting because there is a good chance there is some API flaw inside waiting to be exploited. This is because all the Angular code/logic is run client-side, and this includes API calls. If you look at the Angular code that the browser downloads, you can usually find all the APIs that are used. This information is extremely valuable to those doing security research because you can determine how the APIs work and test them for common security flaws. It is common to find missing/broken API authentication in Angular websites because some developers believe that client-side restrictions are enough.

When you load an ADiTaaS website, it presents you with a loading screen. That is usually an indicator to me that a lot of JavaScript code is being downloaded, and that the website may be using Angular or React. Right-clicking and viewing source in the browser confirmed it was an Angular app, and so I began to dig into the code.

I found that after a successful login, 2 important things happen in the browser’s local storage:

  1. A boolean value named IsLoginDone is set to true.
  2. A string value named ObjLoginData is set to a JSON string containing logged in user information.

Those 2 values are used in various places to check if the login was done and provide an easy way to access the user information.

By reviewing other parts of the application that used ObjLoginData, I was able to determine what values should go inside. The only value that really mattered was the userId. I just guessed and put in a value of 1 to see what effect that would have. I constructed the JSON and then put it into local storage:

Once that was done, reloading the page was enough to get into the dashboard with system admin privileges!

Why the login bypass worked

The login bypass was so effective because the underlying API was unauthenticated. In a secure application, the authentication token returned from a successful login is sent via the Authorization header in an HTTP request. In this case, the header was omitted entirely. The only access control mechanism was the user ID query param in the URL. It turns out the user associated with ID 1 is the system admin, which had full control over everything.

Note the missing Authorization header.

In most other cases, these types of login bypasses will result in empty dashboards or a barrage of 401/403 error popups due to the missing authorization.

Exploring the impact

I initially believed the system was developed in-house by the automaker, but after seeing many mentions of “ADiTaaS” and slogans like “Conquering Complexity”, it prompted me to search online for more information and that is when I realized I had actually broken into a SaaS platform created by an external company. Through creative searching, I managed to uncover many other domains where ADiTaaS was used, and the same exploit worked on all of them. The impact suddenly grew from an isolated incident with a single company to a larger one affecting many more.

With system admin access to customer data, it was possible to see things like plaintext login details, employee/HR personal information, and IT support tickets.

One of the most interesting finds was the way Microsoft corporate account credentials were handled. ADiTaaS customers enter these credentials during setup, and they are used to send/receive emails on the customer’s domain. The password is not shown in the ADiTaaS UI after the initial setup, but it was possible to see an encrypted version in the email manager’s API response. This is an excellent example of OWASP API3:2023 Broken Object Property Level Authorization.

The password was base64 encoded, but decoding did not yield a valid password. Investigating the JavaScript code again revealed that passwords were encrypted using AES. The key and IV were also there, so it was possible to simply run the password through an AES decryption tool to get the plaintext.

With the password in hand, it was possible to log into a customer’s Microsoft corporate cloud.

The lesson here is to exercise special care when dealing with passwords. This is another case where “rolling your own crypto” has unfortunately resulted in weak/breakable encryption. However, the primary issue was that the API returned the password. If it didn’t do that, there would not have been an issue.

A cat and mouse game

As you will see in the timeline at the end of this post, many fixes/countermeasures were applied by the ADiTaaS team in the months leading up to the full, proper fix. It is worth noting these so others will know that any protections implemented client-side can ultimately be bypassed if someone is determined enough.

1. Browser devtools blocking

The first countermeasure applied was a devtools detector and blocker. What this means is that shortly after you open the browser’s devtools, you would get redirected to an API route that returned text telling you to close devtools and go back. This made it annoying to insert the necessary local storage values because you get redirected to the API domain before you get to take action on the domain hosting the ADiTaaS frontend. To stop this from happening, I set up Chrome Overrides and made a modification to the devtools detector to simply push the check to be done far into the future. By default, it was set to run every 600ms, so I added a bunch of 0s to that number and that effectively killed the detection mechanism:

2. Local storage encryption

Since the PoC I provided involved modifying local storage, the ADiTaaS team decided to encrypt it. This meant that putting in plaintext JSON no longer worked. It needed to be encrypted now. The encryption and decryption worked by overriding the local storage API and adding a layer of AES crypto. This was easy to get around by simply setting a breakpoint in the code at a point where it was possible to call the new localStorage.setItem function with the original plaintext JSON. I let their code do all the heavy lifting and there was no need to reverse engineer the encryption.

A breakpoint is set when getting the local storage item. At that point I call localStorage.setItem in the console and then let the code continue.

3. Obfuscated referrer check

The next countermeasure the ADiTaaS team added was one that took a little longer to figure out. I originally thought the vulnerability was fixed because after doing the local storage trick and pasting a dashboard URL in the address bar, I would get redirected to the login screen and the local storage would get wiped out. After an hour or so I discovered that they added a new block of code into a different JavaScript file:

The code was obviously written to be indecipherable, so I knew they were trying to hide something. After spending a lot of time debugging it, I went online to see if there was any way to deobfuscate the code. It didn’t take long to find a website that was 100% effective:

The code works by checking that there is a valid HTTP Referer header when navigating to a page other than the signin page and a survey page. When I pasted the direct dashboard URL in the address bar, there would be no referer, and thus this check would fail.

The workaround was to just remove all this code using Chrome Overrides and the website started working again.

4. Admin auth guard

In Angular there is a concept of route guards that developers can implement to restrict access to specific pages. For example, if a non-admin user tries to go to an admin-only page, a route guard can stop this from happening and show a message to the user that they are not allowed to access the page. Unfortunately, many developers solely rely on this client-side check while the underlying API is more than willing to still give you the admin-only data if you ask for it.

The ADiTaaS team added a new API that checks if the user accessing the page is allowed to access it. They also slimmed down the system admin user’s roles so this check would actually fail for that user when accessing several critical pages. However, this check was completely bypassed by just inserting return true at the top:

This is the final countermeasure the ADiTaaS team added, just 1 day before finally adding the Authorization header to API calls.

Timeline

Summary: The vulnerability was initially reported through the Indian Computer Emergency Response Team (CERT-In) on August 21, 2023, because:

After ~3 months of back-and-forth with them, I sent an email to the address on the ADiTaaS website on November 14, 2023, to ensure no details regarding the severity of the vulnerability were getting lost in translation. I received no response, and later learned my email ended up in spam. After not receiving a response, I contacted a few of the USA-based companies affected by the vulnerability on November 27, 2023, to see if they would be willing to help raise awareness of the vulnerability with the team behind ADiTaaS. Shortly after that, contact was established and the vulnerability was fully fixed a few days later on December 1, 2023.

Full timeline:

Everything after December 1 is continued back-and-forth between me, CERT-In, and ADiTaaS representatives to work out the details of the CVE and disclosure.

Special thanks to the Indian Computer Emergency Response Team (CERT-In) for working with me on this disclosure and getting the CVE issued.

It is no exaggeration when I say that thanks to the time I spent working on this research project, the infrastructure of some of the biggest companies in the world had been saved from cyberattacks and data exfiltration. To all API developers: make sure your authentication is correct, and certainly never forget about it!

Subscribe to new posts

Get an email notification every time something new is published.
📧