API
as discovered previously, a virtual host is hosting a webhook api endpoint at http://webhooks-api-beta.cybermonday.htb/webhooks/fda96d32-e8c8-4301-8fb3-c821a316cf77
A webhook is a user-defined HTTP callback mechanism that enables one system to send real-time data to another system when a specific event occurs. It facilitates the automatic exchange of information between applications or services by triggering predefined actions when events like updates, creations, or deletions occur. Webhooks eliminate the need for continuous polling and provide a more efficient and responsive way to communicate data changes. They are commonly used in various contexts, including API integrations, notifications, and automation workflows.
The additional virtual host information has been appended to the
/etc/hosts
file
The endpoint doesn’t seem to be available, but I will check the webroot
Sending a GET request to the webroot returns a JSON data with various pieces of information, particularly about API routes and their methods and parameters.
It looks like a description of different routes and their associated details in a web API.
The supported features are;
- registration;
/auth/register
- login;
/auth/login
- webhooks;
/webhooks
- webhooks creation;
/webhooks/create
- webhooks deletion;
/webhooks/delete:uuid
- webhooks post;
/webhooks/:uuid
- createLogFile; UNKNOWN
registration
┌──(kali㉿kali)-[/usr/…/seclists/seclists/Discovery/Web-Content]
└─$ curl -X POST http://webhooks-api-beta.cybermonday.htb/auth/register -H "Content-Type: application/json" -d '{"username": "apiuser", "password": "qwe123"}'
{"status":"success","message":"success"}
Testing out the /auth/register
API endpoint with the username, apiuser
, and password, qwe123
It seems to be successful based on the returned data
Not sure where this credential gets registered to
login
┌──(kali㉿kali)-[/usr/…/seclists/seclists/Discovery/Web-Content]
└─$ curl -x post http://webhooks-api-beta.cybermonday.htb/auth/login -H "Content-Type: application/json" -d '{"username": "apiuser", "password": "qwe123"}'
{"status":"success","message":{"x-access-token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwidXNlcm5hbWUiOiJhcGl1c2VyIiwicm9sZSI6InVzZXIifQ.cmh44nhZ-7yjOkacgLB5QOXmks1p50VxqZh_1Yn-VxzUxj64XdtjtZDsQRDxpCTXfnGi2yZ6Fw3xP9DGoY1p75-aJDhlXp0hO7AMb2I87TmDaXUs8kpwaP-akqbCLmSa1tHAFA7ZDz8aX1i-axBcBHdUSgBa1ddGHWkQbp-PiyZ3XwZyS52Pjg-OKbp2ZlFe8y1RyCagolLbro3yv1ghPA_Gpb7Wm1YDOcgD75uD1R2BTtiMc_S03tUy2Kdcv0LVNV4iqYXi6PUQPP5ZKNqbRIlZatdStXQdq5JPeEveoSCV5UfE6SHEigyUTmp1a29gsglCMD7xmFCtWAetKBY1Lg"}}
Testing the /auth/login
API endpoint also succeeded and x-access-token
is given
The token appears to be the JWT(JSON Web Token) as it’s composed of 3 sections separated by dot (.
)
i can confirm that by using an online tool; jwt.io
it indeed is a jwt signed with rs256
another notable point is that the
id
parameter is set to 2
, which indicates that there is an existing user ("id":1
)
webhooks
┌──(kali㉿kali)-[~/archive/htb/labs/cybermonday]
└─$ curl http://webhooks-api-beta.cybermonday.htb/webhooks -H "x-access-token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwidXNlcm5hbWUiOiJhcGl1c2VyIiwicm9sZSI6InVzZXIifQ.cmh44nhZ-7yjOkacgLB5QOXmks1p50VxqZh_1Yn-VxzUxj64XdtjtZDsQRDxpCTXfnGi2yZ6Fw3xP9DGoY1p75-aJDhlXp0hO7AMb2I87TmDaXUs8kpwaP-akqbCLmSa1tHAFA7ZDz8aX1i-axBcBHdUSgBa1ddGHWkQbp-PiyZ3XwZyS52Pjg-OKbp2ZlFe8y1RyCagolLbro3yv1ghPA_Gpb7Wm1YDOcgD75uD1R2BTtiMc_S03tUy2Kdcv0LVNV4iqYXi6PUQPP5ZKNqbRIlZatdStXQdq5JPeEveoSCV5UfE6SHEigyUTmp1a29gsglCMD7xmFCtWAetKBY1Lg"
{"status":"success","message":[{"id":1,"uuid":"fda96d32-e8c8-4301-8fb3-c821a316cf77","name":"tests","description":"webhook for tests","action":"createLogFile"}]}
The regular GET request to the /webhooks
endpoint seems to list the available webhooks
This reveals the uuid of the unknown feature; createLogFile
webhooks creation
┌──(kali㉿kali)-[~/archive/htb/labs/cybermonday]
└─$ curl -x post http://webhooks-api-beta.cybermonday.htb/webhooks/create -H "x-access-token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwidXNlcm5hbWUiOiJhcGl1c2VyIiwicm9sZSI6InVzZXIifQ.cmh44nhZ-7yjOkacgLB5QOXmks1p50VxqZh_1Yn-VxzUxj64XdtjtZDsQRDxpCTXfnGi2yZ6Fw3xP9DGoY1p75-aJDhlXp0hO7AMb2I87TmDaXUs8kpwaP-akqbCLmSa1tHAFA7ZDz8aX1i-axBcBHdUSgBa1ddGHWkQbp-PiyZ3XwZyS52Pjg-OKbp2ZlFe8y1RyCagolLbro3yv1ghPA_Gpb7Wm1YDOcgD75uD1R2BTtiMc_S03tUy2Kdcv0LVNV4iqYXi6PUQPP5ZKNqbRIlZatdStXQdq5JPeEveoSCV5UfE6SHEigyUTmp1a29gsglCMD7xmFCtWAetKBY1Lg" -H "Content-Type: application/json" -d '{"name": test", "description": "testing", "action": "someTest"}'
{"status":"error","message":"Unauthorized"}
Attempting to create an arbitrary webhook with the newly created credential fails due to the privileges issue
createLogFile
┌──(kali㉿kali)-[~/archive/htb/labs/cybermonday]
└─$ curl -X POST http://webhooks-api-beta.cybermonday.htb/webhooks/fda96d32-e8c8-4301-8fb3-c821a316cf77 -H "x-access-token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwidXNlcm5hbWUiOiJhcGl1c2VyIiwicm9sZSI6InVzZXIifQ.cmh44nhZ-7yjOkacgLB5QOXmks1p50VxqZh_1Yn-VxzUxj64XdtjtZDsQRDxpCTXfnGi2yZ6Fw3xP9DGoY1p75-aJDhlXp0hO7AMb2I87TmDaXUs8kpwaP-akqbCLmSa1tHAFA7ZDz8aX1i-axBcBHdUSgBa1ddGHWkQbp-PiyZ3XwZyS52Pjg-OKbp2ZlFe8y1RyCagolLbro3yv1ghPA_Gpb7Wm1YDOcgD75uD1R2BTtiMc_S03tUy2Kdcv0LVNV4iqYXi6PUQPP5ZKNqbRIlZatdStXQdq5JPeEveoSCV5UfE6SHEigyUTmp1a29gsglCMD7xmFCtWAetKBY1Lg" -H "Content-Type: application/json" -d '{"url":"blah"}'
{"status":"error","message":"\"log_name\" not defined"}
The returned data shows that the log_name
parameter is missing
I will supply the required parameter and try again
┌──(kali㉿kali)-[~/archive/htb/labs/cybermonday]
└─$ curl -X POST http://webhooks-api-beta.cybermonday.htb/webhooks/fda96d32-e8c8-4301-8fb3-c821a316cf77 -H "x-access-token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwidXNlcm5hbWUiOiJhcGl1c2VyIiwicm9sZSI6InVzZXIifQ.cmh44nhZ-7yjOkacgLB5QOXmks1p50VxqZh_1Yn-VxzUxj64XdtjtZDsQRDxpCTXfnGi2yZ6Fw3xP9DGoY1p75-aJDhlXp0hO7AMb2I87TmDaXUs8kpwaP-akqbCLmSa1tHAFA7ZDz8aX1i-axBcBHdUSgBa1ddGHWkQbp-PiyZ3XwZyS52Pjg-OKbp2ZlFe8y1RyCagolLbro3yv1ghPA_Gpb7Wm1YDOcgD75uD1R2BTtiMc_S03tUy2Kdcv0LVNV4iqYXi6PUQPP5ZKNqbRIlZatdStXQdq5JPeEveoSCV5UfE6SHEigyUTmp1a29gsglCMD7xmFCtWAetKBY1Lg" -H "Content-Type: application/json" -d '{"log_name":"blah"}'
{"status":"error","message":"\"log_content\" not defined"}
This time, the error shows that the log_content
parameter is missing
same thing.
┌──(kali㉿kali)-[~/archive/htb/labs/cybermonday]
└─$ curl -X POST http://webhooks-api-beta.cybermonday.htb/webhooks/fda96d32-e8c8-4301-8fb3-c821a316cf77 -H "x-access-token: eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpZCI6MiwidXNlcm5hbWUiOiJhcGl1c2VyIiwicm9sZSI6InVzZXIifQ.cmh44nhZ-7yjOkacgLB5QOXmks1p50VxqZh_1Yn-VxzUxj64XdtjtZDsQRDxpCTXfnGi2yZ6Fw3xP9DGoY1p75-aJDhlXp0hO7AMb2I87TmDaXUs8kpwaP-akqbCLmSa1tHAFA7ZDz8aX1i-axBcBHdUSgBa1ddGHWkQbp-PiyZ3XwZyS52Pjg-OKbp2ZlFe8y1RyCagolLbro3yv1ghPA_Gpb7Wm1YDOcgD75uD1R2BTtiMc_S03tUy2Kdcv0LVNV4iqYXi6PUQPP5ZKNqbRIlZatdStXQdq5JPeEveoSCV5UfE6SHEigyUTmp1a29gsglCMD7xmFCtWAetKBY1Lg" -H "Content-Type: application/json" -d '{"log_name": "blah", "log_content": "some content here and there"}'
{"status":"success","message":"Log created"}
The purpose of the feature is still unclear, It went through
Fuzzing
┌──(kali㉿kali)-[~/archive/htb/labs/cybermonday]
└─$ ffuf -c -w /usr/share/wordlists/seclists/discovery/web-content/combined_words.txt -u http://webhooks-api-beta.cybermonday.htb/FUZZ -ic
________________________________________________
:: Method : GET
:: URL : http://webhooks-api-beta.cybermonday.htb/FUZZ
:: Wordlist : FUZZ: /usr/share/wordlists/seclists/Discovery/Web-Content/combined_words.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________
[status: 200, Size: 602, Words: 104, Lines: 21, Duration: 103ms]
* fuzz: .htaccess
[status: 200, Size: 447, Words: 7, Lines: 11, Duration: 216ms]
* fuzz: jwks.json
:: Progress: [128338/128338] :: Job [1/1] :: 63 req/sec :: Duration: [0:26:59] :: Errors: 0 ::
ffuf found 2 files; .htaccess
and jwks.json
.htaccess
┌──(kali㉿kali)-[/usr/…/seclists/seclists/Discovery/Web-Content]
└─$ curl http://webhooks-api-beta.cybermonday.htb/.htaccess
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
Not much going on with the .htaccess
file here
jwks.json
┌──(kali㉿kali)-[/usr/…/seclists/seclists/Discovery/Web-Content]
└─$ curl http://webhooks-api-beta.cybermonday.htb/jwks.json
{
"keys": [
{
"kty": "RSA",
"use": "sig",
"alg": "RS256",
"n": "pvezvAKCOgxwsiyV6PRJfGMul-WBYorwFIWudWKkGejMx3onUSlM8OA3PjmhFNCP_8jJ7WA2gDa8oP3N2J8zFyadnrt2Xe59FdcLXTPxbbfFC0aTGkDIOPZYJ8kR0cly0fiZiZbg4VLswYsh3Sn797IlIYr6Wqfc6ZPn1nsEhOrwO-qSD4Q24FVYeUxsn7pJ0oOWHPD-qtC5q3BR2M_SxBrxXh9vqcNBB3ZRRA0H0FDdV6Lp_8wJY7RB8eMREgSe48r3k7GlEcCLwbsyCyhngysgHsq6yJYM82BL7V8Qln42yij1BM7fCu19M1EZwR5eJ2Hg31ZsK5uShbITbRh16w",
"e": "AQAB"
}
]
}
however, the jwks.json
file is a lot more important as it is the private key of the rs256 algorithm used here for JWT
Knowing this would allow me to forge a JWT to impersonate other users