Files
ALPHA-TRAIN2/check_tiktak.sh
T
bobiqqandClaude Opus 5 12b1d02f39 check_tiktak.sh: не зависеть от раскладки каталогов
На vulnbox сервис лежит в ./tiktak, в репе -- в ./services/tiktak, и скрипт
падал на поиске тестового видео ещё до первой проверки.

- каталог сервиса ищется сам (./tiktak, ./services/tiktak, ., рядом со
  скриптом), либо задаётся через TIKTAK_DIR
- тестовый webm: с диска -> скачать с живого сервиса (/feed -> /watch/N ->
  ссылка на .webm, публичное видео отдаёт её без авторизации) -> ffmpeg на
  хосте -> ffmpeg в контейнере
- бомба для проверки DoS-защиты тоже генерится в контейнере, если на хосте
  нет ffmpeg

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 12:36:31 +03:00

180 lines
9.2 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Smoke-test для tiktak. Запускать НА VULNBOX, из любого каталога.
# ./check_tiktak.sh -> проверяет 127.0.0.1:5000
# ./check_tiktak.sh 10.10.10.3 -> проверяет бокс по сети
# TIKTAK_DIR=~/tiktak ./check_tiktak.sh -> если каталог не нашёлся сам
#
# Каталог сервиса ищется сам: ./tiktak, ./services/tiktak, ., рядом со скриптом.
# Тестовое видео берётся с диска, иначе скачивается с самого сервиса, иначе
# генерится ffmpeg на хосте или в контейнере -- нужен хотя бы один источник.
#
# Повторяет сценарий чекера (register -> create -> watch -> vtt -> share по
# токену) и отдельно проверяет, что патчи действительно в задеплоенном билде.
set -uo pipefail
HOST="${1:-127.0.0.1}"
BASE="http://${HOST}:5000"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
PASS=0; FAIL=0
ok() { printf ' \033[32mOK\033[0m %s\n' "$1"; PASS=$((PASS+1)); }
bad() { printf ' \033[31mFAIL\033[0m %s\n' "$1"; FAIL=$((FAIL+1)); }
info() { printf '\n\033[1m%s\033[0m\n' "$1"; }
req() { curl -sS -m 10 "$@"; }
# ---------- где лежит сервис ----------
# Раскладка отличается: на vulnbox это ./tiktak, в репе ./services/tiktak.
# Переопределить можно через TIKTAK_DIR=/path ./check_tiktak.sh
SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SVC=""
for cand in "${TIKTAK_DIR:-}" \
"./tiktak" "./services/tiktak" "." \
"$SELF_DIR/tiktak" "$SELF_DIR/services/tiktak" "$SELF_DIR"; do
[ -n "$cand" ] || continue
if [ -f "$cand/docker-compose.yml" ] && [ -d "$cand/public" ]; then
SVC="$(cd "$cand" && pwd)"; break
fi
done
[ -n "$SVC" ] && echo "каталог сервиса: $SVC" || echo "каталог сервиса не найден (не критично, нужен только для видео и бомбы)"
dc() { [ -n "$SVC" ] && docker compose -f "$SVC/docker-compose.yml" "$@"; }
# ---------- тестовый webm ----------
# 1) уже загруженный файл 2) скачать с живого сервиса 3) ffmpeg на хосте
# 4) ffmpeg внутри контейнера
VIDEO="$TMP/clip.webm"
if [ -n "$SVC" ] && ls "$SVC"/public/video/*.webm >/dev/null 2>&1; then
cp "$(ls -S "$SVC"/public/video/*.webm | tail -1)" "$VIDEO"
echo "видео: взял с диска"
fi
if [ ! -s "$VIDEO" ]; then
# публичное видео отдаёт ссылку на .webm прямо в /watch без авторизации
for vid in $(req "$BASE/feed" | grep -o '/watch/[0-9]*' | grep -o '[0-9]*' | head -15); do
src=$(req "$BASE/watch/$vid" | grep -o 'public/video/[A-Za-z0-9-]*\.webm' | head -1)
[ -n "$src" ] || continue
req -o "$VIDEO" "$BASE/$src" && [ -s "$VIDEO" ] && { echo "видео: скачал с сервиса (/watch/$vid)"; break; }
done
fi
if [ ! -s "$VIDEO" ] && command -v ffmpeg >/dev/null 2>&1; then
ffmpeg -y -v error -f lavfi -i testsrc=size=320x240:rate=5 -t 1 -c:v libvpx "$VIDEO" </dev/null 2>/dev/null \
&& echo "видео: сгенерил ffmpeg"
fi
if [ ! -s "$VIDEO" ] && [ -n "$SVC" ]; then
dc exec -T tiktak ffmpeg -v error -f lavfi -i testsrc=size=320x240:rate=5 -t 1 \
-c:v libvpx -f webm - > "$VIDEO" 2>/dev/null && [ -s "$VIDEO" ] \
&& echo "видео: сгенерил ffmpeg в контейнере"
fi
if [ ! -s "$VIDEO" ]; then
echo
echo "не смог получить тестовый webm. Варианты:"
echo " TIKTAK_DIR=/path/to/tiktak $0 $HOST"
echo " либо положи любой .webm в <сервис>/public/video/"
exit 1
fi
echo "тестовое видео: $(wc -c < "$VIDEO") байт"
# ---------- 1. живость ----------
info "1. сервис отвечает"
code=$(req -o /dev/null -w '%{http_code}' "$BASE/") || true
[ "$code" = "302" ] && ok "GET / -> 302" || bad "GET / -> ${code:-нет ответа} (ждали 302)"
code=$(req -o /dev/null -w '%{http_code}' "$BASE/feed")
[ "$code" = "200" ] && ok "GET /feed -> 200" || bad "GET /feed -> $code"
# ---------- 2. регистрация ----------
info "2. регистрация и сессия"
U1="chk_$RANDOM$RANDOM"; J1="$TMP/j1"
HDR=$(req -D - -o /dev/null -c "$J1" -X POST "$BASE/register" -d "login=$U1&password=pw123456")
grep -q 'Location: /home' <<<"$HDR" && ok "register -> 302 /home" || bad "register не дал редирект на /home"
if grep -qi 'set-cookie:.*httponly' <<<"$HDR"; then
ok "куки с HttpOnly — ПАТЧИ В БИЛДЕ"
else
bad "куки БЕЗ HttpOnly — на боксе СТАРЫЙ билд, деплой не доехал"
fi
code=$(req -o /dev/null -w '%{http_code}' -b "$J1" "$BASE/home")
[ "$code" = "200" ] && ok "GET /home -> 200" || bad "GET /home -> $code"
# ---------- 3. публичное видео ----------
info "3. публичное видео: create -> watch -> vtt"
SUB="checker-canary-$RANDOM"
LOC=$(req -o /dev/null -w '%{redirect_url}' -b "$J1" -X POST "$BASE/create" \
-F "description=smoke" -F "subtitles=$SUB" -F "video=@$VIDEO;type=video/webm")
VID="${LOC##*/}"
if [[ "$VID" =~ ^[0-9]+$ ]]; then ok "create -> /watch/$VID"; else bad "create не создал видео (redirect='$LOC')"; VID=""; fi
if [ -n "$VID" ]; then
body=$(req -b "$J1" "$BASE/watch/$VID")
grep -q 'smoke' <<<"$body" && ok "watch отдаёт description" || bad "watch без description"
vtt=$(req -b "$J1" "$BASE/vtt/?id=$VID")
grep -q 'WEBVTT' <<<"$vtt" && grep -q "$SUB" <<<"$vtt" && ok "vtt отдаёт субтитры" || bad "vtt не отдал субтитры"
fi
# ---------- 4. приватное видео и шаринг ----------
info "4. приватное видео: home -> token -> access -> watch"
PSUB="private-canary-$RANDOM"
LOC=$(req -o /dev/null -w '%{redirect_url}' -b "$J1" -X POST "$BASE/create" \
-F "description=secret" -F "subtitles=$PSUB" -F "private=on" -F "video=@$VIDEO;type=video/webm")
PVID="${LOC##*/}"
if [[ "$PVID" =~ ^[0-9]+$ ]]; then ok "create private -> /watch/$PVID"; else bad "приватное видео не создалось"; PVID=""; fi
if [ -n "$PVID" ]; then
TOKEN=$(req -b "$J1" "$BASE/home" | grep -A0 'Share Token' | sed -n 's/.*Share Token: *\([A-Za-z0-9]\{30\}\).*/\1/p' | head -1)
[ -n "$TOKEN" ] && ok "токен на /home: $TOKEN" || bad "на /home нет Share Token"
U2="chk2_$RANDOM$RANDOM"; J2="$TMP/j2"
req -o /dev/null -c "$J2" -X POST "$BASE/register" -d "login=$U2&password=pw123456"
code=$(req -o /dev/null -w '%{http_code}' -b "$J2" "$BASE/watch/$PVID")
[ "$code" = "403" ] && ok "чужой без токена -> 403" || bad "чужой без токена -> $code (ждали 403)"
if [ -n "$TOKEN" ]; then
LOC=$(req -o /dev/null -w '%{redirect_url}' -b "$J2" -c "$J2" -X POST "$BASE/access" \
-d "videoID=$PVID&token=$TOKEN")
if [[ "$LOC" == */watch/$PVID ]]; then
ok "access по токену -> /watch/$PVID"
grep -q 'secret' <<<"$(req -b "$J2" "$BASE/watch/$PVID")" && ok "шаринг работает" || bad "после access watch пустой"
else
bad "access отверг валидный токен (redirect='$LOC') — ЧЕКЕР СЛОМАЕТСЯ"
fi
fi
fi
# ---------- 5. патчи ----------
info "5. закрыты ли дыры"
for p in "./$VID" "x/../$VID" "/$VID" "../../etc/passwd"; do
code=$(req -o /dev/null -w '%{http_code}' -G "$BASE/vtt/" --data-urlencode "id=$p")
[ "$code" = "404" ] && ok "LFI '$p' -> 404" || bad "LFI '$p' -> $code (дыра ОТКРЫТА)"
done
if [ -n "$PVID" ]; then
code=$(req -o /dev/null -w '%{http_code}' "$BASE/public/static/preview_${PVID}.png")
[ "$code" = "404" ] && ok "резкое превью приватного -> 404" || bad "резкое превью отдаётся ($code)"
code=$(req -o /dev/null -w '%{http_code}' "$BASE/public/static/preview_${PVID}_blured.png")
[ "$code" = "200" ] && ok "размытое превью на месте" || bad "размытое превью -> $code (сломает фид)"
fi
# ---------- 6. бомба ----------
info "6. decompression bomb"
BOMB="$TMP/bomb.webm"
if command -v ffmpeg >/dev/null 2>&1; then
ffmpeg -y -v error -f lavfi -i color=c=black:s=8192x8192:d=1 -c:v libvpx "$BOMB" </dev/null 2>/dev/null
elif [ -n "$SVC" ]; then
dc exec -T tiktak ffmpeg -v error -f lavfi -i color=c=black:s=8192x8192:d=1 \
-c:v libvpx -f webm - > "$BOMB" 2>/dev/null
fi
if [ -s "$BOMB" ]; then
t0=$(date +%s)
code=$(req -o /dev/null -w '%{http_code}' -b "$J1" -X POST "$BASE/create" \
-F "description=b" -F "subtitles=b" -F "video=@$BOMB;type=video/webm")
dt=$(( $(date +%s) - t0 ))
[ "$code" = "422" ] && ok "бомба 8192x8192 отбита за ${dt}s" || bad "бомба -> $code за ${dt}s (ждали 422)"
else
echo " -- пропуск: не смог сгенерить бомбу (нет ffmpeg ни на хосте, ни в контейнере)"
fi
# ---------- итог ----------
info "ИТОГ: $PASS ok, $FAIL fail"
[ "$FAIL" -eq 0 ] || exit 1