Skip to content

API‐Versioning ‐ Solutions

S1rN3tZ edited this page Apr 18, 2024 · 10 revisions

Fuzzing

First of all as we land on a 404 error at the webroot, we have to check for technologies used and try to fuzz directories. By doing this, we discover a directory named "apidocs"

fuzzing

By using the Seclist's API scpecific wordlists, we can also discover an api endpoint "/api/token" that we will talk about later.

Fuzzing2

When trying to access the api documentation, the server ask for a basic authentication.

Basic authentications aren't protected against bruteforcing so by guessing or bruteforcing the authentication, we easily discover the weak credentials (guest:guest). API2:2023 - Broken Authentication

Weak creds

Once logged in, we have access to a Swagger API documentation that details the different endpoints of the api and their usage.

doc

Now the first thing to do is simply to try all the endpoints.

By doing this, we understand that the only endpoints we have access to as an anonymous user is the public endpoints but their is nothing interesting in it.

In fact, not really, because one of the two public endpoints say that the API use a third party service that can lead to paid requests if the daily limit is exeeded.

image

Let's check if a rate limit mecanism protect against this situation. Send 26 requests to the endpoint and get the first flag.

image

If you remember, the lab name is "API-Versioning", maybe we should try decreasing the api version and see if the v1 haven't already been deactivated. So we can test the same endpoints and replace the "v2" in the url by "v1". (API9:2023 - Improper Inventory Management)

By doing this, we see that their is no authentication required to access the endpoints on the v1.

And we find the second flag by sending a GET request to the endpoint "/api/v1/confidential/missions".

flag1

By using the same technic, we can try to delete a crew member from a mission. If we check to the response of the "/api/v1/confidential/missions" endpoint, we can see that the rocket of mission with the ID 7 haven't already been launched. So it could be really impactful if we can delete crew members from it.

If we check the prerequisites of the endpoint, we know that it takes an ID (the id of the mission in the url) and a memberID which is the UUID (Universally Unique Identifier) of the crew member. It would have been almost impossible to guess such information if the first vulnerability didn't leaked it.

So we have now all the information that we need to delete a user. To do so we only have to send a DELETE request to the endpoint "/api/v1/confidential/missions/7/crew" that contain in his body the parameter "memberID" with the UUID of the member to delete as value.

flag2

Documentation

Well, for the fourth flag, we have a hint in the Swagger documentation that say us that the endpoint "/api/v2/missions/{id}/communications" contain a deprecated feature that we can be requested through a PATCH request.

Deprecated

But this request require a parameter that is hidden

Parameter Discovery

Ok, so first, let's check if the API response for the v1 is too verbose and give us information to exploit the endpoint. As the endpoint wait a json payload we can try sending something like {"test":"test"}

Error1

If we try on a mission ID where the rocket isn't launched, we get an error message saying us that the rocket isn't launched.

It means that the endpoint is not used for missions that haven't started. So we can try on a mission that have started. Let's try the mission 1.

Error2

No luck, the error is a generic code 500 for an Internal Server Error.

The API doc say that we should try fuzzing the endpoint. Let's try, for this you can use this wordlist

Intruder

403

Here we have an interesting behavior. it seems that the parameter used is the parameter named "callback". (It was also easily guessable as it is the same that is used in the missions communications data).

Exploit

Now we know that the endpoint need a callback url. So let's try to configure an URL under our control as callback for the API.

ErrorURL

A simple url pointing to our server give an error saying that the URL isn't valid. It may mean that the server use a whitelist to check the callback URL.

by default, the communications are transmitted through the internal URL "https://internal-communications.example.xyz:1234/satellite/messages".

Let's try to bypass the check with a simple trick using the character '@' to make the server validate the check while the callback will only consider that "internal-communications.example.xyz" is a username transmitted to our host.

Success

Success ! Now check your server logs and see that he received a POST request containing an unreadable message.

Callback

Decrypt

If you remember, in the missions information, some information about the communications are leaked, and the encryption key and iv of the AES encryption are a part of it.

Encryption data

So we can try decrypt the message by using this information. For this you can use the CyberChef web application.

flag3

