9.1 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
NONE
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
6.4 Medium
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
PARTIAL
Integrity Impact
PARTIAL
Availability Impact
NONE
AV:N/AC:L/Au:N/C:P/I:P/A:N
0.003 Low
EPSS
Percentile
68.5%
Hello go restful maintainer team, I would like to report a security concerning your CORS Filter feature.
Go restful allows user to specify a CORS Filter with a configurable AllowedDomains
param - which is an array of domains allowed in CORS policy.
However, although there’s is already another param called allowedOriginPatterns
used for matching origin using regular expression, all domains in AllowedDomains
is also used as regular expression to check for matching origin in this code in file cors_filter.go
:
if len(c.allowedOriginPatterns) == 0 {
// compile allowed domains to allowed origin patterns
allowedOriginRegexps, err := compileRegexps(c.AllowedDomains)
if err != nil {
return false
}
c.allowedOriginPatterns = allowedOriginRegexps
}
for _, pattern := range c.allowedOriginPatterns {
if allowed = pattern.MatchString(origin); allowed {
break
}
}
So by this, if the user input example.com
to be one of domain in AllowedDomains
, all domains starting with example.com
would be acceptable.
main.go
with this content:package main
import (
restful "github.com/emicklei/go-restful/v3"
"io"
"net/http"
)
func main() {
container := restful.NewContainer()
ws := new(restful.WebService)
ws.Route(ws.GET("hello").To(hello))
container.Add(ws)
server := &http.Server{Addr: ":8000", Handler: container}
//container.Filter(logHeaders)
cors := restful.CrossOriginResourceSharing{
ExposeHeaders: []string{"X-My-Header"},
AllowedDomains: []string{"example.com"},
CookiesAllowed: true,
Container: container,
}
container.Filter(cors.Filter)
server.ListenAndServe()
}
func hello(req *restful.Request, resp *restful.Response) {
io.WriteString(resp, "world")
}
In the above code, example.com
is configured as an allowed domain.
/hello
with Origin Header = example.com.hacker.domain
and see that the request gets throughHTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: example.com.hacker.domain
Access-Control-Expose-Headers: X-My-Header
Date: Mon, 07 Mar 2022 13:31:08 GMT
Content-Length: 5
Content-Type: text/plain; charset=utf-8
Connection: close
world
This vulnerability is capable of breaking CORS policy and thus allowing any page to make requests, retrieve data on behalf of other users.
9.1 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
NONE
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
6.4 Medium
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
PARTIAL
Integrity Impact
PARTIAL
Availability Impact
NONE
AV:N/AC:L/Au:N/C:P/I:P/A:N
0.003 Low
EPSS
Percentile
68.5%