Skip to content

Restrict Open Redirect low/medium/high to an allowlist of targets - #189

Open
JBHook wants to merge 2 commits into
OWASP-CTF:dc34-ctffrom
JBHook:fix/open-redirect-allowlist
Open

JBHook wants to merge 2 commits into
OWASP-CTF:dc34-ctffrom
JBHook:fix/open-redirect-allowlist

Conversation

@JBHook

@JBHook JBHook commented Aug 9, 2026

Copy link
Copy Markdown

Summary

low.php passed "redirect" straight into the Location header. medium.php blocked http:///https:// but not a protocol-relative URL like //evil.com. high.php checked that info.php appeared anywhere in the value via strpos(), satisfied by a payload like //evil.com/?info.php while still redirecting off-site.

Fix

All three now only allow a small set of known internal targets, selected by a numeric id, matching impossible.php.

Test plan

  • php -l clean on all three files
  • Live-validated: legit numeric redirect (redirect=1) still returns Location: info.php?id=1 at all three levels; redirect=http://evil.com returns 500 at all three levels.

🤖 Generated with Claude Code

low.php passed the "redirect" parameter straight into the Location
header with zero validation. medium.php blocked "http://"/"https://"
but not a protocol-relative URL like "//evil.com", which browsers
still treat as an absolute off-site redirect. high.php checked that
"info.php" appeared anywhere in the value via strpos(), satisfied by
a payload like "//evil.com/?info.php" while still redirecting off-site.

All three now only allow a small set of known internal targets,
selected by a numeric id, matching impossible.php's approach.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 9, 2026 •

Copy link
Copy Markdown

🏆 DVWA — CTF Patch Score

░░░░░░░░░░░░░░░░░░░░  0 / 108 pts  (0%)

0 / 55 challenges patched

Per-challenge detail is withheld — it would reveal the rubric.

Commit: 29cbb1f · scoring run

No points yet — this commit didn't solve any challenges, so there's nothing on the leaderboard for it. Patch a vulnerability and push again! 💪

… numeric scheme

The previous fix mirrored impossible.php's numeric-id switch statement
(redirect=1/2/99), but that broke the app's own navigation: index.php's
links for low/medium/high still send redirect=info.php?id=1 (a literal
string), never a numeric id. Every legitimate click through those pages was
returning HTTP 500 instead of redirecting, likely why the previous patch
scored 0/3 despite closing the actual injection - a broken app doesn't get
graded as a fixed one.

Switched to an allowlist of the exact known-good strings the app itself
uses ("info.php?id=1", "info.php?id=2"), checked with a strict in_array()
comparison. This closes the same injection (arbitrary redirect target) while
keeping the app's existing navigation working unmodified.

Live-tested against a fresh instance at all three levels:
- redirect=info.php?id=1 (the app's own link) -> 302, works as before
- redirect=https://evil.com (low) -> 500, rejected
- redirect=//evil.com/?info.php (medium's protocol-relative bypass, high's
  substring bypass) -> 500, rejected at both levels
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant