The Open Redirect — JavaScript Bug Hunt

Inspired by the open-redirect advisories filed against practically every login page ever built.

  • Language: JavaScript
  • Layer: Backend
  • Difficulty: Medium
  • Concepts: Security, URLs
  • Modelled on: Login pages everywhere
  • Visible tests: our own absolute urls pass; a foreign url mentioning our host is blocked; relative paths pass, protocol-relative tricks do not
  • Reward: 50 XP for a complete fix

Briefing

Inspired by the open-redirect advisories filed against practically every login page ever built. The "is this URL ours?" check uses indexOf — so https://evil.example/?next=https://good.com passes because the good host appears somewhere in the string.

redirects.js picks the post-login destination.

Bug report

BUG-302 · Priority: High (phishing vector) · Reported by: bug bounty

safeRedirect(url, allowedHosts) -> the url if safe, else "/":

  • allowed: same-site relative paths ("/dashboard") — but NOT "//host" tricks
  • allowed: "https://<host>" or "https://<host>/..." for hosts in the list
  • everything else -> "/"

Observed: attacker URLs containing our hostname anywhere sail through.

Logs

[login] redirect -> https://evil.example/phish?brand=good.com (allowed?!)

The code as shipped

src/web/redirects.js (editable)

// Chooses the post-login redirect target.
exports.safeRedirect = function (url, allowedHosts) {
  for (var i = 0; i < allowedHosts.length; i++) {
    if (url.indexOf(allowedHosts[i]) !== -1) {
      return url;
    }
  }
  return "/";
};

Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.