()
| 484 | |
| 485 | |
| 486 | def run_ctf() -> int: |
| 487 | print(BANNER) |
| 488 | |
| 489 | log("INFO", "Starting CTF challenge", gates=len(GATES)) |
| 490 | log("INFO", f"Retry interval: {RETRY_INTERVAL}s between attempts") |
| 491 | log( |
| 492 | "INFO", |
| 493 | "Tip: open the TUI now if you haven't -> openshell term", |
| 494 | ) |
| 495 | print() |
| 496 | |
| 497 | completed = 0 |
| 498 | |
| 499 | # Gate 1: single HTTPS endpoint |
| 500 | if not run_gate(GATES[0]): |
| 501 | return 1 |
| 502 | completed += 1 |
| 503 | |
| 504 | # Gate 2: HTTP endpoint (python) |
| 505 | if not run_gate(GATES[1]): |
| 506 | return 1 |
| 507 | completed += 1 |
| 508 | |
| 509 | # Gate 3: same endpoint via curl (per-binary granularity) |
| 510 | if not run_gate(GATES[2]): |
| 511 | return 1 |
| 512 | completed += 1 |
| 513 | |
| 514 | # Gates 4-6: concurrent |
| 515 | completed += run_gates_concurrent(GATES[3:6]) |
| 516 | |
| 517 | # Gate 7: internal IP endpoint (allowed_ips SSRF override) |
| 518 | if not run_gate(GATES[6]): |
| 519 | return 1 |
| 520 | completed += 1 |
| 521 | |
| 522 | # Done |
| 523 | if completed >= len(GATES): |
| 524 | print(VICTORY) |
| 525 | log("INFO", "CTF complete", gates_passed=f"{completed}/{len(GATES)}") |
| 526 | return 0 |
| 527 | |
| 528 | log("WARN", f"CTF incomplete: {completed}/{len(GATES)} gates passed") |
| 529 | return 1 |
| 530 | |
| 531 | |
| 532 | # -- Entry point --------------------------------------------------------------- |
no test coverage detected