[ToC]
# What is API
:::info
:bulb: APIs (Application Programming Interfaces) enable software systems and applications to communicate and share data.
:::
# API recon
To start API testing, you first need to find out as much information about the API as possible, to discover its attack surface.
To begin, you should identify API endpoints. THese are locations where an API receives requests about a specific resource on its server. For example, consider the following `GET` request:
```
GET /api/books HTTP/1.1
Host: example.com
```
The API endpoint for this request is `api/books`. This results in an interaction with the API to retrieve a list of books from a library. Another API endpoint might be, for example, `/api/books/mystery`, which would retrieve a list of mystery books.
Once you have identified the endpoints, you need to determine how to interact with them. This enables you to construct valid HTTP requests to test the API. For example, you should find out information about the following:
- The input data the API processes, including both compulsory and optional parameters
- The types of requests the API accepts, including supported HTTP methods and media formats
- Rate limits and authentication mechaisms
# API documentation
:::info
APIs are usually documented so that developers know how to use and intergrace with them
:::
API documentation is often publicly available, particularly if the API is intended for use by external developers. If this is the case, always start your recon by reviewing the documentation.
## Discovering API documentation
Even if API documentation isn't openly available, you may still be able to access it by browsing applicaiton that use the API
To do this, you can use Burp Scanner to crawl the API. You can also browse applications manually using Burp's browser. Look for endpoints that may refer to API documentation, for example:
- `/api`
- `/swagger/index.html`
- `/openapi.json`
If you identify an endpoint for a resource, make sure to investigate the base path. For example, if you identify the resource endpoint `api/swagger/v1/users/123`, then you should investigate the following paths:
- `/api/swagger/v1`
- `/api/swagger`
- `/api`
You could also use a list of common paths to directly fuzz for documentation
### APRENTICE Lab: Exploiting an API endpoint using documetation
Try some endpoint may refer to API documentation like `/api`

I find that there is a DELETE api will help us delete an account by sending it's username

Seem like we need to login use this api

Login with wiener's credential

Then try to use DELETE api one more time

Sucess. The lab was solved

:::success
**Solved** :+1:
:::
# Interacting with API endpoints
Once you've identified API endpoints, interact with them using Burp Repeater and Burp Intruder.
## Identifying supported HTTP methods
The HTTP method specifies the action to be performed on a resource. For example:
- `GET` - Retrieves data from a resource
- `PATCH` - Applies partial changes to a resource
- `OPTIONS` - Retrieves information on the types of request methods that can be used on a resource
An API endpoint may support different HTTP methods. It's therefore important to test all potential methods when you're investigating API endpoints. This may enable you to identify additional endpoint functionality, opening up more attack surface.
For example, the endpoint `/api/tasks` may support the following methods:
- `GET /api/tasks` - Retrieves al ist of tasks
- `POST /api/tasks` - Cretes a new task
- `DELETE /api/tasks` - Deletes a task
You can use the built-in HTTP verbs list in Burp Intruder to automatically cyle throught a range of methods
## Identifying supported content types
API endpoints often expect data in a specific format. They may therefore behave differently depending on the content type of the data provided in a request. Changing the content type may enable you to:
- Trigger errors that disclose useful information
- Bypass flawed defenses
- Take advantage of differences in processing logic.
### PRACTIOTIONER Lab: Finding and exploiting an unused API endpoint
First I found an endpoint get the price of the product

Then I found out this endpoint allow using method PATCH

Base on the information that we can send json, and the json data format when we use method GET, I try to send a PATCH request with this body

Now we can see the product is "$0.00", let buy it and solve the lab

:::success
**Solved** :+1:
:::
## Fuzzing to hind hidden endpoints
Once you have identified some initial API endpoints, you can fuzz to uncover hidden endpoints. For example, consider a scenario where you have identified the following API endpoint for updating user information:
```
PUT /api/user/update
```
To identify hidden endpoints, you could use Burp Intruder to fuzz for other resources with the same structure. For example, you could fuzz the `/update` position of the path with a list of other common functions, such as `delete` and `add`
# Finding hidden parameters
## Mass assignment vulnerabilities
Mass assignment (also known as auto-binding) can inadvertently create hidden parameters. It occurs when software frameworks automatically bind request parameters to fields on an internal object. Mass assignment may therefore result in the application supporting parameters that were never intended to be processed by the developer.
For example, consider a `PATCH /api/users/request`, which enables users to update their username and email, and includes the following JSON:
```
{
"username": "wiener"
"email": "wiener@example.com"
}
```
A concurrent `GET /api/users/123` request returns the following JSON:
```
{
"id": 123,
"name": "John Doe",
"email": "john@example.com",
"isAdmin": "false"
}
```
This may indicate that the hidden `id` and `isAdmin` parameters are bound to the internal user object, alongside the updated username and email parameters.
## Testing mass assignment vulnerabilities
To test whether you can modify the enumberated `isAdmin` parameter value, add it to the `PATCH` request:
```
{
"username": "wiener",
"email": "wiener@example.com",
"isAdmin": false,
}
```
In addition, send a `PATCH` request with an invalid `isAdmin` parameter value:
```
{
"username": "wiener",
"email": "wiener@example.com",
"isAdmin": "foo",
}
```
If the application behaves differently, this may suggest that the invalid value impacts the query logic, but the valid value doesn't. This may indicate that the parameter can be successfully updated by the user.
You can then send a PATCH request with the isAdmin parameter value set to true, to try and exploit the vulnerability:
```
{
"username": "wiener",
"email": "wiener@example.com",
"isAdmin": true,
}
```
### PRACTIONER Lab: Exploiting a mass assignment vulnerability
When use function `Place order`, I see there was an endpoint `/api/checkout` with two method `GET` and `POST`

