From 6a4c1e54d9ee4a50eb989fc10a920f45c4aa48ce Mon Sep 17 00:00:00 2001 From: Henry Date: Tue, 16 Feb 2021 14:12:59 +0100 Subject: [PATCH] add default CSP and some other browser mitigations Though, CSP is primarily a tool against cross-site scripting and we don't plan to host any user-generated or 3rd party content it's still a good practice. The primary requirment with this rule is to move all inline style tags to a seperate file. --- cmd/server/main.go | 42 ++++++++++++++++++++++++++++++++++++++++-- go.mod | 1 + go.sum | 3 +++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 212b3ec..9a1f679 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -26,6 +26,7 @@ import ( kitlog "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" _ "github.com/mattn/go-sqlite3" + "github.com/unrolled/secure" "go.cryptoscope.co/muxrpc/v2/debug" "github.com/ssb-ngi-pointer/go-ssb-room/admindb/sqlite" @@ -42,6 +43,10 @@ var ( listenAddrShsMux string listenAddrHTTP string + httpsDomain string + + development bool + listenAddrDebug string logToFile string repoDir string @@ -90,6 +95,9 @@ func initFlags() { flag.StringVar(&listenAddrDebug, "dbg", "localhost:6078", "listen addr for metrics and pprof HTTP server") flag.StringVar(&logToFile, "logs", "", "where to write debug output to (default is just stderr)") + flag.StringVar(&httpsDomain, "https-domain", "", "which domain to use for TLS and AllowedHosts checks") + flag.BoolVar(&development, "development", false, "enable development mode (disable security checks)") + flag.BoolVar(&flagPrintVersion, "version", false, "print version number and build date") flag.Parse() @@ -118,6 +126,10 @@ func runroomsrv() error { return nil } + if httpsDomain == "" && !development { + return fmt.Errorf("https-domain can't be empty. See '%s -h' for a full list of options", os.Args[0]) + } + ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -213,7 +225,33 @@ func runroomsrv() error { return fmt.Errorf("failed to create HTTPdashboard handler: %w", err) } - // TODO: setup other http goodies (such as CSRF and CSP) + // setup CSP and HTTPS redirects + secureMiddleware := secure.New(secure.Options{ + IsDevelopment: development, + + AllowedHosts: []string{httpsDomain}, + + // TLS stuff + SSLRedirect: true, + SSLHost: httpsDomain, + + // Important for reverse-proxy setups (when nginx or similar does the TLS termination) + SSLProxyHeaders: map[string]string{"X-Forwarded-Proto": "https"}, + HostsProxyHeaders: []string{"X-Forwarded-Host"}, + + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security + STSSeconds: 2592000, // 30 days in seconds (TODO configure?) + STSPreload: false, // don't submit to googles list service (TODO configure?) + // TODO configure (could be needed in special setups where the room is a subdomain of a site) + STSIncludeSubdomains: false, + + // See for more https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP + ContentSecurityPolicy: "default-src 'self'", // enforce no external content + + BrowserXssFilter: true, + FrameDeny: true, + //ContentTypeNosniff: true, // TODO: fix Content-Type headers served from assets + }) level.Info(log).Log( "event", "serving", @@ -234,7 +272,7 @@ func runroomsrv() error { ReadTimeout: time.Second * 15, IdleTimeout: time.Second * 60, - Handler: dashboardH, + Handler: secureMiddleware.Handler(dashboardH), } err = srv.Serve(httpLis) diff --git a/go.mod b/go.mod index 81e0e72..d9dd6db 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 // indirect github.com/stretchr/testify v1.6.1 + github.com/unrolled/secure v1.0.8 github.com/volatiletech/sqlboiler/v4 v4.4.0 github.com/volatiletech/strmangle v0.0.1 go.cryptoscope.co/muxrpc/v2 v2.0.0-20210202162901-fe642d405dc6 diff --git a/go.sum b/go.sum index 22b19a5..4a485e6 100644 --- a/go.sum +++ b/go.sum @@ -399,8 +399,11 @@ github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/o github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v0.0.0-20190126102652-8fd0f8d918c8/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA= github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI= +github.com/unrolled/secure v1.0.8 h1:JaMvKbe4CRt8oyxVXn+xY+6jlqd7pyJNSVkmsBxxQsM= +github.com/unrolled/secure v1.0.8/go.mod h1:fO+mEan+FLB0CdEnHf6Q4ZZVNqG+5fuLFnP8p0BXDPI= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/volatiletech/inflect v0.0.1 h1:2a6FcMQyhmPZcLa+uet3VJ8gLn/9svWhJxJYwvE8KsU= github.com/volatiletech/inflect v0.0.1/go.mod h1:IBti31tG6phkHitLlr5j7shC5SOo//x0AjDzaJU1PLA= github.com/volatiletech/null/v8 v8.1.0 h1:eAO3I31A5R04usY5SKMMfDcOCnEGyT/T4wRI0JVGp4U=