fix: sanitize X-Forwarded-Proto header in RedirectScheme middleware

Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
This commit is contained in:
Ludovic Fernandez 2022-12-16 10:34:04 +01:00 committed by GitHub
parent e7baf44a2e
commit 29b8b6911e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 6 deletions

View file

@ -18,6 +18,12 @@ const (
xForwardedProto = "X-Forwarded-Proto"
)
type redirectScheme struct {
http.Handler
name string
}
// NewRedirectScheme creates a new RedirectScheme middleware.
func NewRedirectScheme(ctx context.Context, next http.Handler, conf dynamic.RedirectScheme, name string) (http.Handler, error) {
logger := log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeSchemeName))
@ -33,10 +39,19 @@ func NewRedirectScheme(ctx context.Context, next http.Handler, conf dynamic.Redi
port = ":" + conf.Port
}
return newRedirect(next, uriPattern, conf.Scheme+"://${2}"+port+"${4}", conf.Permanent, clientRequestURL, name)
rs := &redirectScheme{name: name}
handler, err := newRedirect(next, uriPattern, conf.Scheme+"://${2}"+port+"${4}", conf.Permanent, rs.clientRequestURL, name)
if err != nil {
return nil, err
}
rs.Handler = handler
return rs, nil
}
func clientRequestURL(req *http.Request) string {
func (r *redirectScheme) clientRequestURL(req *http.Request) string {
scheme := schemeHTTP
host, port, err := net.SplitHostPort(req.Host)
if err != nil {
@ -71,12 +86,12 @@ func clientRequestURL(req *http.Request) string {
// Given that we're in a middleware that is only used in the context of HTTP(s) requests,
// the only possible valid schemes are one of "http" or "https", so we convert back to them.
switch {
case strings.EqualFold(xProto, "ws"):
case strings.EqualFold(xProto, schemeHTTP), strings.EqualFold(xProto, "ws"):
scheme = schemeHTTP
case strings.EqualFold(xProto, "wss"):
case strings.EqualFold(xProto, schemeHTTPS), strings.EqualFold(xProto, "wss"):
scheme = schemeHTTPS
default:
scheme = xProto
log.FromContext(middlewares.GetLoggerCtx(req.Context(), r.name, typeSchemeName)).Debugf("invalid X-Forwarded-Proto: %s", xProto)
}
}

View file

@ -72,7 +72,7 @@ func TestRedirectSchemeHandler(t *testing.T) {
headers: map[string]string{
"X-Forwarded-Proto": "bar",
},
expectedURL: "https://bar://foo",
expectedURL: "https://foo",
expectedStatus: http.StatusFound,
},
{