Tuesday, 3 November 2020

From a 500 error to Django admin takeover

This bug is about a private target I was hunting. I passed all the subdomains to FFUF, a great tool written in GoLang to brute force directories. 

Since there were no interesting 200 responses against my wordlist. I started checking other responses like 302, 403, etc. 

I noticed one of the subdomains (let that be sub.vulnerable.com) gave a 500 error for the endpoint 

/api-docs/


This was interesting because when tried an endpoint /anything, it returned 404. So I was quite sure that /api-docs existed but needs more privileges or something like that...

I tried lots of methods, but nothing worked. So I just went back to test the main application. I signed up, and I had an intuition to refresh the page in the next tab, which was /api-docs/

PFFF, to my surprise, I could see the API docs now, which was a swagger UI. 



I after seeing the admin-api, I thought I had hit a goldmine. But that was not the case. None of the admin-API's were working. So I started looking at the normal API endpoints. 


Two of the endpoints were interesting:

1. /api/panel/v1/users/{id}/

Where the {id} value is an integral value. I automated the request for 1 to 100 numerical values, and I was able to fetch other user's email addresses, DOB, name, etc. by filtering all 200 responses.



 2. A similar endpoint and similar leak with search functionality

/api/panel/v1/users/?page=1&page_size=1&search=cyberboy


I reported the bug, and the team asked me if I could raise the severity. 

Challenge accepted!


I started digging the endpoint again  /api/panel/v1/users/{id}/

and notice a JSON value in response "is_staff:false"

So it is pretty easy to guess that there are different roles for the website. I wanted to know more about the roles, so I thought of looking at the admin account's privileges, and they would-be some developers of the company. It was easy to find the developers' names in public places and then pass the name to the search API and fetch their data if I get lucky.

So when I did this, one of the names worked, and I got an admin account information.

/api/panel/v1/users/?page=1&page_size=1&search=NAME_OF_A_DEV_I_KNEW


Now I have a few more interesting roles. 

"is_superuser":true

"is_staff":true

"lms_role":"super_admin"


But again, how do I access an admin account. I tried and failed. So I thought, what if I am modified to these privileges. The first thing I tried was making a POST request with the above JSON value to my own ID


POST /api/panel/v1/users/{id}/ HTTP/1.1

{
"is_superuser":true
"is_staff":true
"lms_role":"super_admin"
}

Unfortunately, a 500 error.

The next thing would be to try the PATCH method. 

PATCH /api/panel/v1/users/{id}/ HTTP/1.1

{
"is_superuser":true
"is_staff":true
"lms_role":"super_admin"
}

I got 200, okay. 

I logged into my account, and I was a staff and a superuser who could edit and modify contents. 

My curiosity did not stop so, I searched for "lms_role" turns out; it's a learning management system and had something to do with Django. So I just opened /admin. And I was greeted with welcome "Cyberboy."

Here we go.. I am the admin now :)



Mission accomplished!
I informed the team that I would like to stop here, and they agreed. 

Bounty reward 3000$












Tuesday, 18 August 2020

Escalating a GitHub leak to takeover entire organization

I was hunting on a private program. One of the common things I do is look for leaked credentials on Github. I give special attention to deleted files. Because many people are not aware that just deleting a file doesn't remove it from your repository. 

One of the YAML files caught my attention.


data:
matrixbot-username: {{ .Values.matrixbot.username | default "some_leaked_username" | b64enc }}
matrixbot-password: {{ .Values.matrixbot.password | default "some_leaked_password" | b64enc }}

Initially, I had no clue what were these passwords. So I started searching about the matrix thing.
I stumbled upon https://matrix.org and realized this is a communication client.

Matrix is an open-source project that publishes the Matrix open standard for secure, decentralized, real-time communication, and its Apache-licensed reference implementations.

So, here's the plan. Find the client and try to log in and see if I was lucky enough. I found a web-based client at https://app.element.io/#/login attempted to log in, but it didn't work.

I almost gave up, but then I noticed that there is an option to have a self-hosted server. And it somehow summed up my theory that a DevOps person might have used it for some automation, so there was a YAML file, and hence it should be self-hosted.

Now I had to find the hosted server. And the most obvious step was to look for subdomains.
There were multiple subdomains, and, one that caught my attention was matrix.thewebsite.com

Visting the URL showed this, which was very convincing I am at the right place.



So, I visited https://app.element.io/#/login again. Added the custom server. Entered the leaked username and password. To my surprise, I was in.



As I logged in, I understood the creds were of a matrix bot. There was a hell lot of information like Grafana passwords, server logs, private keys, etc. in channel description itself. However, I immediately logged out and filed a report.

Reward 4000$





Takeaway for hackers:
- Do not give up or conclude too early. Try and research more.
- Try to escalate leaks but with caution. Do not go very deep.

Takeaway for companies:
- Purge the files just deleting a file doesn't work.
- Implement 2FA for all accounts.



Timeline:
7th Aug: Filed the report.
7th Aug: Bug was fixed by removing the file as well as refreshing the credentials. Additionally, 2FA was implemented.
11th Aug: 4000$ bounty reward.