> For the complete documentation index, see [llms.txt](https://simon-6.gitbook.io/simoncyber/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://simon-6.gitbook.io/simoncyber/portswigger-web-academy/api-testing/lab-3.md).

# Lab 3

Intruder

**Automates sending many requests with a wordlist**

* You mark a position in the request with `§ §` markers
* It cycles through a list of payloads and fires them all automatically
* Good for: fuzzing, brute force, endpoint discovery

Example from the screenshot:

```
PUT /api/user/§update§
```

Intruder replaces `§update§` with `delete`, `add`, `edit`, `remove`... hundreds of words automatically, then shows you which ones returned interesting responses.

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

Basically, use intruder to find hidden endpoints, and almost brute force API endpoints. It uses word lists you provide or supplied database.

{% hint style="info" %}
The Param miner BApp enables you to automatically guess up to 65,536 param names per request. Param miner automatically guesses names that are relevant to the application, based on information taken from the scope. "SecLists is a built in wordlist."
{% endhint %}

### What's Mass Assignment&#x20;

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

You fill out a form with 3 fields. But the database has 10 fields for that object.

The app just takes **whatever you send** and maps it to the database — so you can fill in fields that were never on the form. App accepts more parameters than it advertises. You guess or discover hidden ones (like `isAdmin`, `discount`, `price`) and the server processes them because the framework doesn't know to ignore them.

***

**Step 1 — Look at what PATCH accepts:**

```json
PATCH /api/users/
{ "username": "wiener", "email": "wiener@example.com" }
```

Only exposes 2 fields. Looks innocent.

**Step 2 — Do a GET on the same object:**

```json
GET /api/users/123
→ { "id": 123, "name": "John Doe", "email": "...", "isAdmin": "false" }
```

The GET response reveals the *full* DB object — including fields the PATCH form never showed you.

**Step 3 — Now you know `isAdmin` exists**, so go back to your PATCH and add it:

```json
PATCH /api/users/
{ "username": "wiener", "email": "wiener@example.com", "isAdmin": true }
```

If the server is vulnerable to mass assignment → you just made yourself admin.

***

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

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

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

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

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

Yes — the GET gathers the full object structure that the server uses internally. The POST only sends what the UI was programmed to send. The gap between those two is where mass assignment lives.
