[release-11.4.9] Forbid more redirect patterns (#110506)

This commit is contained in:
grafana-delivery-bot[bot] 2025-09-03 11:43:58 +02:00 committed by GitHub
parent 36e7095840
commit c100d2c684
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 23 additions and 9 deletions

View File

@ -41,7 +41,7 @@ var getViewIndex = func() string {
return viewIndex
}
// Only allow redirects that start with an alphanumerical character, a dash or an underscore.
// Only allow redirects that start with a slash followed by an alphanumerical character, a dash or an underscore.
var redirectRe = regexp.MustCompile(`^/[a-zA-Z0-9-_].*`)
var (
@ -73,12 +73,17 @@ func (hs *HTTPServer) ValidateRedirectTo(redirectTo string) error {
return errForbiddenRedirectTo
}
if to.Path != "/" && !redirectRe.MatchString(to.Path) {
return errForbiddenRedirectTo
}
cleanPath := path.Clean(to.Path)
// "." is what path.Clean returns for empty paths
if cleanPath == "." {
return errForbiddenRedirectTo
}
if to.Path != "/" && !redirectRe.MatchString(cleanPath) {
if cleanPath != "/" && !redirectRe.MatchString(cleanPath) {
return errForbiddenRedirectTo
}

View File

@ -166,6 +166,7 @@ func TestHTTPServer_RotateUserAuthTokenRedirect(t *testing.T) {
// Invalid redirects should be converted to root
{"backslash domain", `/\grafana.com`, "/"},
{"backslash domain at the start of the path", `/\grafana.com/../a`, "/"},
{"traversal backslash domain", `/a/../\grafana.com`, "/"},
{"double slash", "//grafana", "/"},
{"missing initial slash", "missingInitialSlash", "/"},
@ -232,7 +233,7 @@ func TestHTTPServer_RotateUserAuthTokenRedirect(t *testing.T) {
res, err := server.Send(req)
require.NoError(t, err)
assert.Equal(t, 302, redirectStatusCode)
assert.Equal(t, redirectCase.expectedUrl, redirectLocation)
assert.Equal(t, redirectCase.expectedUrl, redirectLocation, "redirectTo=%s", redirectCase.redirectUrl)
require.NoError(t, res.Body.Close())
})

View File

@ -14,7 +14,7 @@ import (
"github.com/grafana/grafana/pkg/web"
)
// Only allow redirects that start with an alphanumerical character, a dash or an underscore.
// Only allow redirects that start with a slash followed by an alphanumerical character, a dash or an underscore.
var redirectRe = regexp.MustCompile(`^/?[a-zA-Z0-9-_].*`)
// OrgRedirect changes org and redirects users if the
@ -67,6 +67,9 @@ func OrgRedirect(cfg *setting.Cfg, userSvc user.Service) web.Handler {
}
func validRedirectPath(p string) bool {
if p != "" && p != "/" && !redirectRe.MatchString(p) {
return false
}
cleanPath := path.Clean(p)
return cleanPath == "." || cleanPath == "/" || redirectRe.MatchString(cleanPath)
}

View File

@ -71,12 +71,17 @@ func TestOrgRedirectMiddleware(t *testing.T) {
})
middlewareScenario(t, "when redirecting to an invalid path", func(t *testing.T, sc *scenarioContext) {
testPaths := []string{
url.QueryEscape(`/\example.com`),
`/%2fexample.com`,
}
for _, path := range testPaths {
sc.withIdentity(&authn.Identity{})
path := url.QueryEscape(`/\example.com`)
sc.m.Get(url.QueryEscape(path), sc.defaultHandler)
sc.fakeReq("GET", fmt.Sprintf("%s?orgId=3", path)).exec()
require.Equal(t, 404, sc.resp.Code)
require.Equal(t, 404, sc.resp.Code, "path: %s", path)
}
})
}