I also found an api documentation at `/api`

Then in the api documentation I found that when we send the POST request to place order, we can also so send a discount without discount_id

By sending a request with percent discount value is 100, we can buy the product with product_id = 1


:::success
**Solved** :+1:
:::
# Server-side parameter pollution
Some systems contain internal APIs that aren't directly accessible from the internet. Server-side parameter pollution occurs when a website embeds in a server-side request to an internal API without adequate encoding. This means that an attacker may be able to manipulate or inject parameters, which may enable them to, for example:
- Override existing parameters
- Modify the application behavior
- Access unauthorized data
You can test any user input for any kind of parameter pollution. For example, query parameters, form fields, headers, and URL path parameters may all be vulnerable
# Testing for server-side parameter pollution in the query string
To test for server-side parameter pollution in the query string, place query syntax charactoers like `#`, `&`, and `=` in your input and observe how the application responds.
Consider a vulnerable application that enables you to search for other users based on their username. When you search for a user, your browser makes the folowing request:
```
GET /userSearch?name=peter&back=/home
```
To retrieve user information, the server queries an internal API with the following request:
```
GET /users/search?name=peter&publicProfile=true
```
## Truncating query strings
You can use a URL-encoded `#` character to attempt to truncate the server-side request. To help you interpret the response, you could also add a string after the `#` character.
For example, you could modify the query string to the following:
```
GET /userSearch?name=peter%23foo&back=/home
```
The front-end will try to access the following URL:
```
GET /users/search?name=peter#foo&publicProfile=true
```
If you're able to truncate the server-side request, this removes the requirement for the `publicProfile` field to be set to true. You may be able to exploit this to return non-public user profiles.
## Injecting invalid parameters
You can use an URL-encoded `&` character to attempt to add a second parameter to the server-side request.
For example, you could modify the query string to the following:
```
GET /userSearch?name=peter%26foo=xyz&back=/home
```
This results in the following server-side request to the internal API:
```
GET /users/search?name=peter&foo=xyz&publicProfile=true
```
Review the response for clues about how the additional parameter is parsed. For example, if the response is unchanged this may indicate that the parameter was successfully injected but ignored by the application
To build up a more complete picture, you'll need to test further application
## Injecting valid parameters
If you're able to modify the query string, you can then attempt to add a second valid parameter to the server-side request
For example, if you've identified the `email` parameter, you could add it to the query string as follows:
```
GET /userSearch?name=peter%26email=foo&back=/home
```
This results in the following server-side request to the internal API:
```
GET /users/search?name=peter&email=foo&publicProfile=true
```
Review the response for clues about how the additional parameter is parsed
## Overriding existing parameters
To confirm whether the application is vulnerable to server-side parameter pollution, you could try to override the original parameter. Do this by injecting a second parameter with the same name.
For example, you could modify the query string to the following:
```
GET /userSearch?name=peter%26name=carlos&back=/home
```
This results in the following server-side request to the internal API:
```
GET /users/search?name=peter&name=carlos&publicProfile=true
```
The internal API interprets two `name` parameters. The impact of this depends on how the application processes the second parameter. This varies across different web technologies. For example:
- **PHP** parses the last parameter only. This would results in a user search for `carlos`
- **ASP.NET** combines both parameters. This would result in a user search for `peter,carlos`, which might result in an `Invalid username` error message
- **Node.js** express parses the first parameter only. This would result in a user search for `peter`, giving an unchanged result
If you're able to override the original parameter, you may be able to conduct an exploit. For example, you could add `name=administrator` to the request. This may enable you to log in as the administrator user.
### PRACTITIONER Lab: Exploiting server-side parameter pollution in a query string
1. In Burp's browser, trigger a password reset for the `administrator` user.
2. In **Proxy > HTTP history**, notice the `POST /forgot-password` request and the related `/static/js/forgotPassword.js` JavaScript file.

3. Right-click the `POST /forgot-password` request and select **Send to Repeater**
4. In the **Repeater** tab, resend the reqeust to confirm that the response is consistent.
5. Change the value of the `username` parameter from `administrator` to an invalid username, such as `administratorx`. Send the request. Notice that this results in an `Invalid username` error message

