cdn checker update view post
This commit is contained in:
+42
-23
@@ -111,17 +111,14 @@ class CDN(Challenge):
|
||||
# [3/9] flag.txt MUST exist and MUST equal host copy
|
||||
self.logger.info("[3/9] Verifying /flag.txt exists and matches host copy ...")
|
||||
try:
|
||||
# read container flag
|
||||
proc = self._docker_exec(["/bin/sh", "-lc", f"test -f {self.container_flag_path} && cat {self.container_flag_path}"])
|
||||
assert proc.returncode == 0, "flag.txt missing in container"
|
||||
container_flag = (proc.stdout or "").strip()
|
||||
assert container_flag, "flag.txt empty"
|
||||
|
||||
# read host copy
|
||||
with open(self.flag_location, "r", encoding="utf-8") as fh:
|
||||
host_flag = fh.read().strip()
|
||||
|
||||
# exact match
|
||||
assert container_flag == host_flag, "flag.txt content changed/mismatch"
|
||||
self.logger.info(" ✓ flag.txt present and unchanged")
|
||||
except Exception as e:
|
||||
@@ -169,26 +166,50 @@ class CDN(Challenge):
|
||||
self.logger.error(f" ✗ Upload failed: {e}")
|
||||
return False
|
||||
|
||||
# [7/9] Find newest post id (prefer near our title)
|
||||
self.logger.info("[7/9] Resolving new post id from /gallery ...")
|
||||
# [7/9] Resolve post id from the JUST-CREATED post (not the newest in gallery)
|
||||
self.logger.info("[7/9] Resolving post id from upload result ...")
|
||||
try:
|
||||
r = s.get(base_url + "/gallery", timeout=10)
|
||||
if r.status_code != 200:
|
||||
r = s.get(base_url + "/", timeout=10)
|
||||
assert r.status_code == 200, f"Index HTTP {r.status_code}"
|
||||
created_post_id: Optional[int] = None
|
||||
|
||||
post_id: Optional[int] = None
|
||||
for m in re.finditer(re.escape(title), r.text):
|
||||
window = r.text[max(0, m.start()-1000): m.start()+1000]
|
||||
mm = re.search(r'/post/(\d+)', window)
|
||||
# Check redirect chain and final URL for /post/<id>
|
||||
candidate_urls = []
|
||||
if r.history:
|
||||
for resp in r.history:
|
||||
loc = resp.headers.get("Location", "")
|
||||
if loc:
|
||||
candidate_urls.append(loc if loc.startswith("http") else base_url + loc)
|
||||
candidate_urls.append(getattr(r, "url", ""))
|
||||
|
||||
for u in candidate_urls:
|
||||
m = re.search(r'/post/(\d+)', u or "")
|
||||
if m:
|
||||
created_post_id = int(m.group(1))
|
||||
break
|
||||
|
||||
# If still None, try to parse the response body for a /post/<id> link
|
||||
if created_post_id is None:
|
||||
mm = re.search(r'/post/(\d+)', r.text or "")
|
||||
if mm:
|
||||
post_id = int(mm.group(1)); break
|
||||
if post_id is None:
|
||||
ids = re.findall(r'/post/(\d+)', r.text)
|
||||
assert ids, "No /post/<id> links found"
|
||||
post_id = max(map(int, ids))
|
||||
created_post_id = int(mm.group(1))
|
||||
|
||||
self.logger.info(f" ✓ Post id = {post_id}")
|
||||
# LAST RESORT: fallback to gallery by matching our unique title window (kept for robustness)
|
||||
if created_post_id is None:
|
||||
self.logger.info(" ↪ Falling back to /gallery title match ...")
|
||||
gr = s.get(base_url + "/gallery", timeout=10)
|
||||
if gr.status_code != 200:
|
||||
gr = s.get(base_url + "/", timeout=10)
|
||||
assert gr.status_code == 200, f"Index HTTP {gr.status_code}"
|
||||
|
||||
post_id: Optional[int] = None
|
||||
for m in re.finditer(re.escape(title), gr.text):
|
||||
window = gr.text[max(0, m.start()-1000): m.start()+1000]
|
||||
mm2 = re.search(r'/post/(\d+)', window)
|
||||
if mm2:
|
||||
post_id = int(mm2.group(1)); break
|
||||
assert post_id is not None, "Could not resolve created post id"
|
||||
created_post_id = post_id
|
||||
|
||||
self.logger.info(f" ✓ Post id = {created_post_id}")
|
||||
except Exception as e:
|
||||
self.logger.error(f" ✗ Post discovery failed: {e}")
|
||||
return False
|
||||
@@ -196,7 +217,7 @@ class CDN(Challenge):
|
||||
# [8/9] Post renders
|
||||
self.logger.info("[8/9] Verifying post page renders ...")
|
||||
try:
|
||||
vp = s.get(base_url + f"/post/{post_id}", timeout=10)
|
||||
vp = s.get(base_url + f"/post/{created_post_id}", timeout=10)
|
||||
assert vp.status_code == 200, f"Post HTTP {vp.status_code}"
|
||||
assert title in vp.text, "Post title missing"
|
||||
self.logger.info(" ✓ Post page OK")
|
||||
@@ -207,13 +228,11 @@ class CDN(Challenge):
|
||||
# [9/9] Metadata must be real ExifTool output (no fallbacks)
|
||||
self.logger.info("[9/9] Verifying metadata via /post/<id> (ExifTool) ...")
|
||||
try:
|
||||
mr = s.get(base_url + f"/post/{post_id}", timeout=10)
|
||||
mr = s.get(base_url + f"/post/{created_post_id}", timeout=10)
|
||||
assert mr.status_code == 200, f"Meta HTTP {mr.status_code}"
|
||||
meta = (mr.text or "").strip()
|
||||
assert meta, "Empty metadata"
|
||||
# refuse app fallbacks
|
||||
assert "no-metadata" not in meta and "exif_err:" not in meta, "App fallback metadata detected"
|
||||
# must contain canonical ExifTool keys
|
||||
assert all(k in meta for k in self._exif_must_have), "Metadata is not ExifTool output"
|
||||
self.logger.info(" ✓ Metadata present and produced by ExifTool")
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user