Security: Fixes for CVE-2025-6197 and CVE-2025-6023 (#108280)
fix(redirect): make validation of redirect uri stricter Co-authored-by: volcanonoodle <114113189+volcanonoodle@users.noreply.github.com>
This commit is contained in:
co-authored by
volcanonoodle
parent
1e9c78656a
commit
988d964200
@@ -3,6 +3,8 @@ package middleware
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/contexthandler"
|
||||
@@ -11,6 +13,9 @@ import (
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
// Only allow redirects that start with an alphanumerical character, a dash or an underscore.
|
||||
var redirectRe = regexp.MustCompile(`^/?[a-zA-Z0-9-_].*`)
|
||||
|
||||
// OrgRedirect changes org and redirects users if the
|
||||
// querystring `orgId` doesn't match the active org.
|
||||
func OrgRedirect(cfg *setting.Cfg, userSvc user.Service) web.Handler {
|
||||
@@ -31,6 +36,11 @@ func OrgRedirect(cfg *setting.Cfg, userSvc user.Service) web.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
if !validRedirectPath(c.Req.URL.Path) {
|
||||
// Do not switch orgs or perform the redirect because the new path is not valid
|
||||
return
|
||||
}
|
||||
|
||||
if err := userSvc.Update(ctx.Req.Context(), &user.UpdateUserCommand{UserID: ctx.UserID, OrgID: &orgId}); err != nil {
|
||||
if ctx.IsApiRequest() {
|
||||
ctx.JsonApiErr(404, "Not found", nil)
|
||||
@@ -54,3 +64,8 @@ func OrgRedirect(cfg *setting.Cfg, userSvc user.Service) web.Handler {
|
||||
c.Redirect(newURL, 302)
|
||||
}
|
||||
}
|
||||
|
||||
func validRedirectPath(p string) bool {
|
||||
cleanPath := path.Clean(p)
|
||||
return cleanPath == "." || cleanPath == "/" || redirectRe.MatchString(cleanPath)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package middleware
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -23,6 +24,12 @@ func TestOrgRedirectMiddleware(t *testing.T) {
|
||||
expStatus: 302,
|
||||
expLocation: "/?orgId=3",
|
||||
},
|
||||
{
|
||||
desc: "when setting a correct org for the user with an empty path",
|
||||
input: "?orgId=3",
|
||||
expStatus: 302,
|
||||
expLocation: "/?orgId=3",
|
||||
},
|
||||
{
|
||||
desc: "when setting a correct org for the user with '&kiosk'",
|
||||
input: "/?orgId=3&kiosk",
|
||||
@@ -64,6 +71,16 @@ func TestOrgRedirectMiddleware(t *testing.T) {
|
||||
require.Equal(t, 404, sc.resp.Code)
|
||||
})
|
||||
|
||||
middlewareScenario(t, "when redirecting to an invalid path", func(t *testing.T, sc *scenarioContext) {
|
||||
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)
|
||||
})
|
||||
|
||||
middlewareScenario(t, "works correctly when grafana is served under a subpath", func(t *testing.T, sc *scenarioContext) {
|
||||
sc.withIdentity(&authn.Identity{})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user