Well done, we found a new flag !

For this flag, remember that we found an interesting api endpoint (/api/token) while fuzzing. This endpoint isn't documented in the API documentation so let's analyze it.

First, it seems to accept only POST requests.

Method

So let's check what happen if we enter a random json payload

Check

Ok so, now we now that the endpoint expect an email, if we look closely the endpoint name, we can understand that the endpoint must be used for user tokens. And we have luck because the API documentation give us a potential user email in the "Users" section.

userdoc

Let's try to do something with it.

jwt

Nice, apparently, the endpoint doesn't check for any password and give us the jwt associated with the user email.

Now let's check if we can get the user information via the /api/v2/users/me endpoint.

flag

Flag found !

Being able to account takeover is cool, but we only have one account and it have a very limited "user" role. It could be interesting to escalate privileges, for this we can try to exploit the JWT.

The server seems to have some checks as we cannot change the jwt content.

try1

"None" algorithm doesn't work.

try2

Embedded JWK, HMAC key confusion and other bypass methods as well...

But now that we know that the API already contain some weak and default credentials, maybe we can find the JWT secret.

Let's try to crack the JWT with hashcat and a specific wordlist from Seclists.

JWT_Secret

Got a hit!

Now that we have the secret, we can forge a valid JWT with the role "admin".

JWT_forgery

And check if the privesc worked with the /api/v2/users/me endpoint.

flag

Well done :)

The API documentation show that the users have the ability to upload a custom avatar image. The feature use the endpoint /api/v2/users/me/avatar to do so.

upload_doc

Thanks to this, we know that the endpoint use the following json parameters:

{
    "filetype":"string",
    "content":"string"
}

As we doesn't know more, we have to check the attended working of the endpoint.

try1

The errors seems generic and doesn't leak much information but as we know that the server is waiting for a file we can try to send a MIME type as filetype.

try2

Then we get an error saying that the server can't decode the base64. It may mean that the content need to be base64 encoded.

try3

After encoding the content, we get a success message so we have found the attended usage of the endpoint. Our goal now is to find a way to upload malicious files through it so we try to change the MIME type for a potentially dangerous one like "text/html".

try4

Unfortunately, It doesn't seems to be permitted. But what if the server does only check if the filetype is an image by verifying the start of the MIME type.

try5

Indeed, the server use the end of the MIME type to determine the file extension and generate a random file name with it but doesn't check the consistency of it leading to bypass the MIME type check and upload arbitrary file types. (The flag is in the X-Flag header)

Eighth flag (Race Condition)

An other feature needing to be authenticated is the account deletion feature. The documentation say that the feature allow to delete an account by his email but their is no check on the user sending the request.

send_link

Anyway, it isn't a direct deletion because it use a confirmation link, so we cannot exploit it as it is.

note: Having the email content in the HTTP response is only to make it easier.

So first we have to find a way to exploit it, you will probably think first about a Host Header Poisoning and it's a good idea. Let's try different injections, here is a list of headers we can use for this:

Host: evil.xyz
X-Forwarded-For: evil.xyz
X-Forwarded-Host: evil.xyz
X-Host: evil.xyz
Referrer: https://evil.xyz
Origin: https://evil.xyz

Header-poisoning

Unfortunately, no one work and even if it worked, their is few chances that a victim click on a deletion link that is not coming from himself.

An other thing that we could try is to bruteforce json parameters to find a potential hidden "test/debug" parameter like "link" or "href" but their is none.

But Now, if you look closely to the generated links generated while fuzzing, you will see that two consecutive requests generates exactly the same link.

token

It may mean that the token generation is time-based, and if it is the case, it could be possible to generate the same token for two different users meaning that it could be possible to confirm arbitrary users account deletion.

So now we have to find an other user to test our scenario and we have one in our user details.

manager

Jane Smith is the manager of John Doe whose email is john.doe@example.xyz. A little bit of guessing and we have our test email. (jane.smith@example.xyz)

We can now use the "Group Tab" feature of burp suite (or the intruder or consecutive curl requests) to generate consecutively a deletion link for our user and Jane Smith.

flag8

Clone this wiki locally