From 08b6ef87fc919e974e233c31cab1a7421f00d385 Mon Sep 17 00:00:00 2001 From: wangkerong Date: Fri, 24 Sep 2021 14:19:51 +0800 Subject: [PATCH] fix cve-2021-3660 --- backport-0001-CVE-2021-3660.patch | 184 ++++++++++++++++++++++++++++++ backport-0002-CVE-2021-3660.patch | 142 +++++++++++++++++++++++ cockpit.spec | 10 +- 3 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 backport-0001-CVE-2021-3660.patch create mode 100644 backport-0002-CVE-2021-3660.patch diff --git a/backport-0001-CVE-2021-3660.patch b/backport-0001-CVE-2021-3660.patch new file mode 100644 index 0000000..e76e2ac --- /dev/null +++ b/backport-0001-CVE-2021-3660.patch @@ -0,0 +1,184 @@ +From b0b57c8093f180fa7d67fdd4efa2f1a13e296930 Mon Sep 17 00:00:00 2001 +From: Martin Pitt +Date: Tue, 14 Sep 2021 11:03:32 +0200 +Subject: [PATCH] bridge: Robust JSON object comparison in test-httpstream.c + +Comparing the received control message JSON against the expected value +in string form has always been brittle: It assumes a +predictable/reproducible GLib dictionary serialization. This will break +across different GLib versions once we add a new static header. + +So change the tests to compare the control message with +`cockpit_assert_json_eq()` (which will do parsing and deep object +comparison) instead of plain string comparison. Introduce a new +assert_channel_response() helper for this. + +Conflict:NA +Reference:https://github.com/cockpit-project/cockpit/pull/16348/commits/b0b57c8093f180fa7d67fdd4efa2f1a13e296930 +--- + src/bridge/test-httpstream.c | 69 ++++++++++++++++++++---------------- + 1 file changed, 38 insertions(+), 31 deletions(-) + +diff --git a/src/bridge/test-httpstream.c b/src/bridge/test-httpstream.c +index 53cd7bf..47af9ea 100644 +--- a/src/bridge/test-httpstream.c ++++ b/src/bridge/test-httpstream.c +@@ -30,6 +30,9 @@ + + #include + ++/* JSON dict snippet for headers that are present in every request */ ++#define STATIC_HEADERS "\"Cross-Origin-Resource-Policy\":\"same-origin\",\"Referrer-Policy\":\"no-referrer\",\"X-Content-Type-Options\":\"nosniff\",\"X-DNS-Prefetch-Control\":\"off\"" ++ + static void + on_closed_set_flag (CockpitChannel *channel, + const gchar *problem, +@@ -64,6 +67,24 @@ non_local_ip (void) + return str; + } + ++/* Compare subsequent "{ control JSON }" and "body" channel messages against expected values. */ ++static void ++assert_channel_response (MockTransport *transport, ++ const gchar *channel_id, ++ const gchar *expected_control, ++ const gchar *expected_body) ++{ ++ GBytes *data; ++ ++ data = mock_transport_pop_channel (transport, channel_id); ++ JsonNode *node = cockpit_json_parse (g_bytes_get_data (data, NULL), -1, NULL); ++ cockpit_assert_json_eq (json_node_get_object (node), expected_control); ++ json_node_unref (node); ++ ++ data = mock_transport_pop_channel (transport, channel_id); ++ cockpit_assert_bytes_eq (data, expected_body, -1); ++} ++ + static void + setup_general (TestGeneral *tt, + gconstpointer host_fixture) +@@ -116,8 +137,6 @@ test_host_header (TestGeneral *tt, + JsonObject *options; + const gchar *control; + gboolean closed; +- GBytes *data; +- guint count; + + if (tt->host == NULL) + { +@@ -154,11 +173,9 @@ test_host_header (TestGeneral *tt, + g_signal_connect (channel, "closed", G_CALLBACK (on_closed_set_flag), &closed); + while (!closed) + g_main_context_iteration (NULL, TRUE); +- +- data = mock_transport_combine_output (tt->transport, "444", &count); +- cockpit_assert_bytes_eq (data, "{\"status\":200,\"reason\":\"OK\",\"headers\":{\"X-DNS-Prefetch-Control\":\"off\",\"Referrer-Policy\":\"no-referrer\"}}Da Da Da", -1); +- g_assert_cmpuint (count, ==, 2); +- g_bytes_unref (data); ++ assert_channel_response (tt->transport, "444", ++ "{\"status\":200,\"reason\":\"OK\",\"headers\":{" STATIC_HEADERS "}}", ++ "Da Da Da"); + } + + static gboolean +@@ -340,11 +357,8 @@ test_http_chunked (void) + TestResult *tr = g_slice_new (TestResult); + + GBytes *bytes = NULL; +- GBytes *data = NULL; + + const gchar *control; +- gchar *expected = g_strdup_printf ("{\"status\":200,\"reason\":\"OK\",\"headers\":{\"X-DNS-Prefetch-Control\":\"off\",\"Referrer-Policy\":\"no-referrer\"}}%0*d", MAGIC_NUMBER, 0); +- guint count; + guint port; + + web_server = cockpit_web_server_new (NULL, 0, NULL, NULL, NULL); +@@ -387,12 +401,11 @@ test_http_chunked (void) + g_main_context_iteration (NULL, TRUE); + g_assert_cmpstr (tr->problem, ==, NULL); + +- data = mock_transport_combine_output (transport, "444", &count); +- cockpit_assert_bytes_eq (data, expected, -1); +- g_assert_cmpuint (count, ==, 2); ++ g_autofree gchar *expected_body = g_strdup_printf ("%0*d", MAGIC_NUMBER, 0); + +- g_bytes_unref (data); +- g_free (expected); ++ assert_channel_response (transport, "444", ++ "{\"status\":200,\"reason\":\"OK\",\"headers\":{" STATIC_HEADERS "}}", ++ expected_body); + + g_object_unref (transport); + g_object_add_weak_pointer (G_OBJECT (channel), (gpointer *)&channel); +@@ -509,7 +522,6 @@ test_tls_basic (TestTls *test, + JsonObject *options; + const gchar *control; + GBytes *bytes; +- GBytes *data; + + options = json_object_new (); + json_object_set_int_member (options, "port", test->port); +@@ -537,10 +549,9 @@ test_tls_basic (TestTls *test, + while (closed == FALSE) + g_main_context_iteration (NULL, TRUE); + +- data = mock_transport_combine_output (test->transport, "444", NULL); +- cockpit_assert_bytes_eq (data, "{\"status\":200,\"reason\":\"OK\",\"headers\":{\"X-DNS-Prefetch-Control\":\"off\",\"Referrer-Policy\":\"no-referrer\"}}Oh Marmalaade!", -1); +- +- g_bytes_unref (data); ++ assert_channel_response (test->transport, "444", ++ "{\"status\":200,\"reason\":\"OK\",\"headers\":{" STATIC_HEADERS "}}", ++ "Oh Marmalaade!"); + + g_object_add_weak_pointer (G_OBJECT (channel), (gpointer *)&channel); + g_object_unref (channel); +@@ -668,7 +679,6 @@ test_tls_certificate (TestTls *test, + GTlsCertificate *cert; + const gchar *control; + GBytes *bytes; +- GBytes *data; + + tls = cockpit_json_parse_object (json, -1, &error); + g_assert_no_error (error); +@@ -699,10 +709,9 @@ test_tls_certificate (TestTls *test, + while (closed == FALSE) + g_main_context_iteration (NULL, TRUE); + +- data = mock_transport_combine_output (test->transport, "444", NULL); +- cockpit_assert_bytes_eq (data, "{\"status\":200,\"reason\":\"OK\",\"headers\":{\"X-DNS-Prefetch-Control\":\"off\",\"Referrer-Policy\":\"no-referrer\"}}Oh Marmalaade!", -1); +- +- g_bytes_unref (data); ++ assert_channel_response (test->transport, "444", ++ "{\"status\":200,\"reason\":\"OK\",\"headers\":{" STATIC_HEADERS "}}", ++ "Oh Marmalaade!"); + + g_assert (test->peer != NULL); + +@@ -733,7 +742,6 @@ test_tls_authority_good (TestTls *test, + GError *error = NULL; + const gchar *control; + GBytes *bytes; +- GBytes *data; + + tls = cockpit_json_parse_object (json, -1, &error); + g_assert_no_error (error); +@@ -763,11 +771,10 @@ test_tls_authority_good (TestTls *test, + + while (closed == FALSE) + g_main_context_iteration (NULL, TRUE); +- +- data = mock_transport_combine_output (test->transport, "444", NULL); +- cockpit_assert_bytes_eq (data, "{\"status\":200,\"reason\":\"OK\",\"headers\":{\"X-DNS-Prefetch-Control\":\"off\",\"Referrer-Policy\":\"no-referrer\"}}Oh Marmalaade!", -1); +- +- g_bytes_unref (data); ++ ++ assert_channel_response (test->transport, "444", ++ "{\"status\":200,\"reason\":\"OK\",\"headers\":{" STATIC_HEADERS "}}", ++ "Oh Marmalaade!"); + + g_object_add_weak_pointer (G_OBJECT (channel), (gpointer *)&channel); + g_object_unref (channel); +-- +2.27.0 + diff --git a/backport-0002-CVE-2021-3660.patch b/backport-0002-CVE-2021-3660.patch new file mode 100644 index 0000000..6481457 --- /dev/null +++ b/backport-0002-CVE-2021-3660.patch @@ -0,0 +1,142 @@ +From 25a8a5c6e47268933b9b4433a9590ccfd9c04c83 Mon Sep 17 00:00:00 2001 +From: Martin Pitt +Date: Tue, 14 Sep 2021 09:02:33 +0200 +Subject: [PATCH] common: Restrict frame embedding to same origin + +Declare `X-Frame-Options: sameorigin` [1] so that cockpit frames can +only be embedded into pages coming from the same origin. This is similar +to setting CORP in commit 2b38b8de92f9a (which applies to `