Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open redirect vulnerability exposed when localePrefix: 'as-needed' #1207

Closed
3 tasks done
hblee12294 opened this issue Jul 19, 2024 · 1 comment · Fixed by #1208
Closed
3 tasks done

Open redirect vulnerability exposed when localePrefix: 'as-needed' #1207

hblee12294 opened this issue Jul 19, 2024 · 1 comment · Fixed by #1208
Labels
bug Something isn't working unconfirmed Needs triage.

Comments

@hblee12294
Copy link
Contributor

hblee12294 commented Jul 19, 2024

Description

Hi, I have found an open redirect vulnerability when localePrefix is 'as-needed' . This vulnerability allows an attacker to redirect users to a malicious site by manipulating URL parameters.

The vulnerability occurs due to decodeURI doesn't escape decoded backslashs(%5C & %5c) and will decode them into '\' as an unsafe externalPathname. This unsafe externalPathname will be passed to new URL(normalizeTrailingSlash(url), request.url) to be the redirect destination. But URL will internally replace backslashs with slashes and take it as a new authority (host) part, the host will be parsed wrongly due to this bug(or feature?). Here's an example of what I'm talking about:

// Escaped
const  pathnameWithOtherCodes = 'http://localhost:3000/en/%20example.org'
console.log(decodeURI(pathnameWithOtherCodes)) // Output: http://localhost:3000/en/%2Bexample.org

// Non-escaped
const pathnameWithBackslash = 'http://localhost:3000/en/%5Cexample.org'
console.log(decodeURI(pathnameWithBackslash)) // Output: http://localhost:3000/en/\example.org

// Uncommon behaviour of constructing URL
console.log(new URL("/\\example.org", "http://google.com"))
console.log(new URL("//example.org", "http://google.com"))

/*
*  They both output:
*  {
*    href: 'http://example.org/',
*    origin: 'http://example.org',
*    protocol: 'http:',
*    username: '',
*    password: '',
*    host: 'example.org',
*    hostname: 'example.org',
*    port: '',
*    pathname: '/',
*    search: '',
*    searchParams: URLSearchParams {},
*    hash: ''
*  }
*/

Example:

My project reproduces this issue, access it from this url

https://nextempura.vercel.app/en/%5Cexample.org

References

A similar vulnerability occurred in URI.js, which was fixed by replacing all '\' with ''.

Verifications

  • I've verified that the problem I'm experiencing isn't covered in the docs.
  • I've searched for similar, existing issues on GitHub and Stack Overflow.
  • I've compared my app to a working example to look for differences.

Mandatory reproduction URL

https://github.com/hblee12294/nextempura

Reproduction description

Steps to reproduce:

  1. Clone this repo: https://github.com/hblee12294/nextempura
  2. Run pnpm install / npm install / yarn install
  3. Run pnpm dev / pnpm run dev / yarn dev
  4. Open localhost:3000 in the browser
  5. Visit http://localhost:3000/en/%5Cexample.org

Expected behaviour

The website will be redirected to example.org, but it should be http://localhost:3000/%5Cexample.org.

@hblee12294 hblee12294 added bug Something isn't working unconfirmed Needs triage. labels Jul 19, 2024
@hblee12294
Copy link
Contributor Author

I'll create a pr to fix this issue shortly.

@hblee12294 hblee12294 changed the title Open redirect vulnerability exposed when localePrefix: 'as-needed' Open redirect vulnerability exposed when localePrefix: 'as-needed' Jul 19, 2024
amannn added a commit that referenced this issue Jul 19, 2024
…'` by sanitizing pathname in the middleware (#1208)

Fixes #1207 (see issue for details)

---------

Co-authored-by: Jan Amann <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working unconfirmed Needs triage.
Projects
None yet
1 participant