From b00bc407c4e83444bf21a090f4170fd20717b7df Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Mon, 6 Apr 2020 13:31:49 +0200 Subject: [PATCH] http: block all ^Mozilla user agents without Origin nor Referer --- http/config.go | 36 +++++++++--------------------------- http/errors_test.go | 13 ++++++++----- 2 files changed, 17 insertions(+), 32 deletions(-) diff --git a/http/config.go b/http/config.go index a3a2501..6dc3877 100644 --- a/http/config.go +++ b/http/config.go @@ -15,19 +15,6 @@ const ( ACACredentials = "Access-Control-Allow-Credentials" ) -// disallowedUserAgents specifies a denylist of user agents that are not -// allowed to perform POST requests if they are not providing Origin -// and/or Referer headers. As mitigation for things like -// https://bugzilla.mozilla.org/show_bug.cgi?id=429594. Defaults to -// Firefox-related things. The matching against the user-agent string -// is made with strings.Contains(). -var disallowedUserAgents = []string{ - "Firefox", - "Focus", - "Klar", - "FxiOS", -} - type ServerConfig struct { // APIPath is the prefix of all request paths. // Example: host:port/api/v0/add. Here the APIPath is /api/v0 @@ -44,14 +31,6 @@ type ServerConfig struct { // websites to include resources from the API but not _read_ them. AllowGet bool - // DisallowUserAgents specifies a blacklist of user agents that are not - // allowed to perform POST requests if they are not providing Origin - // and/or Referer headers. As mitigation for things like - // https://bugzilla.mozilla.org/show_bug.cgi?id=429594. - // Defaults to ["Firefox"]. The matching against the user-agent - // string is made with strings.Contains(). - DisallowUserAgents []string - // corsOpts is a set of options for CORS headers. corsOpts *cors.Options @@ -191,12 +170,15 @@ func allowUserAgent(r *http.Request, cfg *ServerConfig) bool { return true } - // If not, check that request is not from a blacklisted UA. + // Allow if the user agent does not start with Mozilla... (i.e. curl) ua := r.Header.Get("User-agent") - for _, forbiddenUA := range disallowedUserAgents { - if strings.Contains(ua, forbiddenUA) { - return false - } + if !strings.HasPrefix(ua, "Mozilla") { + return true } - return true + + // Disallow otherwise. + // + // This means the request probably came from a browser and thus, it + // should have included Origin or referer headers. + return false } diff --git a/http/errors_test.go b/http/errors_test.go index c55d423..48b8359 100644 --- a/http/errors_test.go +++ b/http/errors_test.go @@ -174,7 +174,7 @@ func TestUnhandledMethod(t *testing.T) { func TestDisallowedUserAgents(t *testing.T) { tcs := []httpTestCase{ { - // Block Firefox + // Block Mozilla* browsers that do not provide origins. Method: "POST", AllowGet: false, Code: http.StatusForbidden, @@ -192,10 +192,13 @@ func TestDisallowedUserAgents(t *testing.T) { }, }, { - // Do not block Chrome - Method: "POST", - AllowGet: false, - Code: http.StatusOK, + // Do not block a Mozilla* browser that provides an + // allowed Origin + Method: "POST", + AllowGet: false, + AllowOrigins: []string{"*"}, + Origin: "null", + Code: http.StatusOK, ReqHeaders: map[string]string{ "User-Agent": "Mozilla/5.0 (Linux; U; Android 4.1.1; en-gb; Build/KLP) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30", }, -- GitLab