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 in oauth path #77

Closed
wants to merge 3 commits into from
Closed

Conversation

saez0pub
Copy link

@saez0pub saez0pub commented Oct 15, 2019

The state is used in order to redirect user after authentication.
It is composed of crsf_cookie:redirect_url.
redirect_url is not validated and could lead to an open redirect (CWE-601: URL Redirection to Untrusted Site ('Open Redirect')) in case of xss forging the crsf cookie in the website protected by the authentication.
A prevention could be to use a whitelist: https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md

Looking at the code, the state parameter of the auth cannot be on another domain and scheme than the redirect parameter in state.

So I added the verification of the redirect parameter based on how the state parameter.

@thomseddon
Copy link
Owner

@saez0pub Thank you for this and my apologies for the delayed response.

I agree this is a possible issue, so let's get this resolved, I like the approach here but we'll also need to support the use of AuthHost...can I suggest:

  • Rename redirectBase to be forwardedRequestBase and use this in returnUrl
  • Create a new function redirectBase which includes the auth host check logic from redirectUri, use this in redirectUri function
  • Encapsulate the logic of this PR into a new function validateRedirect, this can use the new redirectBase and move tests to just test this function

Sorry I've taken a while to pick this up, if you don't have time to do this I can pick it up over the next couple of weeks, no problemo.

Thanks again :)

@thomseddon thomseddon added enhancement New feature or request under review labels Jan 18, 2020
@thomseddon thomseddon added this to the 2.2 milestone Apr 16, 2020
thomseddon added a commit that referenced this pull request Apr 16, 2020
This change introduces a validation step prior to redirect as
discussed in #77
@thomseddon
Copy link
Owner

I've just pushed another version of this, it works slightly differently as I realised the patch you initially provided would not work with an auth host setup.

I need to do a little more testing on this, as the lack of validation could be considered a bug I'd like to release this ASAP.

@thomseddon
Copy link
Owner

thomseddon commented Apr 17, 2020

I've thought a little more about this and I'm not sure this is actually anything to exploit here.

The redirect is read from the CSRF cookie here:

// Validate state
valid, providerName, redirect, err := ValidateCSRFCookie(r, c)
if !valid {
logger.Warnf("Error validating csrf cookie: %v", err)
http.Error(w, "Not authorized", 401)
return
}

During the CSRF "validation", the nonce is also read and the function just verifies that the nonce matches the state param in the URL, which could be forged.

However, the redirect is only followed if the code is successfully exchanged for an access token with the provider. If the exchange fails or the user cannot be retrieved, the server returns a 503 and does not follow the redirect:

// Exchange code for token
token, err := p.ExchangeCode(redirectUri(r), r.URL.Query().Get("code"))
if err != nil {
logger.Errorf("Code exchange failed with: %v", err)
http.Error(w, "Service unavailable", 503)
return
}
// Get user
user, err := p.GetUser(token)
if err != nil {
logger.Errorf("Error getting user: %s", err)
return
}

As such, to exploit this redirect the attacker would need to pass a valid code - which can only be obtained following successful authentication of the user. Additionally, by design the code is prevented from being intercepted as the user must explicitly configure valid return_url's with the provider, so the code will only ever be sent to an expected destination.

I understand this was a vulnerability in the oauth2-proxy module, but I believe they were vulnerable as they have a sign in page that will redirect an authenticated user: https://github.com/oauth2-proxy/oauth2-proxy/blob/dd05e7ff0bad417b088c9e67e5eaa624e30e3ddc/oauthproxy.go#L684-L705

Reading here: https://tools.ietf.org/id/draft-ietf-oauth-security-topics-05.html#rfc.section.3.8.2

In order to prevent open redirection, clients should only expose such a function, if the target URLs are whitelisted or if the origin of a request can be authenticated.

And so it seems that successful code exchange should be sufficient for validating the origin of the request. There is the possible vector of the attacker generating a valid code themself, injecting a malicious redirect_uri and tricking another use to visit, however our use of the state param here is designed to prevent that exact CSRF attack.

If anyone thinks I have missed something here, please let me know - I will leave this open for a while in case anyone can show how this could be exploited, but otherwise I will close this

@thomseddon thomseddon added help wanted Extra attention is needed invalid This doesn't seem right and removed enhancement New feature or request labels Apr 17, 2020
@thomseddon thomseddon removed this from the 2.2 milestone Apr 17, 2020
@sauyon
Copy link

sauyon commented Apr 22, 2020

I've thought a little bit about this and I think I agree with your assessment of the situation, though if redirects are only meant to go to certain places I'd suggest doing checks against the redirect URL just in case.

jordemort added a commit to jordemort/traefik-forward-auth that referenced this pull request Nov 5, 2022
* Validate redirect domain

This change introduces a validation step prior to redirect as
discussed in thomseddon#77

* Fix tests

* Try harder to make CodeQL happy

* Fix tests

* Try just a little bit harder to appease CodeQL