6. Attempt to add a second parameter-value pair to the server-side using a URL-encoded `&` character. For example, add URL-encoded `&x=y`:`username=amdinistrator%26x=y`. Send the request.

Notice that this results in an `Invalid field` error message. This suggests that the server-side application may recognize the injected field parameter.
7. Attempt to truncate the server-side query string using a URL-encoded `#` character: `username=administrator%23`. Send the request.

Notice that this results in an `Field not specified` error message. This suggests that the server-side query may include an additional parameter called `field`, which has mee removed by the `#` character.
8. Add a `field` parameter with an invalid value to the request. Truncate the query string after the added parameter-value pair. For example, add URL-encoded `&field=x#`:`username=administrator%26field=x%23`. Send the request.

Notice that this results in an `Invalid field` error message. This suggests that the server-side application may recognize the injected field parameter.
9. Brute-force the value of the `field` parameter:
- Right-click the `POST /forgot-password` request and select **Send to Intruder**
- In the **Intruder** tab, add a payload position to the value of the `field` parameter as follows: `username=administrator%26field=§x§%23`
- In **Intruder > Payloads**, click **Add from list**, Select the built-in **Server-side variable names** payload list, the start the attack.

- Review the results. Notice that the requests with the username and email payloads both return a `200` response
10. Change the value of the `field` parameter from `x#` to `email`:`username=administrator%26field=email%23` Send the request.

Notice that this returns the original response. This suggests that `email` is a valid field type.
11. In **Proxy > HTTP history**, review the `/static/js/forgotPassword.js` JavaScript file.

Notice the password reset endpoint, which refers to the `reset_token` parameter: `/forgot-password?reset_token=${resetToken}`
12. In the **Repeater** tab, change the value of the `field` parameter from `email` to `reset_token`

Notice that this returns a password reset token. Make a note of this.
13. In Burp's browser, enter the password reset endpoint in the address bar. Add your password reset token as the value of the `reset_token` parameter.

14. Set a new password
15. Log in as the `administrator` user using your password
16. Go to the **Admin panel** and delete `carlos` to solve the lab

:::success
**Solved** :+1:
:::
## Testing for server-side parameter pollution in REST paths
A RESTful API may place parater names and values in the URL paht, rather than the query string. For example, consider the following path:
```
/api/users/123
```
The URL path might be broken down as follows:
- `/api` is the root API endpoint
- `/users` represents a resource, in this case `users`
- `/123` represents a parameter, here an indentifier for the specific user
Consider an application that enables you to edit user profiles based on their username. Requests are sent to the following endpoint:
```
GET /edit_profile.php?name=peter
```
This results in the following sever-side request:
```
GET /api/private/users/peter
```
An attacker may be able to manipulate server-side URL path parameters to exploit the API. To test for this vulnerability, add path traversal sequences to modify parameters and observe how the application responds.
You could submit URL-encoded `peter/../admin` as the value of the `name` parameter:
```
GET /edit_profile.php?name=peter%2f..%2fadmin
```
This may result in the following server-side request:
```
GET /api/private/users/peter/../admin
```
If the server-side client or back-end API normalize this path, it may be resolved to `/api/private/users/admin`
### EXPERT Lab: Exploiting server-side parameter pollution in a REST URL
1. Observe that `POST /forgot-password` return JSON value --> it might be a result from an API

2. Right-click the request and select **Send to Repeater**
3. Send a variety of requests with a modified username parameter value to determine whether the input is placed in the URL path of a server-side request without escaping:
- Submit URL-encoded `administrator#` as the value of the `username` parameter

Notice that this returns an `Invalid route` error message. This suggests that the server may have placed the input in the path of a server-side request, and that the fragment has truncated some trailing data. Observe that the message also refers to an API definition
- Change the value of the username parameter to `administrator/../carlos`, then send the request

Notice that this return carlos's email. This suggests that this vulnerable to path traversal
- After a few `../` we get to this page, seem like that we've navigated outside the API root

- At this level, add some common API definition filenames to the URL path. For example, submit the following: `username=../../../../openapi.json%23`

Notice that this returns an error message, which contains the following API endpoint for finding users:
`/api/internal/v1/users/{username}/field/{field}`
Notice that this endpoint indicates that the URL path includes a parameter called `field`
**Exploit the vulnerability**
1. Update the value of the `username` parameter, using the structure of the identified endpoint. `../../../../api/internal/v1/users/administrator/field/username#` or `../../../../api/internal/v1/users/administrator/field/email#`

2. In `/static/js/forgotPassword.js` JavaScript file. Identify the password reset endpoint, which refers to the `passwordResetToken` parameter

3. Change the field parameter to `passwordResetToken`

4. Notice that this returns a password reset token. In Burp's browser, enter the password reset endpoint in the address bar. Add your password reset token as the value of the `reset_token` parameter

5. Set a new password
6. Log in as the `administrator` using your password
7. Go to the Admin panel and delete `carlos` to solve the lab

:::success
**Solved** :+1:
:::