DEV Community

Cover image for From App User to Tenant Admin
Breno Vitório
Breno Vitório

Posted on

From App User to Tenant Admin

Hello there, y'all! Hope you are doing great 🤗

Today, I'm gonna be sharing with you the process of finding CVE-2022-3225. Just like the last post, what I am about to show is not complex at all, but it's really cool and similar bugs can still be found out there!

🏞️ Continuing The Journey of Securing Low Code App Builders

Right after finding the last bug on Tooljet, I decided to look for issues in similar projects, so I googled for Tooljet vs and found some software with very near concepts and goals. One of those was Budibase, and I arbitrarily pick it as a new application for testing.

One thing I like to do is to map what parts of the code can directly interact with user input. I do that just by using the app and monitoring requests with Burp or ZAP. So I got that the "immediate" logic was being handled by controllers, and then I took a look at most of them, hoping for spotting something strange happening.

Detective Pikachu

😱 Look! A Mass Assignment!

Out of all those different methods, one that got my attention was the method which updates your own user's information. Why? Well, because it clearly was doing a mass assignment!

If you don't know what it means, I explain it a little bit better here. But this pseudocode resumes what the function was looking like:

function updateSelf(request) {
  self := User::findOrFail(request.params.id)
  # ...some other logic here...
  self.update(request.body)

  return self
}
Enter fullscreen mode Exit fullscreen mode

It was picking up the entire request body and using it to update our user data 😱. This means that if we inserted valid user attributes that are not in the original request made by the browser, it would still work! So I looked for my user's object in some HTTP requests, including this specific one, and noticed some interesting attributes:

{
...
    "builder": {
        "global":true
    },
    "admin": {
        "global":true
    },
...
}
Enter fullscreen mode Exit fullscreen mode

So I decided to set this admin.global value to false, and...Boom! I was not an admin of my tenant anymore, yaaaaay! No, wait! It's not something good 😭

Luckily, when trying to set it back to true, it also worked 😅

🫠 Bringing Some Impact

Okay, but what can we do with it?

try to take over the world

As an administrator, it doesn't bring any harm to be able to change my own access levels, but this endpoint is available to any authenticated user. So I looked for the lowest access level that exists, and this is the App User. It's a user that has basically no permissions, other than being capable of running specific apps from the given tenant.

The app user also has access to a form where they can change their "display name", and this form calls the vulnerable endpoint. So I tried to change the role of my app user to admin and...it worked! 🥳

Again, okay...but what can we do with it? 🧐

After digging a little bit, I found that as an admin, I could delete all of the other accounts (including the account of the original admins), and also delete every app or change their content to something else.

In other words: with one single request, any simple app user could become capable of ruining an entire tenant.

So I reported it to Budibase, and after validating the bug, they fixed it really fast! Kudos to Budibase mantainers for being amazing! 🤩

Thank you for taking your time 🤗

Top comments (0)