From 08811a6da78c3f1f973b8f50a337ff4dc4ed9e2c Mon Sep 17 00:00:00 2001 From: Brian Picciano Date: Tue, 24 May 2022 17:42:00 -0600 Subject: [PATCH] Replace CSRF token checking with Referer checking --- srv/src/http/api.go | 5 +-- srv/src/http/csrf.go | 64 ++++----------------------------- srv/src/http/tpl.go | 18 ++-------- srv/src/http/tpl/assets.html | 6 ---- srv/src/http/tpl/edit-post.html | 4 --- srv/src/http/tpl/load-csrf.html | 13 ------- srv/src/http/tpl/posts.html | 5 --- 7 files changed, 10 insertions(+), 105 deletions(-) delete mode 100644 srv/src/http/tpl/load-csrf.html diff --git a/srv/src/http/api.go b/srv/src/http/api.go index da54c9c..4143200 100644 --- a/srv/src/http/api.go +++ b/srv/src/http/api.go @@ -164,8 +164,6 @@ func (a *api) Shutdown(ctx context.Context) error { func (a *api) apiHandler() http.Handler { mux := http.NewServeMux() - mux.Handle("/csrf", a.getCSRFTokenHandler()) - mux.Handle("/pow/challenge", a.newPowChallengeHandler()) mux.Handle("/pow/check", a.requirePowMiddleware( @@ -250,11 +248,10 @@ func (a *api) handler() http.Handler { h := apiutil.MethodMux(map[string]http.Handler{ "GET": applyMiddlewares( mux, - setCSRFMiddleware, ), "*": applyMiddlewares( mux, - checkCSRFMiddleware, + a.checkCSRFMiddleware, addResponseHeadersMiddleware(map[string]string{ "Cache-Control": "no-store, max-age=0", "Pragma": "no-cache", diff --git a/srv/src/http/csrf.go b/srv/src/http/csrf.go index 7a45269..d0f7b6a 100644 --- a/srv/src/http/csrf.go +++ b/srv/src/http/csrf.go @@ -3,76 +3,26 @@ package http import ( "errors" "net/http" + "net/url" "github.com/mediocregopher/blog.mediocregopher.com/srv/http/apiutil" ) -const ( - csrfTokenCookieName = "csrf_token" - csrfTokenHeaderName = "X-CSRF-Token" - csrfTokenFormName = "csrfToken" -) - -func setCSRFMiddleware(h http.Handler) http.Handler { +func (a *api) checkCSRFMiddleware(h http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - csrfTok, err := apiutil.GetCookie(r, csrfTokenCookieName, "") - + refererURL, err := url.Parse(r.Referer()) if err != nil { - apiutil.InternalServerError(rw, r, err) - return - - } else if csrfTok == "" { - http.SetCookie(rw, &http.Cookie{ - Name: csrfTokenCookieName, - Value: apiutil.RandStr(32), - Secure: true, - }) - } - - h.ServeHTTP(rw, r) - }) -} - -func checkCSRFMiddleware(h http.Handler) http.Handler { - return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - - csrfTok, err := apiutil.GetCookie(r, csrfTokenCookieName, "") - - if err != nil { - apiutil.InternalServerError(rw, r, err) + apiutil.BadRequest(rw, r, errors.New("invalid Referer")) return } - givenCSRFTok := r.Header.Get(csrfTokenHeaderName) - if givenCSRFTok == "" { - givenCSRFTok = r.FormValue(csrfTokenFormName) - } - - if csrfTok == "" || givenCSRFTok != csrfTok { - apiutil.BadRequest(rw, r, errors.New("invalid CSRF token")) + if refererURL.Scheme != a.params.PublicURL.Scheme || + refererURL.Host != a.params.PublicURL.Host { + apiutil.BadRequest(rw, r, errors.New("invalid Referer")) return } h.ServeHTTP(rw, r) }) } - -func (a *api) getCSRFTokenHandler() http.Handler { - - return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { - - csrfTok, err := apiutil.GetCookie(r, csrfTokenCookieName, "") - - if err != nil { - apiutil.InternalServerError(rw, r, err) - return - } - - apiutil.JSONResult(rw, r, struct { - CSRFToken string - }{ - CSRFToken: csrfTok, - }) - }) -} diff --git a/srv/src/http/tpl.go b/srv/src/http/tpl.go index 8654569..fb0f5bd 100644 --- a/srv/src/http/tpl.go +++ b/srv/src/http/tpl.go @@ -5,7 +5,6 @@ import ( "fmt" "html/template" "io/fs" - "log" "net/http" "path/filepath" "strings" @@ -100,21 +99,12 @@ func (a *api) mustParseTpl(name string) *template.Template { func (a *api) mustParseBasedTpl(name string) *template.Template { tpl := a.mustParseTpl(name) - tpl = template.Must(tpl.New("load-csrf.html").Parse(mustReadTplFile("load-csrf.html"))) tpl = template.Must(tpl.New("base.html").Parse(mustReadTplFile("base.html"))) return tpl } type tplData struct { - Payload interface{} - CSRFToken string -} - -func (t tplData) CSRFFormInput() template.HTML { - return template.HTML(fmt.Sprintf( - ``, - csrfTokenFormName, - )) + Payload interface{} } // executeTemplate expects to be the final action in an http.Handler @@ -123,11 +113,8 @@ func executeTemplate( tpl *template.Template, payload interface{}, ) { - csrfToken, _ := apiutil.GetCookie(r, csrfTokenCookieName, "") - tplData := tplData{ - Payload: payload, - CSRFToken: csrfToken, + Payload: payload, } if err := tpl.Execute(rw, tplData); err != nil { @@ -141,7 +128,6 @@ func executeTemplate( func (a *api) executeRedirectTpl( rw http.ResponseWriter, r *http.Request, url string, ) { - log.Printf("here url:%q", url) executeTemplate(rw, r, a.redirectTpl, struct { URL string }{ diff --git a/srv/src/http/tpl/assets.html b/srv/src/http/tpl/assets.html index 86e0ba5..41d470c 100644 --- a/srv/src/http/tpl/assets.html +++ b/srv/src/http/tpl/assets.html @@ -1,7 +1,5 @@ {{ define "body" }} -{{ $csrfFormInput := .CSRFFormInput }} -

Upload Asset

@@ -10,7 +8,6 @@

- {{ $csrfFormInput }}
@@ -37,7 +34,6 @@ method="POST" style="margin-bottom: 0;" > - {{ $csrfFormInput }} @@ -46,8 +42,6 @@ -{{ template "load-csrf.html" . }} - {{ end }} {{ template "base.html" . }} diff --git a/srv/src/http/tpl/edit-post.html b/srv/src/http/tpl/edit-post.html index 48af882..1a81df4 100644 --- a/srv/src/http/tpl/edit-post.html +++ b/srv/src/http/tpl/edit-post.html @@ -2,8 +2,6 @@
- {{ .CSRFFormInput }} -
@@ -99,8 +97,6 @@ - {{ template "load-csrf.html" . }} - {{ end }} {{ template "base.html" . }} diff --git a/srv/src/http/tpl/load-csrf.html b/srv/src/http/tpl/load-csrf.html deleted file mode 100644 index b0757f9..0000000 --- a/srv/src/http/tpl/load-csrf.html +++ /dev/null @@ -1,13 +0,0 @@ - - - diff --git a/srv/src/http/tpl/posts.html b/srv/src/http/tpl/posts.html index 0609ff6..885018d 100644 --- a/srv/src/http/tpl/posts.html +++ b/srv/src/http/tpl/posts.html @@ -18,8 +18,6 @@ {{ define "body" }} - {{ $csrfFormInput := .CSRFFormInput }} -

@@ -44,7 +42,6 @@ action="{{ PostURL .ID }}?method=delete" method="POST" > - {{ $csrfFormInput }} @@ -55,8 +52,6 @@ {{ template "posts-nextprev" . }} - {{ template "load-csrf.html" . }} - {{ end }} {{ template "base.html" . }}