From 5790ba49c252f2cf739423d4902976d004475e43 Mon Sep 17 00:00:00 2001 From: dsotirakis Date: Mon, 20 Mar 2023 09:51:29 +0200 Subject: [PATCH 1/3] Geomap: Sanitize the attribution string (#745) * SAML: Update grafana/saml library (#691) Co-authored-by: jguer * SVG: Add dompurify preprocessor step (#698) * add sanitized SVG component * add sanitize * Fix frontend build * Remove unnecessary yarn.lock changes * Fix formatting * Re-add yarn.lock message as I guess it is needed --------- Co-authored-by: dsotirakis Co-authored-by: jguer Co-authored-by: nmarrs Co-authored-by: Drew Slobodnjak <60050885+drew08t@users.noreply.github.com> --- go.mod | 2 +- public/app/plugins/panel/geomap/utils/layers.ts | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index aaf21363f5b..c2600e0213a 100644 --- a/go.mod +++ b/go.mod @@ -127,7 +127,7 @@ require ( gopkg.in/mail.v2 v2.3.1 gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 - xorm.io/builder v0.3.6 // indirect + xorm.io/builder v0.3.6 xorm.io/core v0.7.3 xorm.io/xorm v0.8.2 ) diff --git a/public/app/plugins/panel/geomap/utils/layers.ts b/public/app/plugins/panel/geomap/utils/layers.ts index 6e9d5995aa7..75a2357c388 100644 --- a/public/app/plugins/panel/geomap/utils/layers.ts +++ b/public/app/plugins/panel/geomap/utils/layers.ts @@ -2,7 +2,7 @@ import { Map as OpenLayersMap } from 'ol'; import { FeatureLike } from 'ol/Feature'; import { Subject } from 'rxjs'; -import { getFrameMatchers, MapLayerHandler, MapLayerOptions, PanelData } from '@grafana/data/src'; +import { getFrameMatchers, MapLayerHandler, MapLayerOptions, PanelData, textUtil } from '@grafana/data'; import { config } from '@grafana/runtime/src'; import { GeomapPanel } from '../GeomapPanel'; @@ -114,6 +114,10 @@ export async function initLayer( return Promise.reject('unknown layer: ' + options.type); } + if (options.config?.attribution) { + options.config.attribution = textUtil.sanitizeTextPanelContent(options.config.attribution); + } + const handler = await item.create(map, options, panel.props.eventBus, config.theme2); const layer = handler.init(); // eslint-disable-line if (options.opacity != null) { From 7a1a8b7a868753c214390da58d7fc833ae17fe72 Mon Sep 17 00:00:00 2001 From: Jo Date: Mon, 3 Apr 2023 12:49:11 +0100 Subject: [PATCH 2/3] AuthJWT: Fix JWT query param leak (CVE-2023-1387) (#825) fix JWT query param leak Co-authored-by: Gabriel MABILLE Co-authored-by: Kalle Persson --- pkg/services/authn/clients/jwt.go | 15 +++++++++ pkg/services/authn/clients/jwt_test.go | 44 +++++++++++++++++++++++++ pkg/services/contexthandler/auth_jwt.go | 24 +++++++++++--- 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/pkg/services/authn/clients/jwt.go b/pkg/services/authn/clients/jwt.go index a6474ba7176..cc65b7e4ed2 100644 --- a/pkg/services/authn/clients/jwt.go +++ b/pkg/services/authn/clients/jwt.go @@ -19,6 +19,8 @@ import ( "github.com/grafana/grafana/pkg/util/errutil" ) +const authQueryParamName = "auth_token" + var _ authn.ContextAwareClient = new(JWT) var ( @@ -50,6 +52,7 @@ func (s *JWT) Name() string { func (s *JWT) Authenticate(ctx context.Context, r *authn.Request) (*authn.Identity, error) { jwtToken := s.retrieveToken(r.HTTPRequest) + s.stripSensitiveParam(r.HTTPRequest) claims, err := s.jwtService.Verify(ctx, jwtToken) if err != nil { @@ -120,6 +123,18 @@ func (s *JWT) Authenticate(ctx context.Context, r *authn.Request) (*authn.Identi return id, nil } +// remove sensitive query param +// avoid JWT URL login passing auth_token in URL +func (s *JWT) stripSensitiveParam(httpRequest *http.Request) { + if s.cfg.JWTAuthURLLogin { + params := httpRequest.URL.Query() + if params.Has(authQueryParamName) { + params.Del(authQueryParamName) + httpRequest.URL.RawQuery = params.Encode() + } + } +} + // retrieveToken retrieves the JWT token from the request. func (s *JWT) retrieveToken(httpRequest *http.Request) string { jwtToken := httpRequest.Header.Get(s.cfg.JWTAuthHeaderName) diff --git a/pkg/services/authn/clients/jwt_test.go b/pkg/services/authn/clients/jwt_test.go index 04a4c837bfe..f59aac88d8e 100644 --- a/pkg/services/authn/clients/jwt_test.go +++ b/pkg/services/authn/clients/jwt_test.go @@ -307,3 +307,47 @@ func TestJWTTest(t *testing.T) { }) } } + +func TestJWTStripParam(t *testing.T) { + jwtService := &jwt.FakeJWTService{ + VerifyProvider: func(context.Context, string) (jwt.JWTClaims, error) { + return jwt.JWTClaims{ + "sub": "1234567890", + "email": "eai.doe@cor.po", + "preferred_username": "eai-doe", + "name": "Eai Doe", + "roles": "Admin", + }, nil + }, + } + + jwtHeaderName := "X-Forwarded-User" + + cfg := &setting.Cfg{ + JWTAuthEnabled: true, + JWTAuthHeaderName: jwtHeaderName, + JWTAuthAutoSignUp: true, + JWTAuthAllowAssignGrafanaAdmin: true, + JWTAuthURLLogin: true, + JWTAuthRoleAttributeStrict: false, + JWTAuthRoleAttributePath: "roles", + JWTAuthEmailClaim: "email", + JWTAuthUsernameClaim: "preferred_username", + } + + // #nosec G101 -- This is a dummy/test token + token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.XbPfbIHMI6arZ3Y922BhjWgQzWXcXNrz0ogtVhfEd2o" + + httpReq := &http.Request{ + URL: &url.URL{RawQuery: "auth_token=" + token + "&other_param=other_value"}, + } + jwtClient := ProvideJWT(jwtService, cfg) + _, err := jwtClient.Authenticate(context.Background(), &authn.Request{ + OrgID: 1, + HTTPRequest: httpReq, + Resp: nil, + }) + require.NoError(t, err) + // auth_token should be removed from the query string + assert.Equal(t, "other_param=other_value", httpReq.URL.RawQuery) +} diff --git a/pkg/services/contexthandler/auth_jwt.go b/pkg/services/contexthandler/auth_jwt.go index 9936d956c96..1d3d79640c3 100644 --- a/pkg/services/contexthandler/auth_jwt.go +++ b/pkg/services/contexthandler/auth_jwt.go @@ -15,12 +15,14 @@ import ( loginsvc "github.com/grafana/grafana/pkg/services/login" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/user" + "github.com/grafana/grafana/pkg/setting" ) const ( - InvalidJWT = "Invalid JWT" - InvalidRole = "Invalid Role" - UserNotFound = "User not found" + InvalidJWT = "Invalid JWT" + InvalidRole = "Invalid Role" + UserNotFound = "User not found" + authQueryParamName = "auth_token" ) func (h *ContextHandler) initContextWithJWT(ctx *contextmodel.ReqContext, orgId int64) bool { @@ -30,13 +32,15 @@ func (h *ContextHandler) initContextWithJWT(ctx *contextmodel.ReqContext, orgId jwtToken := ctx.Req.Header.Get(h.Cfg.JWTAuthHeaderName) if jwtToken == "" && h.Cfg.JWTAuthURLLogin { - jwtToken = ctx.Req.URL.Query().Get("auth_token") + jwtToken = ctx.Req.URL.Query().Get(authQueryParamName) } if jwtToken == "" { return false } + stripSensitiveParam(h.Cfg, ctx.Req) + // Strip the 'Bearer' prefix if it exists. jwtToken = strings.TrimPrefix(jwtToken, "Bearer ") @@ -204,3 +208,15 @@ func searchClaimsForStringAttr(attributePath string, claims map[string]interface return "", nil } + +// remove sensitive query params +// avoid JWT URL login passing auth_token in URL +func stripSensitiveParam(cfg *setting.Cfg, httpRequest *http.Request) { + if cfg.JWTAuthURLLogin { + params := httpRequest.URL.Query() + if params.Has(authQueryParamName) { + params.Del(authQueryParamName) + httpRequest.URL.RawQuery = params.Encode() + } + } +} From 80de6d6d02bddcf038521e5448e31be15b9f91eb Mon Sep 17 00:00:00 2001 From: Misi Date: Mon, 3 Apr 2023 14:23:52 +0200 Subject: [PATCH 3/3] Chore: Update SAML lib (#824) Update saml lib --- go.mod | 4 ++-- go.sum | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index c2600e0213a..92c37fb8027 100644 --- a/go.mod +++ b/go.mod @@ -127,7 +127,7 @@ require ( gopkg.in/mail.v2 v2.3.1 gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 - xorm.io/builder v0.3.6 + xorm.io/builder v0.3.6 // indirect xorm.io/core v0.7.3 xorm.io/xorm v0.8.2 ) @@ -400,7 +400,7 @@ require ( ) // Use fork of crewjam/saml with fixes for some issues until changes get merged into upstream -replace github.com/crewjam/saml => github.com/grafana/saml v0.4.13-0.20230203140620-5f476db5c00a +replace github.com/crewjam/saml => github.com/grafana/saml v0.4.13-0.20230331080031-67cbfa09c7b6 // Thema's thema CLI requires cobra, which eventually works its way down to go-hclog@v1.0.0. // Upgrading affects backend plugins: https://github.com/grafana/grafana/pull/47653#discussion_r850508593 diff --git a/go.sum b/go.sum index 589fa79a58b..11990c30bee 100644 --- a/go.sum +++ b/go.sum @@ -1284,8 +1284,8 @@ github.com/grafana/phlare/api v0.1.3 h1:mYTaE9mLsAW/uzPXlW/PQSLsZ4ojBFA+oAMfR/PD github.com/grafana/phlare/api v0.1.3/go.mod h1:29vcLwFDmZBDce2jwFIMtzvof7fzPadT8VMKw9ks7FU= github.com/grafana/prometheus-alertmanager v0.25.1-0.20230308154952-78fedf89728b h1:VQOGGGJ2lKcVPANyzIESKYhSeA0QIvUQwfA3CbrkDfA= github.com/grafana/prometheus-alertmanager v0.25.1-0.20230308154952-78fedf89728b/go.mod h1:MnBfDPXJqXmmfPwQlCLvVUdqfnvrAw+hSPtDeaaFwj4= -github.com/grafana/saml v0.4.13-0.20230203140620-5f476db5c00a h1:aWSTt/pTOI4uGY9DhBMG1l0GOnGjIYtaqxzYR3/q82o= -github.com/grafana/saml v0.4.13-0.20230203140620-5f476db5c00a/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA= +github.com/grafana/saml v0.4.13-0.20230331080031-67cbfa09c7b6 h1:oHn/OOUkECNX06DPHksS7R3UY5Qdye04b/sBj2/OJ5E= +github.com/grafana/saml v0.4.13-0.20230331080031-67cbfa09c7b6/go.mod h1:igEejV+fihTIlHXYP8zOec3V5A8y3lws5bQBFsTm4gA= github.com/grafana/sqlds/v2 v2.3.10 h1:HWKhE0vR6LoEiE+Is8CSZOgaB//D1yqb2ntkass9Fd4= github.com/grafana/sqlds/v2 v2.3.10/go.mod h1:c6ibxnxRVGxV/0YkEgvy7QpQH/lyifFyV7K/14xvdIs= github.com/grafana/thema v0.0.0-20230302221249-6952e4a999b7 h1:XOxaBjhozlleshff3mKNdp55ul74nXJEX3wz8ckjTpc=