#!/usr/bin/env python3 """Decision 61 (R-752) on 9202, DRILL catalog: calibre-web with a generated admin LOGIN NAME. 1 the box's template copy carries ADMIN_USER; 2 a stranger polls the public default login from the deploy press until the install hold opens (R-741's window); 3 the household's name is read the way the app page reads it (the Settings page's reveal, POST /stacks//auto-field/reveal); 4 positive controls (name + password: the login form and OPDS), `admin` + the right password refused; 5 a stranger's 40 wrong tries on `admin` at the 3/minute pace (~14 min); 6 the household logs in AT ONCE with its own name (form and OPDS); a wrong password on the real name still refused. Removed.""" import json, subprocess, threading, time import walk as w import lk APP, SUB = "calibre-web", "books" def reveal(env_var): sess = open(f"{w.SC}/sess{__import__('os').getpid()}.txt").read().strip() csrf = open(f"{w.SC}/csrf{__import__('os').getpid()}.txt").read().strip() r = subprocess.run(["curl", "-sk", "-H", w.HOSTHDR, "-H", f"Cookie: {sess}", "-H", f"X-CSRF-Token: {csrf}", "-H", "Content-Type: application/x-www-form-urlencoded", "--data", f"env_var={env_var}", f"{w.BASE}/stacks/{APP}/auto-field/reveal"], capture_output=True, text=True) try: return json.loads(r.stdout)["data"]["value"] except Exception: return "" w.login() for _ in range(12): w.sync_rescan() cp = w.guest(f"grep -c ADMIN_USER /opt/docker/stacks/{APP}/.felhom.yml").strip() if cp not in ("", "0"): break time.sleep(15) lk.p("the box's template copy names ADMIN_USER:", cp, "times") res, stop = [], threading.Event() def poll(): while not stop.is_set(): res.append((lk.now(), lk.calibre("admin", "admin123"))) time.sleep(2) t = threading.Thread(target=poll, daemon=True) t.start() lk.p("deploy:", w.deploy(APP, SUB)) for _ in range(120): time.sleep(5) if "hold OPENED" in w.guest(f"docker logs --since 20m felhom-controller 2>&1 | grep '{APP}: install hold OPENED'"): break time.sleep(5) stop.set() t.join() prev = None for ts, c in res: if c != prev: lk.p(" stranger, default login admin/admin123 ->", c) prev = c lk.p("stranger got in with the default login:", sum(1 for _, c in res if c == "ok"), "of", len(res)) lk.p(w.guest("docker logs --since 20m felhom-controller 2>&1 | grep -E 'calibre-web.*(install HOLD|hold OPENED|after_install)' | cut -c1-200").strip()) lk.p("app.yaml after_install record:", w.guest(f"grep -A3 '^after_install:' /opt/docker/stacks/{APP}/app.yaml").strip().replace("\n", " ")) name = reveal("ADMIN_USER") pw = (w.GENERATED.get(APP) or {}).get("ADMIN_PASSWORD", "") lk.p(f"the household's name (read through the page's reveal): {len(name)} characters, lowercase hex: {name.isalnum() and name == name.lower()}") lk.p("users in app.db (total, named admin):", w.guest("""cat > /tmp/cwu.py <<'PY' import sqlite3 c = sqlite3.connect('/config/app.db') print(c.execute("SELECT count(*), sum(lower(name) = 'admin') FROM user").fetchone()) PY docker cp /tmp/cwu.py calibre-web:/tmp/cwu.py && docker exec calibre-web python3 /tmp/cwu.py""").strip()) lk.p("positive — form, name + password:", lk.calibre(name, pw), "| OPDS:", lk.calibre_opds(name, pw)) lk.p("admin + the RIGHT password (the old name is gone):", lk.calibre("admin", pw)) lk.p("## a stranger: 40 wrong tries on `admin`, 3 a minute") n = 0 while n < 40: for _ in range(3): if n < 40: n += 1 r = lk.calibre("admin", f"daily-{n}") if n % 10 == 0 or r not in ("wrong",): lk.p(f" wrong try {n}: {r}") time.sleep(61) lk.p("one more stranger try on admin:", lk.calibre("admin", "one-more")) lk.p("HOUSEHOLD at once — form, own name + password:", lk.calibre(name, pw), "| OPDS:", lk.calibre_opds(name, pw)) lk.p("a wrong password on the real name:", lk.calibre(name, "wrong-real"), "| right again:", lk.calibre(name, pw)) w.remove(APP) lk.p("removed; deployed =", w.stack(APP).get("deployed"))