浏览代码

cmd/syncthing: Add some common security releated HTTP headers (fixes #4360)

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4361
Jakob Borg 8 年之前
父节点
当前提交
429cc20eb7
共有 3 个文件被更改,包括 40 次插入18 次删除
  1. 23 2
      cmd/syncthing/gui.go
  2. 6 6
      cmd/syncthing/gui_statics.go
  3. 11 10
      lib/config/guiconfiguration.go

+ 23 - 2
cmd/syncthing/gui.go

@@ -332,7 +332,7 @@ func (s *apiService) Serve() {
 	}
 
 	// Add the CORS handling
-	handler = corsMiddleware(handler)
+	handler = corsMiddleware(handler, guiCfg.InsecureAllowFrameLoading)
 
 	if addressIsLocalhost(guiCfg.Address()) && !guiCfg.InsecureSkipHostCheck {
 		// Verify source host
@@ -459,7 +459,7 @@ func debugMiddleware(h http.Handler) http.Handler {
 	})
 }
 
-func corsMiddleware(next http.Handler) http.Handler {
+func corsMiddleware(next http.Handler, allowFrameLoading bool) http.Handler {
 	// Handle CORS headers and CORS OPTIONS request.
 	// CORS OPTIONS request are typically sent by browser during AJAX preflight
 	// when the browser initiate a POST request.
@@ -486,6 +486,27 @@ func corsMiddleware(next http.Handler) http.Handler {
 			return
 		}
 
+		// Other security related headers that should be present.
+		// https://www.owasp.org/index.php/Security_Headers
+
+		if !allowFrameLoading {
+			// We don't want to be rendered in an <iframe>,
+			// <frame> or <object>. (Unless we do it ourselves.
+			// This is also an escape hatch for people who serve
+			// Syncthing GUI as part of their own website
+			// through a proxy, so they don't need to set the
+			// allowFrameLoading bool.)
+			w.Header().Set("X-Frame-Options", "SAMEORIGIN")
+		}
+
+		// If the browser senses an XSS attack it's allowed to take
+		// action. (How this would not always be the default I
+		// don't fully understand.)
+		w.Header().Set("X-XSS-Protection", "1; mode=block")
+
+		// Our content type headers are correct. Don't guess.
+		w.Header().Set("X-Content-Type-Options", "nosniff")
+
 		// For everything else, pass to the next handler
 		next.ServeHTTP(w, r)
 		return

+ 6 - 6
cmd/syncthing/gui_statics.go

@@ -141,17 +141,17 @@ func (s *staticsServer) serveThemes(w http.ResponseWriter, r *http.Request) {
 func (s *staticsServer) mimeTypeForFile(file string) string {
 	// We use a built in table of the common types since the system
 	// TypeByExtension might be unreliable. But if we don't know, we delegate
-	// to the system.
+	// to the system. All our files are UTF-8.
 	ext := filepath.Ext(file)
 	switch ext {
 	case ".htm", ".html":
-		return "text/html"
+		return "text/html; charset=utf-8"
 	case ".css":
-		return "text/css"
+		return "text/css; charset=utf-8"
 	case ".js":
-		return "application/javascript"
+		return "application/javascript; charset=utf-8"
 	case ".json":
-		return "application/json"
+		return "application/json; charset=utf-8"
 	case ".png":
 		return "image/png"
 	case ".ttf":
@@ -159,7 +159,7 @@ func (s *staticsServer) mimeTypeForFile(file string) string {
 	case ".woff":
 		return "application/x-font-woff"
 	case ".svg":
-		return "image/svg+xml"
+		return "image/svg+xml; charset=utf-8"
 	default:
 		return mime.TypeByExtension(ext)
 	}

+ 11 - 10
lib/config/guiconfiguration.go

@@ -13,16 +13,17 @@ import (
 )
 
 type GUIConfiguration struct {
-	Enabled               bool   `xml:"enabled,attr" json:"enabled" default:"true"`
-	RawAddress            string `xml:"address" json:"address" default:"127.0.0.1:8384"`
-	User                  string `xml:"user,omitempty" json:"user"`
-	Password              string `xml:"password,omitempty" json:"password"`
-	RawUseTLS             bool   `xml:"tls,attr" json:"useTLS"`
-	APIKey                string `xml:"apikey,omitempty" json:"apiKey"`
-	InsecureAdminAccess   bool   `xml:"insecureAdminAccess,omitempty" json:"insecureAdminAccess"`
-	Theme                 string `xml:"theme" json:"theme" default:"default"`
-	Debugging             bool   `xml:"debugging,attr" json:"debugging"`
-	InsecureSkipHostCheck bool   `xml:"insecureSkipHostcheck,omitempty" json:"insecureSkipHostcheck"`
+	Enabled                   bool   `xml:"enabled,attr" json:"enabled" default:"true"`
+	RawAddress                string `xml:"address" json:"address" default:"127.0.0.1:8384"`
+	User                      string `xml:"user,omitempty" json:"user"`
+	Password                  string `xml:"password,omitempty" json:"password"`
+	RawUseTLS                 bool   `xml:"tls,attr" json:"useTLS"`
+	APIKey                    string `xml:"apikey,omitempty" json:"apiKey"`
+	InsecureAdminAccess       bool   `xml:"insecureAdminAccess,omitempty" json:"insecureAdminAccess"`
+	Theme                     string `xml:"theme" json:"theme" default:"default"`
+	Debugging                 bool   `xml:"debugging,attr" json:"debugging"`
+	InsecureSkipHostCheck     bool   `xml:"insecureSkipHostcheck,omitempty" json:"insecureSkipHostcheck"`
+	InsecureAllowFrameLoading bool   `xml:"insecureAllowFrameLoading,omitempty" json:"insecureAllowFrameLoading"`
 }
 
 func (c GUIConfiguration) Address() string {