CVE-2020-24711 (published 2020-10-28T20:15Z)

The Reset button on the Account Settings page in Gophish before 0.11.0 allows attackers to cause a denial of service via a clickjacking attack

Severity: MEDIUM
CVSS v2 base score: 4.3 (AV:N/AC:M/Au:N/C:N/I:N/A:P)
CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H)

Weakness information:
cwe_id: CWE-1021
cwe_name: Improper Restriction of Rendered UI Layers or Frames
description: The web application does not restrict or incorrectly restricts frame objects or UI layers that belong to another application or domain, which can lead to user confusion about which interface the user is interacting with.
extended_description: A web application is expected to place restrictions on whether it is allowed to be rendered within frames, iframes, objects, embed or applet elements. Without the restrictions, users can be tricked into interacting with the application when they were not intending to.
         

Fix information:
repo_url: https://github.com/gophish/gophish
commit_details: repo_url: https://github.com/gophish/gophish
author: Jordan Wright
author_date: 2020-08-20 10:39:23-05:00
msg: Added a simple Content-Security-Policy to mitigate clickjacking attempts.
repository: repo_url: https://github.com/gophish/gophish
repo_name: gophish/gophish
description: Open-Source Phishing Toolkit
repo_language: Go
owner: gophish
file_changes: filename: route.go
change_type: ModificationType.MODIFY
diff: @@ -155,7 +155,7 @@ func (as *AdminServer) registerRoutes() {
 		csrf.FieldName("csrf_token"),
 		csrf.Secure(as.config.UseTLS))
 	adminHandler := csrfHandler(router)
-	adminHandler = mid.Use(adminHandler.ServeHTTP, mid.CSRFExceptions, mid.GetContext)
+	adminHandler = mid.Use(adminHandler.ServeHTTP, mid.CSRFExceptions, mid.GetContext, mid.ApplySecurityHeaders)
 
 	// Setup GZIP compression
 	gzipWrapper, _ := gziphandler.NewGzipLevelHandler(gzip.BestCompression)

programming_language: Go
filename: middleware.go
change_type: ModificationType.MODIFY
diff: @@ -176,6 +176,17 @@ func RequirePermission(perm string) func(http.Handler) http.HandlerFunc {
 	}
 }
 
+// ApplySecurityHeaders applies various security headers according to best-
+// practices.
+func ApplySecurityHeaders(next http.Handler) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		csp := "frame-ancestors 'none';"
+		w.Header().Set("Content-Security-Policy", csp)
+		w.Header().Set("X-Frame-Options", "DENY")
+		next.ServeHTTP(w, r)
+	}
+}
+
 // JSONError returns an error in JSON format with the given
 // status code and message
 func JSONError(w http.ResponseWriter, c int, m string) {

programming_language: Go
filename: middleware_test.go
change_type: ModificationType.MODIFY
diff: @@ -181,3 +181,19 @@ func TestPasswordResetRequired(t *testing.T) {
 		t.Fatalf("incorrect location header received. expected %s got %s", expectedLocation, gotLocation)
 	}
 }
+
+func TestApplySecurityHeaders(t *testing.T) {
+	expected := map[string]string{
+		"Content-Security-Policy": "frame-ancestors 'none';",
+		"X-Frame-Options":         "DENY",
+	}
+	req := httptest.NewRequest(http.MethodGet, "/", nil)
+	response := httptest.NewRecorder()
+	ApplySecurityHeaders(successHandler).ServeHTTP(response, req)
+	for header, value := range expected {
+		got := response.Header().Get(header)
+		if got != value {
+			t.Fatalf("incorrect security header received for %s: expected %s got %s", header, value, got)
+		}
+	}
+}

programming_language: Go