提交 83ca1abb 编写于 作者: I ItalyPaleAle 提交者: Artur Souza

Fixed API token authentication bypassed when path contains `/healthz`

The APITokenAuthMiddleware allowed bypassing the check if the path included `/healthz`. An attacker only needed to include `/healthz` in the URL, even the querystring, to bypass the API token check, for example `/v1.0/invoke/myapp/method/something?foo=/healthz`.

Additionally, this was not checking the method of the request, so requests to `POST /healthz` would cause a service invocation to happen.

This fixes the issue by making the check a lot more strict. The API token check can be bypassed only if:

- The path is exactly `/v1.0/healthz` or `/v1.0/healthz/outbound` (slashes are trimmed on each side)
- The method is `GET`
Signed-off-by: NItalyPaleAle <43508+ItalyPaleAle@users.noreply.github.com>
上级 9dbd0ab8
......@@ -2,7 +2,8 @@
This update contains security fixes:
- [Security: Potential DoS in avro dependency (CVE-2023-37475)](#security-potential-dos-in-avro-dependency-cve-2023-37475)
- [Security: API token authentication bypass in HTTP endpoints](#security-api-token-authentication-bypass-in-http-endpoints) ([Security advisory](https://github.com/dapr/dapr/security/advisories/GHSA-59m6-82qm-vqgj))
- [Security: Potential DoS in avro dependency](#security-potential-dos-in-avro-dependency-cve-2023-37475) ([CVE-2023-37475](https://github.com/hamba/avro/security/advisories/GHSA-9x44-9pgq-cf45))
Additionally, this patch release contains bug fixes:
......@@ -10,6 +11,26 @@ Additionally, this patch release contains bug fixes:
- [Fixed: Workflows not working in some Kubernetes clusters](#fixed-workflows-not-working-in-some-kubernetes-clusters)
- [Fixed a number of bugs in the gRPC Configuration Subscribe API](#fixed-a-number-of-bugs-in-the-grpc-configuration-subscribe-api)
## Security: API token authentication bypass in HTTP endpoints
### Problem
[Security advisory](https://github.com/dapr/dapr/security/advisories/GHSA-59m6-82qm-vqgj)
A high-severity vulnerability has been found in Dapr that allows bypassing [API token authentication](https://docs.dapr.io/operations/security/api-token/), which is used by the Dapr sidecar to authenticate calls coming from the application, with a well-crafted HTTP request.
### Impact
The vulnerability impacts all users on Dapr <=1.10.9 and <=1.11.2 who are using API token authentication.
### Root cause
The Dapr sidecar allowed all requests containing `/healthz` in the URL (including query string) to bypass API token authentication.
### Solution
We have changed the API token authentication middleware to allow bypassing the authentication only for healthcheck endpoints more strictly.
## Security: Potential DoS in avro dependency (CVE-2023-37475)
### Problem
......
......@@ -287,12 +287,29 @@ func useAPIAuthentication(next fasthttp.RequestHandler) fasthttp.RequestHandler
return func(ctx *fasthttp.RequestCtx) {
v := ctx.Request.Header.Peek(authConsts.APITokenHeader)
if auth.ExcludedRoute(string(ctx.Request.URI().FullURI())) || string(v) == token {
ctx.Request.Header.Del(authConsts.APITokenHeader)
next(ctx)
} else {
if string(v) != token && !isRouteExcludedFromAPITokenAuth(string(ctx.Request.Header.Method()), string(ctx.Request.URI().FullURI())) {
ctx.Error("invalid api token", http.StatusUnauthorized)
return
}
ctx.Request.Header.Del(authConsts.APITokenHeader)
next(ctx)
}
}
func isRouteExcludedFromAPITokenAuth(method string, urlString string) bool {
u, err := url.Parse(urlString)
if err != nil {
return false
}
path := strings.Trim(u.Path, "/")
switch path {
case apiVersionV1 + "/healthz":
return method == http.MethodGet
case apiVersionV1 + "/healthz/outbound":
return method == http.MethodGet
default:
return false
}
}
......
......@@ -15,13 +15,10 @@ package security
import (
"os"
"strings"
"github.com/dapr/dapr/pkg/runtime/security/consts"
)
var excludedRoutes = []string{"/healthz"}
// GetAPIToken returns the value of the api token from an environment variable.
func GetAPIToken() string {
return os.Getenv(consts.APITokenEnvVar)
......@@ -31,13 +28,3 @@ func GetAPIToken() string {
func GetAppToken() string {
return os.Getenv(consts.AppAPITokenEnvVar)
}
// ExcludedRoute returns whether a given route should be excluded from a token check.
func ExcludedRoute(route string) bool {
for _, r := range excludedRoutes {
if strings.Contains(route, r) {
return true
}
}
return false
}
......@@ -54,17 +54,3 @@ func TestAppToken(t *testing.T) {
assert.Equal(t, "", token)
})
}
func TestExcludedRoute(t *testing.T) {
t.Run("healthz route is excluded", func(t *testing.T) {
route := "v1.0/healthz"
excluded := ExcludedRoute(route)
assert.True(t, excluded)
})
t.Run("custom route is not excluded", func(t *testing.T) {
route := "v1.0/state"
excluded := ExcludedRoute(route)
assert.False(t, excluded)
})
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册