From e4cf02cde728d1d23b8eed57dd2ebaf296349e7f Mon Sep 17 00:00:00 2001 From: mappu Date: Sun, 13 Aug 2017 18:25:58 +1200 Subject: [PATCH] restructure error handling to prevent reflected XSS --- pageTemplate.go | 10 +++++++++- rErrors.go | 25 ++++++++++++++++--------- rHistory.go | 4 ++-- rView.go | 2 +- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/pageTemplate.go b/pageTemplate.go index 11f5ba7..fddbf91 100644 --- a/pageTemplate.go +++ b/pageTemplate.go @@ -17,7 +17,9 @@ type pageTemplateOptions struct { LoadCodeResources bool DefaultPage string AllowDownload bool - SessionMessage template.HTML + SessionMessage string + PageNotExistsError bool + PageNotExistsTarget string } func DefaultPageTemplateOptions(opts *ServerOptions) *pageTemplateOptions { @@ -105,6 +107,12 @@ function els(e,s){ // no js exec in innerHTML {{end}}
+{{if .PageNotExistsError}} +
+ No such article exists. + Click here to create it. +
+{{end}} {{if len .SessionMessage}}
{{.SessionMessage}}
{{end}} diff --git a/rErrors.go b/rErrors.go index 7bde339..2827147 100644 --- a/rErrors.go +++ b/rErrors.go @@ -8,12 +8,8 @@ import ( "time" ) -func (this *WikiServer) noSuchArticleError(title string) template.HTML { - return template.HTML(`No such article exists. Click here to create it.`) -} - -func (this *WikiServer) serveErrorMessage(w http.ResponseWriter, message error) { - this.serveErrorHTMLMessage(w, template.HTML(template.HTMLEscapeString(message.Error()))) +func (this *WikiServer) serveErrorMessage(w http.ResponseWriter, err error) { + this.serveErrorText(w, err.Error()) } func (this *WikiServer) serveInternalError(w http.ResponseWriter, r *http.Request, e error) { @@ -21,8 +17,12 @@ func (this *WikiServer) serveInternalError(w http.ResponseWriter, r *http.Reques http.Error(w, "An internal error occurred. Please ask an administrator to check the log file.", 500) } -func (this *WikiServer) serveErrorHTMLMessage(w http.ResponseWriter, msg template.HTML) { - this.serveRedirect(w, this.opts.ExpectBaseURL+"view/"+url.PathEscape(this.opts.DefaultPage)+"?error="+url.QueryEscape(string(msg))) +func (this *WikiServer) serveErrorText(w http.ResponseWriter, msg string) { + this.serveRedirect(w, this.opts.ExpectBaseURL+"view/"+url.PathEscape(this.opts.DefaultPage)+"?error="+url.QueryEscape(msg)) +} + +func (this *WikiServer) serveNoSuchArticle(w http.ResponseWriter, lookingFor string) { + this.serveRedirect(w, this.opts.ExpectBaseURL+"view/"+url.PathEscape(this.opts.DefaultPage)+"?notfound="+url.QueryEscape(lookingFor)) } func (this *WikiServer) serveRedirect(w http.ResponseWriter, location string) { @@ -32,7 +32,14 @@ func (this *WikiServer) serveRedirect(w http.ResponseWriter, location string) { func (this *WikiServer) servePageResponse(w http.ResponseWriter, r *http.Request, pto *pageTemplateOptions) { w.WriteHeader(200) - pto.SessionMessage = template.HTML(r.URL.Query().Get("error")) // FIXME reflected XSS (although Chrome automatically blocks it..) + + if noSuchArticleTarget, ok := r.URL.Query()["notfound"]; ok { + pto.PageNotExistsError = true + pto.PageNotExistsTarget = noSuchArticleTarget[0] + + } else { + pto.SessionMessage = r.URL.Query().Get("error") + } err := this.pageTmp.Execute(w, pto) if err != nil { diff --git a/rHistory.go b/rHistory.go index dedf7f5..ec51225 100644 --- a/rHistory.go +++ b/rHistory.go @@ -12,7 +12,7 @@ func (this *WikiServer) routeHistory(w http.ResponseWriter, r *http.Request, art revs, err := this.db.GetRevisionHistory(articleTitle) if err != nil { if err == sql.ErrNoRows { - this.serveErrorHTMLMessage(w, this.noSuchArticleError(articleTitle)) + this.serveNoSuchArticle(w, articleTitle) return } @@ -21,7 +21,7 @@ func (this *WikiServer) routeHistory(w http.ResponseWriter, r *http.Request, art } if len(revs) == 0 { - this.serveErrorHTMLMessage(w, this.noSuchArticleError(articleTitle)) + this.serveNoSuchArticle(w, articleTitle) return } diff --git a/rView.go b/rView.go index fa7b012..9e36fce 100644 --- a/rView.go +++ b/rView.go @@ -19,7 +19,7 @@ func (this *WikiServer) routeView(w http.ResponseWriter, r *http.Request, articl return } - this.serveErrorHTMLMessage(w, this.noSuchArticleError(articleTitle)) + this.serveNoSuchArticle(w, articleTitle) return } this.serveErrorMessage(w, err)