cockpit/backport-0002-CVE-2021-3660.patch
2021-09-24 15:21:43 +08:00

143 lines
6.1 KiB
Diff

From 25a8a5c6e47268933b9b4433a9590ccfd9c04c83 Mon Sep 17 00:00:00 2001
From: Martin Pitt <mpitt@redhat.com>
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 `<script>`,
`<img>`, etc.).
The main use case for embedding is to run cockpit-ws behind a reverse
proxy, while also serving other pages. Cross-origin embedding is
discouraged these days to prevent "clickjacking".
Cross-origin embedding already did not work in most cases: Frames would
always just show the login page. However, this looks confusing and is
unclean. With X-Frame-Options, the browser instead shows an explanatory
error page.
Mention the same origin requirement in the embedding documentation.
Fixes #16122
https://bugzilla.redhat.com/show_bug.cgi?id=1980688
CVE-2021-3660
[1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
Conflict:NA
Reference:https://github.com/cockpit-project/cockpit/pull/16342/commits/25a8a5c6e47268933b9b4433a9590ccfd9c04c83
---
doc/guide/embedding.xml | 4 +++-
src/bridge/test-httpstream.c | 2 +-
src/bridge/test-packages.c | 3 +++
src/common/cockpitwebresponse.c | 6 ++++++
src/common/test-webresponse.c | 3 +++
src/ws/test-channelresponse.c | 3 +++
6 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/doc/guide/embedding.xml b/doc/guide/embedding.xml
index 99b30dc..7fe8aa9 100644
--- a/doc/guide/embedding.xml
+++ b/doc/guide/embedding.xml
@@ -5,7 +5,9 @@
<title>Embedding and Integrating Cockpit</title>
<para>Cockpit can be embedded in other web applications either as a whole or specific
- Cockpit components can be integrated.</para>
+ Cockpit components can be integrated. Due to frame security policy restrictions,
+ this only works if Cockpit and the web application have the <emphasis>same origin</emphasis>;
+ this is commonly achieved by running both from a common reverse proxy.</para>
<section id="embedding-full">
<title>Embedding the Cockpit Interface</title>
diff --git a/src/bridge/test-httpstream.c b/src/bridge/test-httpstream.c
index 47af9ea..6844f72 100644
--- a/src/bridge/test-httpstream.c
+++ b/src/bridge/test-httpstream.c
@@ -31,7 +31,7 @@
#include <string.h>
/* 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\""
+#define STATIC_HEADERS "\"Cross-Origin-Resource-Policy\":\"same-origin\",\"Referrer-Policy\":\"no-referrer\",\"X-Content-Type-Options\":\"nosniff\",\"X-DNS-Prefetch-Control\":\"off\",\"X-Frame-Options\":\"sameorigin\""
static void
on_closed_set_flag (CockpitChannel *channel,
diff --git a/src/bridge/test-packages.c b/src/bridge/test-packages.c
index 769c51c..b96a3b4 100644
--- a/src/bridge/test-packages.c
+++ b/src/bridge/test-packages.c
@@ -45,6 +45,9 @@
#define CHECKSUM_RELOAD_UPDATED "0d1c0b7c6133cc7c3956197fd8a76bef68b158bd78beac75cfa80b75c36aa827"
#define CHECKSUM_CSP "25cab69451c3667cb9ed33f006fc7003c248f1029dae4a763bbadb0c4cafaf8d"
+/* JSON dict snippet for headers that are present in every request */
+#define STATIC_HEADERS "\"X-DNS-Prefetch-Control\":\"off\",\"Referrer-Policy\":\"no-referrer\",\"X-Content-Type-Options\":\"nosniff\",\"Cross-Origin-Resource-Policy\": \"same-origin\",\"X-Frame-Options\": \"sameorigin\""
+
extern const gchar **cockpit_bridge_data_dirs;
extern const gchar *cockpit_bridge_local_address;
extern gint cockpit_bridge_packages_port;
diff --git a/src/common/cockpitwebresponse.c b/src/common/cockpitwebresponse.c
index 0e757f3..ddf1911 100644
--- a/src/common/cockpitwebresponse.c
+++ b/src/common/cockpitwebresponse.c
@@ -735,6 +735,7 @@ enum {
HEADER_CACHE_CONTROL = 1 << 3,
HEADER_DNS_PREFETCH_CONTROL = 1 << 4,
HEADER_REFERRER_POLICY = 1 << 5,
+ HEADER_X_FRAME_OPTIONS = 1 << 8,
};
static GString *
@@ -773,6 +774,8 @@ append_header (GString *string,
return HEADER_DNS_PREFETCH_CONTROL;
if (g_ascii_strcasecmp ("Referrer-Policy", name) == 0)
return HEADER_REFERRER_POLICY;
+ if (g_ascii_strcasecmp ("X-Frame-Options", name) == 0)
+ return HEADER_X_FRAME_OPTIONS;
else if (g_ascii_strcasecmp ("Connection", name) == 0)
g_critical ("Don't set Connection header manually. This is a programmer error.");
return 0;
@@ -875,6 +878,9 @@ finish_headers (CockpitWebResponse *self,
g_string_append (string, "X-DNS-Prefetch-Control: off\r\n");
if ((seen & HEADER_REFERRER_POLICY) == 0)
g_string_append (string, "Referrer-Policy: no-referrer\r\n");
+ /* This is the counterpart for iframe embedding, line of defence against clickjacking */
+ if ((seen & HEADER_X_FRAME_OPTIONS) == 0)
+ g_string_append (string, "X-Frame-Options: sameorigin\r\n");
g_string_append (string, "\r\n");
return g_string_free_to_bytes (string);
diff --git a/src/common/test-webresponse.c b/src/common/test-webresponse.c
index ab59c13..a797f2b 100644
--- a/src/common/test-webresponse.c
+++ b/src/common/test-webresponse.c
@@ -34,6 +34,9 @@
#include <stdlib.h>
#include <string.h>
+/* headers that are present in every request */
+#define STATIC_HEADERS "X-DNS-Prefetch-Control: off\r\nReferrer-Policy: no-referrer\r\nX-Content-Type-Options: nosniff\r\nCross-Origin-Resource-Policy: same-origin\r\nX-Frame-Options: sameorigin\r\n\r\n"
+
static gchar *srcdir;
typedef struct {
diff --git a/src/ws/test-channelresponse.c b/src/ws/test-channelresponse.c
index 86c0fff..763913b 100644
--- a/src/ws/test-channelresponse.c
+++ b/src/ws/test-channelresponse.c
@@ -51,6 +51,9 @@
#define PASSWORD "this is the password"
+/* headers that are present in every request */
+#define STATIC_HEADERS "X-Content-Type-Options: nosniff\r\nX-DNS-Prefetch-Control: off\r\nReferrer-Policy: no-referrer\r\nCross-Origin-Resource-Policy: same-origin\r\nX-Frame-Options: sameorigin\r\n"
+
typedef struct {
CockpitWebService *service;
GIOStream *io;
--
2.27.0