CVE-2023-6483: Improper/missing API authentication in ADiTaaS v5.1
Key Points / Summary
- ADiTaaS version 5.1 had an API flaw that made it possible to gain system admin access to customer instances. The API was missing authentication and access was controlled via user ID in the URL. Putting in the system admin’s user ID enabled full access to all API resources.
- A wide variety of companies in various industries could have been affected. Thanks to responsible disclosure, no company suffered any cyberattack or data breach.
- The vulnerability was reported to India’s CERT-In August 22 and fully resolved by December 1, 2023. In that time, many fixes were implemented with the final fix being applied December 1.
- ID: CVE-2023-6483
- Severity: 9.1 / Critical
- Links:
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.
- 🚗 A top automaker
- 🏥 A medical company
- 🏠 A real-estate company
- 📦 A packaging/design company
- ✈️ An aviation company
- 👜 A fashion brand group
- 💉 A pharmaceutical company
- ⚒️ A mining company
- 🏭 A manufacturing company
- ❤️🩹 A personal care/healthcare company
- 💵 An insurance company
- 🧑💻 An IT services/digital transformation company
- 📈 Many others in industries like education, banking, finance, and food manufacturing
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:
- A boolean value named
IsLoginDone
is set to true. - 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.
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.
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:
- The company behind ADiTaaS is partly an Indian company.
- There is no bug bounty program for ADiTaaS, and no known security email address.
- I believed this to be CVE material and wanted CERT-In’s help getting one issued.
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:
- August 21, 2023: I send a comprehensive email to CERT-In to report the vulnerability.
- August 22, 2023: Response received from CERT-In. A case ID was issued, and they stated they will reach out to the company.
- September 1, 2023: I ask for an update and ask for assistance getting a CVE ID. They respond same-day informing me they are still coordinating with the ADiTaaS team.
- October 4, 2023: After a month I decide to check if the exploit still works. It does. I respond back with more details about the problem – the underlying API is unauthenticated and attach an annotated screenshot of the API with a missing Authorization header. They respond same-day confirming remediation action is underway, and requested I inform them if I identify new vulnerable ADiTaaS instances.
- October 25, 2023: I discovered 2 new ADiTaaS instances and respond letting them know. I also discovered the ADiTaaS team had taken steps to fix the vulnerability. They added a devtools detector and local storage encryption. This did not resolve the vulnerability and I quickly bypassed them. I let them know that I noticed these fixes and that they are insufficient.
- October 26, 2023: Response received informing me the vulnerability could no longer be reproduced on their end. This was because of the local storage encryption. I respond same-day with new reproduction steps and a video.
- October 27, 2023: Response received informing me they still could not reproduce the vulnerability. I respond same-day providing extra details to ensure success.
- October 30, 2023: Response received confirming they are coordinating with the ADiTaaS team again.
- October 31, 2023: I respond requesting that they keep me updated. I also ask how the CVE process will work.
- November 9, 2023: Response received informing me they received confirmation the vulnerability is fixed on 1 customer instance and that I should check if the fix is effective. They also request some details to kick off the CVE assignment process. I respond same-day. I discovered the ADiTaaS team added an obfuscated referrer check, which made the previous steps I provided more difficult to perform. I provide updated steps and the CVE details they requested.
- November 14, 2023: I emailed the ADiTaaS team for the first time using the email address listed on their website. I wanted 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.
- November 15, 2023: Response received from CERT-In confirming they are awaiting a response from the ADiTaaS team, and if I could provide the exact root cause of the vulnerability. I already gave details regarding the root cause on October 4, but I send a more comprehensive version of that response today.
- November 17, 2023: Response received informing me they received confirmation the vulnerability is fixed again on 1 customer instance and that I should check if the fix is effective. The obfuscated referrer check was changed in a way that made the previous workaround stop working. At this point I respond saying they are trying to fix the vulnerability in the wrong place, and I provide a new sample application. The application retrieved data from the unauthenticated APIs and displayed it in a UI. I also added checks for 401 and 403 status codes so the application could detect when the vulnerability was probably fixed. View App Image 1, View App Image 2
- November 20, 2023: Response received thanking me for the application and they will continue coordinating with the ADiTaaS team.
- November 20, 2023: I respond informing them I discovered 4 more vulnerable ADiTaaS instances.
- November 24, 2023: Response received thanking me for the update and they will continue coordinating with the ADiTaaS team.
- November 27, 2023: After much deliberation, I decide to reach out to a few of the USA-based companies affected by the vulnerability to see if they would be willing to help raise awareness of the vulnerability with the team behind ADiTaaS. At this point it has been more than 3 months and wanted to try and get this wrapped up before the end of the year.
- November 28, 2023: CERT-In responds informing me that a representative for ADiTaaS now wants to coordinate with me directly. I confirm that they can share my email address with them.
- November 29, 2023: Response received confirming they will be sharing my email address with them, and they also provided the email address of the ADiTaaS representative. They also inform me they are in the process of reserving a CVE ID. I respond same-day informing them that I have found 2 more ADiTaaS instances. I also send an email to the ADiTaaS representative. They respond same-day confirming they will try to resolve the issue by December 1. I respond back thanking them for their prompt response, and they respond back thanking me for my support.
- November 30, 2023: Response received from the ADiTaaS representative informing me the vulnerability is resolved in 3 customer instances. They share what they did to fix it and it’s everything I was hoping to hear. I respond asking how many customer instances are affected in total.
- December 1, 2023: Response received from CERT-In informing me that the ADiTaaS team let them know the vulnerability is resolved in the 3 customer instances. Response also received from the ADiTaaS representative with a nice message of gratitude confirming the fix is fully rolled out. They would also like to know how I discovered the vulnerability and how I was able to exploit it. I send them a comprehensive 83-page slide deck detailing how the vulnerability impacts various customers a few days later. I also confirmed that the vulnerability is finally properly fixed.
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!