From 0593b8b0e4279cf015140229795a09df6e3ca8f1 Mon Sep 17 00:00:00 2001
From: jingrui <jingrui@huawei.com>
Date: Mon, 12 Aug 2019 19:13:00 +0800
Subject: [PATCH] docker: [backport] fix CVE-2019-13509

ref:
https://github.com/moby/moby/commit/e4b9edd31fdba3adf1e39fb9874f73d391f0ff34

Commit 77b8465d7e68ca102d7aae839c7b3fe0ecd28398 added a secret update
endpoint to allow updating labels on existing secrets. However, when
implementing the endpoint, the DebugRequestMiddleware was not updated
to scrub the Data field (as is being done when creating a secret).

When updating a secret (to set labels), the Data field should be either
`nil` (not set), or contain the same value as the existing secret. In
situations where the Data field is set, and the `dockerd` daemon is
running with debugging enabled / log-level debug, the base64-encoded
value of the secret is printed to the daemon logs.

The docker cli does not have a `docker secret update` command, but
when using `docker stack deploy`, the docker cli sends the secret
data both when _creating_ a stack, and when _updating_ a stack, thus
leaking the secret data if the daemon runs with debug enabled:
...

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit c7ce4be93ae8edd2da62a588e01c67313a4aba0c)
Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 73db8c77bfb2d0cbdf71ce491f3d3e66c9dd5be6)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Upstream-commit: 32b40c53662e733b4627b0b303c71b52484a31f4

Change-Id: If571264d227f41cbdcf7dceaa56d7b10ec2a3ee7
Signed-off-by: jingrui <jingrui@huawei.com>
---
 .../engine/api/server/middleware/debug.go     | 24 +++++++++++--------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/components/engine/api/server/middleware/debug.go b/components/engine/api/server/middleware/debug.go
index 2cef1d46c3..31165bf918 100644
--- a/components/engine/api/server/middleware/debug.go
+++ b/components/engine/api/server/middleware/debug.go
@@ -71,9 +71,22 @@ func maskSecretKeys(inp interface{}, path string) {
 	}
 
 	if form, ok := inp.(map[string]interface{}); ok {
+		scrub := []string{
+			// Note: The Data field contains the base64-encoded secret in 'secret'
+			// and 'config' create and update requests. Currently, no other POST
+			// API endpoints use a data field, so we scrub this field unconditionally.
+			// Change this handling to be conditional if a new endpoint is added
+			// in future where this field should not be scrubbed.
+			"data",
+			"jointoken",
+			"password",
+			"secret",
+			"signingcakey",
+			"unlockkey",
+		}
 	loop0:
 		for k, v := range form {
-			for _, m := range []string{"password", "secret", "jointoken", "unlockkey", "signingcakey"} {
+			for _, m := range scrub {
 				if strings.EqualFold(m, k) {
 					form[k] = "*****"
 					continue loop0
@@ -81,14 +94,5 @@ func maskSecretKeys(inp interface{}, path string) {
 			}
 			maskSecretKeys(v, path)
 		}
-
-		// Route-specific redactions
-		if strings.HasSuffix(path, "/secrets/create") {
-			for k := range form {
-				if k == "Data" {
-					form[k] = "*****"
-				}
-			}
-		}
 	}
 }
-- 
2.17.1

