From 2936dc87d074e6d83147c9e6cf4ae8bac4e4af8d Mon Sep 17 00:00:00 2001 From: Daniel Schalla Date: Thu, 2 Aug 2018 00:16:04 +0200 Subject: CSRF Token Implementation for Plugins (#9192) deleted test config fix test config Dont wipe the session token for plugins Simplified Tokens; Generate CSRF for other sessions Remove CSRF from Access Token; Remove Getter/Setter from Context fix removed setter remove getcsrf helper from plugin api enforce csrf only for cookie auth --- app/plugin_requests.go | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'app/plugin_requests.go') diff --git a/app/plugin_requests.go b/app/plugin_requests.go index 2f9ac1476..ec6091017 100644 --- a/app/plugin_requests.go +++ b/app/plugin_requests.go @@ -8,11 +8,13 @@ import ( "path" "strings" + "bytes" "github.com/gorilla/mux" "github.com/mattermost/mattermost-server/mlog" "github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/plugin" "github.com/mattermost/mattermost-server/utils" + "io/ioutil" ) func (a *App) ServePluginRequest(w http.ResponseWriter, r *http.Request) { @@ -38,22 +40,44 @@ func (a *App) ServePluginRequest(w http.ResponseWriter, r *http.Request) { func (a *App) servePluginRequest(w http.ResponseWriter, r *http.Request, handler func(*plugin.Context, http.ResponseWriter, *http.Request)) { token := "" + context := &plugin.Context{} + cookieAuth := false authHeader := r.Header.Get(model.HEADER_AUTH) if strings.HasPrefix(strings.ToUpper(authHeader), model.HEADER_BEARER+" ") { token = authHeader[len(model.HEADER_BEARER)+1:] } else if strings.HasPrefix(strings.ToLower(authHeader), model.HEADER_TOKEN+" ") { token = authHeader[len(model.HEADER_TOKEN)+1:] - } else if cookie, _ := r.Cookie(model.SESSION_COOKIE_TOKEN); cookie != nil && (r.Method == "GET" || r.Header.Get(model.HEADER_REQUESTED_WITH) == model.HEADER_REQUESTED_WITH_XML) { + } else if cookie, _ := r.Cookie(model.SESSION_COOKIE_TOKEN); cookie != nil { token = cookie.Value + cookieAuth = true } else { token = r.URL.Query().Get("access_token") } r.Header.Del("Mattermost-User-Id") if token != "" { - if session, err := a.GetSession(token); session != nil && err == nil { + session, err := a.GetSession(token) + csrfCheckPassed := true + + if err == nil && cookieAuth && r.Method != "GET" && r.Header.Get(model.HEADER_REQUESTED_WITH) != model.HEADER_REQUESTED_WITH_XML { + bodyBytes, _ := ioutil.ReadAll(r.Body) + r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) + r.ParseForm() + sentToken := r.FormValue("csrf") + expectedToken := session.GetCSRF() + + if sentToken != expectedToken { + csrfCheckPassed = false + } + + // Set Request Body again, since otherwise form values aren't accessible in plugin handler + r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) + } + + if session != nil && err == nil && csrfCheckPassed { r.Header.Set("Mattermost-User-Id", session.UserId) + context.SessionId = session.Id } } @@ -76,5 +100,5 @@ func (a *App) servePluginRequest(w http.ResponseWriter, r *http.Request, handler r.URL.RawQuery = newQuery.Encode() r.URL.Path = strings.TrimPrefix(r.URL.Path, path.Join(subpath, "plugins", params["plugin_id"])) - handler(&plugin.Context{}, w, r) + handler(context, w, r) } -- cgit v1.2.3-1-g7c22