Co-authored-by: Thom Seddon <thom@seddonmedia.co.uk>
@saez0pub saez0pub closed this Jun 23, 2023
mkska added a commit to mkska/traefik-forward-auth that referenced this pull request Aug 22, 2023
* Allow custom key to be used for whitelist and X-Forwarded-User instead of the hardcoded email (#1)

* init commit

* add github workflow

* fix naming

* fix missing param

* upgrade Go version to 1.14

* tmp remove of tests
update error message

* add more specific error message

* put back tests

* rename User ID Key to User ID Path

* upgrade dependencies

* Revert "upgrade dependencies"

This reverts commit 40bd110

It prevents GO 1.12 from working 1.13 + 1.14 still work however.

* Revert "upgrade dependencies"

This reverts commit 40bd110

* mention the user that is not authorized

* mention the user that is not authorized

* tidy error message

* tidy error message

* remove actions

* rename UserIDPath to UserID
remove UserID type
rename comma delimited to comma separated

* rename GetUsedID function to GetUser

* revert docker golang version to 1.13

* change whitelist comment to indicate userIDs instead of explicitly emails

* revert go version

* fix conflicts

* add tests

* push to docker for testing

Co-authored-by: Maximilian Mitchell <max@max.me.uk>
Co-authored-by: Max Mitchell <max.mitchell@ly.st>
Co-authored-by: Maximilian Mitchell <max@maxis.me>

* Domain matching should be case insensitive (#2)

* Domain matching should be case insensitive

* s/ValidateEmail/ValidateUser/

Co-authored-by: Mal Curtis <mal@mal.co.nz>

* fix too many forward_auth cookies (#3)

* fix too many forward_auth cookies

* fix missing csrf cookie

Co-authored-by: orvice <orvice@gmail.com>

* feature: trusted ip address ranges skip authentication (#4)

Co-authored-by: Alexander Metzner <alexander.metzner@nortal.com>

* Use Go 1.19 in CI (#5)

* Update dependencies (#6)

* Update dependencies

* Stop testing with ancient Go versions

* Redo Dockerfile with Go 1.19 and distroless (#7)

* Create dependabot.yml

* Bump github/codeql-action from 1 to 2 (#8)

Bumps [github/codeql-action](https://github.com/github/codeql-action) from 1 to 2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@v1...v2)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump actions/setup-go from 2 to 3 (#9)

Bumps [actions/setup-go](https://github.com/actions/setup-go) from 2 to 3.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](actions/setup-go@v2...v3)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump actions/checkout from 2 to 3 (#10)

Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump github.com/stretchr/testify from 1.8.0 to 1.8.1 (#11)

Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](stretchr/testify@v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Fix most of the issues CodeQL dislikes (#12)

* Fix most of the issues CodeQL dislikes

* Escape ipAddr closer to source

* Validate redirect domain (#13)

* Validate redirect domain

This change introduces a validation step prior to redirect as
discussed in thomseddon#77

* Fix tests

* Try harder to make CodeQL happy

* Fix tests

* Try just a little bit harder to appease CodeQL

Co-authored-by: Thom Seddon <thom@seddonmedia.co.uk>

* Workflow update: build container, rename master to main (#14)

* Run tests as part of container build (#15)

* Update README (#16)

* Update README

* Further README tweaks

* Update README.md

* Bump docker/setup-buildx-action from 2.0.0 to 2.2.1 (#17)

Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2.0.0 to 2.2.1.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](docker/setup-buildx-action@v2.0.0...v2.2.1)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump github.com/traefik/traefik/v2 from 2.9.4 to 2.9.6 (#21)

Bumps [github.com/traefik/traefik/v2](https://github.com/traefik/traefik) from 2.9.4 to 2.9.6.
- [Release notes](https://github.com/traefik/traefik/releases)
- [Changelog](https://github.com/traefik/traefik/blob/master/CHANGELOG.md)
- [Commits](traefik/traefik@v2.9.4...v2.9.6)

---
updated-dependencies:
- dependency-name: github.com/traefik/traefik/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump golang.org/x/oauth2 from 0.1.0 to 0.4.0 (#22)

Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.1.0 to 0.4.0.
- [Release notes](https://github.com/golang/oauth2/releases)
- [Commits](golang/oauth2@v0.1.0...v0.4.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add .github to .dockerignore

* Add actions workflow to build and push docker image
This workflow builds multi-arch docker image on every push and pull request.
Also, this workflow pushes image to docker hub with appropriate semver tags on tag push.

* Publish to ghcr

* chore(ci): use own registry

* Add SameSite option

* docs: updates readme

* Update README.md

* remove docker workflow

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Jordan Webb <jordan@webb.haus>
Co-authored-by: Maximilian Mitchell <max@max.me.uk>
Co-authored-by: Max Mitchell <max.mitchell@ly.st>
Co-authored-by: Maximilian Mitchell <max@maxis.me>
Co-authored-by: Mal Curtis <mal@mal.co.nz>
Co-authored-by: orvice <orvice@gmail.com>
Co-authored-by: Alexander Metzner <alexander.metzner@nortal.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Thom Seddon <thom@seddonmedia.co.uk>
Co-authored-by: Ciffelia <mc.prince.0203@gmail.com>
Co-authored-by: Beanow <497556+Beanow@users.noreply.github.com>
Co-authored-by: Alexandre Richonnier <heralight@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed invalid This doesn't seem right under review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants