fix URL Redirection to Untrusted Site Open Redirect on redirectURI()
https://github.com/buzzfeed/sso/blob/549155a64d6c5f8916ed909cfa4e340734056284/internal/auth/authenticator.go#L430-L430
fix the problem to validate the redirectURI to ensure it is a local URL and does not redirect to a different host. This can be done by parsing the URL and checking that its hostname is empty. Additionally, we should replace all backslashes with forward slashes before parsing the URL to account for browser behavior.
- Parse the
redirectURIand check that its hostname is empty. - Replace all backslashes with forward slashes before parsing the URL.
- If the
redirectURIis valid, proceed with the redirection. Otherwise, return a 400 Bad Request response.
Directly incorporating user input into a URL redirect request without validating the input can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a malicious site that looks very similar to the real site they intend to visit, but is controlled by the attacker.
POC
The following shows an HTTP request parameter being used directly in a URL redirect without validating the input, which facilitates phishing attacks:
package main
import (
"net/http"
"buzzfeed/sso"
)
func serve() {
http.HandleFunc("/redir", func(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
http.Redirect(w, r, r.Form.Get("target"), 302)
})
}
One way to remedy the problem is to parse the target URL and check that its hostname is empty, which means that it is a relative URL:
package main
import (
"net/http"
"net/url"
"strings"
)
func serve1() {
http.HandleFunc("/redir", func(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
targetUrl := r.Form.Get("target")
// replace all backslashes with forward slashes before parsing the URL
targetUrl = strings.ReplaceAll(targetUrl, "\\", "/")
target, err := url.Parse(targetUrl)
if err != nil {
// ...
}
if target.Hostname() == "" {
// GOOD: check that it is a local redirect
http.Redirect(w, r, target.String(), 302)
} else {
w.WriteHeader(400)
}
})
}
Note that some browsers treat backslashes in URLs as forward slashes. To account for this, we replace all backslashes with forward slashes before parsing the URL and checking its hostname.