Bug#1002956: New debdiff
My appologies for opening a new bug. I didn't realize #1002956 was still
pending my input. I merged both bugs.
Please see, attached to this message, the new debdiff, adding the fix
for CVE-2021-22116 as well.
Cheers,
Thomas Goirand (zigo)
diff -Nru rabbitmq-server-3.8.9/debian/changelog rabbitmq-server-3.8.9/debian/changelog
--- rabbitmq-server-3.8.9/debian/changelog 2021-04-10 22:59:57.000000000 +0200
+++ rabbitmq-server-3.8.9/debian/changelog 2022-01-01 18:46:04.000000000 +0100
@@ -1,3 +1,39 @@
+rabbitmq-server (3.8.9-3+deb11u1) bullseye; urgency=medium
+
+ * CVE-2021-32719: In rabbitmq-server prior to version 3.8.18, when a
+ federation link was displayed in the RabbitMQ management UI via the
+ `rabbitmq_federation_management` plugin, its consumer tag was rendered
+ without proper <script> tag sanitization. This potentially allows
+ for JavaScript code execution in the context of the page. The user must
+ be signed in and have elevated permissions (manage federation upstreams
+ and policies) for this to occur. Applied upstream patch: Escape the
+ consumer-tag value in federation mgmt.
+ * CVE-2021-32718: In rabbitmq-server prior to version 3.8.17, a new user
+ being added via management UI could lead to the user's bane being
+ rendered in a confirmation message without proper `<script>` tag
+ sanitization, potentially allowing for JavaScript code execution in the
+ context of the page. In order for this to occur, the user must be signed
+ in and have elevated permissions (other user management).
+ * Closes: #990524
+ * Add a new README.Debian explaining how to secure RabbitMQ.
+ * Stop moving mv /etc/rabbitmq/rabbitmq.conf /etc/rabbitmq/rabbitmq-env.conf.
+ * Generate the Erlang cookie in /var/lib/rabbitmq/.erlang.cookie using
+ OpenSSL, rather than letting RabbitMQ use Erlang to generate a poor entropy
+ Erlang cookie, which was easily brute-forceable in 10 minutes. The OpenSSL
+ generated version has order of magnitudes more possible values, which makes
+ it a way harder to bruteforce. If an old Erlang cookie is detected, a new
+ one is generated, and rabbitmq-server restarted if it was running.
+ * rabbitmq-server.service now correctly depends on epmd.socket and not the
+ epmd@.socket, so it can correctly start after a reboot.
+ * CVE-2021-22116: RabbitMQ all versions prior to 3.8.16 are prone to a denial
+ of service vulnerability due to improper input validation in AMQP 1.0
+ client connection endpoint. A malicious user can exploit the vulnerability
+ by sending malicious AMQP messages to the target RabbitMQ instance having
+ the AMQP 1.0 plugin enabled. Added upstream patch: AMQP 1.0 binary parser:
+ treat arrays with extra or missing input as fatal errors.
+
+ -- Thomas Goirand <zigo@debian.org> Sat, 01 Jan 2022 18:46:04 +0100
+
rabbitmq-server (3.8.9-3) unstable; urgency=medium
[ Adam Cecile ]
diff -Nru rabbitmq-server-3.8.9/debian/control rabbitmq-server-3.8.9/debian/control
--- rabbitmq-server-3.8.9/debian/control 2021-04-10 22:59:57.000000000 +0200
+++ rabbitmq-server-3.8.9/debian/control 2022-01-01 18:46:04.000000000 +0100
@@ -61,6 +61,7 @@
locales-all,
logrotate,
lsb-base,
+ openssl,
socat,
${misc:Depends},
${python3:Depends},
diff -Nru rabbitmq-server-3.8.9/debian/patches/CVE-2021-22116_AMQP_1.0_parser_treat_arrays_with_extra_or_missing_input_as_fatal_errors.patch rabbitmq-server-3.8.9/debian/patches/CVE-2021-22116_AMQP_1.0_parser_treat_arrays_with_extra_or_missing_input_as_fatal_errors.patch
--- rabbitmq-server-3.8.9/debian/patches/CVE-2021-22116_AMQP_1.0_parser_treat_arrays_with_extra_or_missing_input_as_fatal_errors.patch 1970-01-01 01:00:00.000000000 +0100
+++ rabbitmq-server-3.8.9/debian/patches/CVE-2021-22116_AMQP_1.0_parser_treat_arrays_with_extra_or_missing_input_as_fatal_errors.patch 2022-01-01 18:46:04.000000000 +0100
@@ -0,0 +1,135 @@
+From 626d5219115d087a2695c0eb243c7ddb7e154563 Mon Sep 17 00:00:00 2001
+From: Michael Klishin <klishinm@vmware.com>
+Date: Wed, 7 Apr 2021 13:42:20 +0300
+Subject: [PATCH] Merge pull request #2953 from
+ rabbitmq/mk-amqp10-parser-infinite-loop
+
+AMQP 1.0 binary parser: treat arrays with extra or missing input as fatal errors
+
+(cherry picked from commit f37a31de55229e6c763215500e376fa16803390b)
+---
+ .../src/amqp10_binary_parser.erl | 26 +++++---
+ .../test/binary_parser_SUITE.erl | 59 +++++++++++++++++++
+ 2 files changed, 78 insertions(+), 7 deletions(-)
+ create mode 100644 deps/amqp10_common/test/binary_parser_SUITE.erl
+
+diff --git a/deps/amqp10_common/src/amqp10_binary_parser.erl b/deps/amqp10_common/src/amqp10_binary_parser.erl
+index b936f9f4ca8..376ac47aed5 100644
+--- a/deps/amqp10_common/src/amqp10_binary_parser.erl
++++ b/deps/amqp10_common/src/amqp10_binary_parser.erl
+@@ -31,15 +31,15 @@ parse_described(Bin) ->
+ {Value, Rest2} = parse(Rest1),
+ {{described, Descriptor, Value}, Rest2}.
+
+-parse_primitive0(<<Type,Rest/binary>>) ->
++parse_primitive0(<<Type, Rest/binary>>) ->
+ parse_primitive(Type, Rest).
+
+ %% Constants
+-parse_primitive(16#40, Rest) -> {null, Rest};
+-parse_primitive(16#41, Rest) -> {true, Rest};
+-parse_primitive(16#42, Rest) -> {false, Rest};
+-parse_primitive(16#43, Rest) -> {{uint, 0}, Rest};
+-parse_primitive(16#44, Rest) -> {{ulong, 0}, Rest};
++parse_primitive(16#40, R) -> {null, R};
++parse_primitive(16#41, R) -> {true, R};
++parse_primitive(16#42, R) -> {false, R};
++parse_primitive(16#43, R) -> {{uint, 0}, R};
++parse_primitive(16#44, R) -> {{ulong, 0}, R};
+
+ %% Fixed-widths. Most integral types have a compact encoding as a byte.
+ parse_primitive(16#50, <<V:8/unsigned, R/binary>>) -> {{ubyte, V}, R};
+@@ -122,6 +122,14 @@ parse_compound1(Count, Bin, Acc) ->
+ {Value, Rest} = parse(Bin),
+ parse_compound1(Count - 1, Rest, [Value | Acc]).
+
++parse_array_primitive(16#40, <<_:8/unsigned, R/binary>>) -> {null, R};
++parse_array_primitive(16#41, <<_:8/unsigned, R/binary>>) -> {true, R};
++parse_array_primitive(16#42, <<_:8/unsigned, R/binary>>) -> {false, R};
++parse_array_primitive(16#43, <<_:8/unsigned, R/binary>>) -> {{uint, 0}, R};
++parse_array_primitive(16#44, <<_:8/unsigned, R/binary>>) -> {{ulong, 0}, R};
++parse_array_primitive(ElementType, Data) ->
++ parse_primitive(ElementType, Data).
++
+ %% array structure is {array, Ctor, [Data]}
+ %% e.g. {array, symbol, [<<"amqp:accepted:list">>]}
+ parse_array(UnitSize, Bin) ->
+@@ -141,8 +149,12 @@ parse_array1(Count, <<Type, ArrayBin/binary>>) ->
+
+ parse_array2(0, Type, <<>>, Acc) ->
+ {array, parse_constructor(Type), lists:reverse(Acc)};
++parse_array2(0, Type, Bin, Acc) ->
++ exit({failed_to_parse_array_extra_input_remaining, Type, Bin, Acc});
++parse_array2(Count, Type, <<>>, Acc) when Count > 0 ->
++ exit({failed_to_parse_array_insufficient_input, Type, Count, Acc});
+ parse_array2(Count, Type, Bin, Acc) ->
+- {Value, Rest} = parse_primitive(Type, Bin),
++ {Value, Rest} = parse_array_primitive(Type, Bin),
+ parse_array2(Count - 1, Type, Rest, [Value | Acc]).
+
+ parse_constructor(16#a3) -> symbol;
+diff --git a/deps/amqp10_common/test/binary_parser_SUITE.erl b/deps/amqp10_common/test/binary_parser_SUITE.erl
+new file mode 100644
+index 00000000000..7c1b2322e38
+--- /dev/null
++++ b/deps/amqp10_common/test/binary_parser_SUITE.erl
+@@ -0,0 +1,59 @@
++-module(binary_parser_SUITE).
++
++-compile(export_all).
++
++-export([
++ ]).
++
++-include_lib("common_test/include/ct.hrl").
++-include_lib("eunit/include/eunit.hrl").
++
++%%%===================================================================
++%%% Common Test callbacks
++%%%===================================================================
++
++all() ->
++ [
++ {group, tests}
++ ].
++
++
++all_tests() ->
++ [
++ array_with_extra_input
++ ].
++
++groups() ->
++ [
++ {tests, [], all_tests()}
++ ].
++
++init_per_suite(Config) ->
++ Config.
++
++end_per_suite(_Config) ->
++ ok.
++
++init_per_group(_Group, Config) ->
++ Config.
++
++end_per_group(_Group, _Config) ->
++ ok.
++
++init_per_testcase(_TestCase, Config) ->
++ Config.
++
++end_per_testcase(_TestCase, _Config) ->
++ ok.
++
++%%%===================================================================
++%%% Test cases
++%%%===================================================================
++
++array_with_extra_input(_Config) ->
++ Bin = <<83,16,192,85,10,177,0,0,0,1,48,161,12,114,97,98,98,105,116, 109,113,45,98,111,120,112,255,255,0,0,96,0,50,112,0,0,19,136,163,5,101,110,45,85,83,224,14,2,65,5,102,105,45,70,73,5,101,110,45,85,83,64,64,193,24,2,163,20,68,69,70,69,78,83,73,67,83,46,84,69,83,84,46,83,85,73,84,69,65>>,
++ ?assertExit({failed_to_parse_array_extra_input_remaining,
++ %% element type, input, accumulated result
++ 65, <<105,45,70,73,5,101,110,45,85,83>>, [true,true]},
++ amqp10_binary_parser:parse_all(Bin)),
++ ok.
diff -Nru rabbitmq-server-3.8.9/debian/patches/CVE-2021-32718_Escape_username_before_displaying_it.patch rabbitmq-server-3.8.9/debian/patches/CVE-2021-32718_Escape_username_before_displaying_it.patch
--- rabbitmq-server-3.8.9/debian/patches/CVE-2021-32718_Escape_username_before_displaying_it.patch 1970-01-01 01:00:00.000000000 +0100
+++ rabbitmq-server-3.8.9/debian/patches/CVE-2021-32718_Escape_username_before_displaying_it.patch 2022-01-01 18:46:04.000000000 +0100
@@ -0,0 +1,21 @@
+Description: CVE-2021-32718: Escape username before displaying it
+ All other values displayed in pop-ups are already escaped.
+Author: Michael Klishin <michael@clojurewerkz.org>
+Date: Thu, 6 May 2021 06:57:43 +0300
+Origin: upstream, https://github.com/rabbitmq/rabbitmq-server/commit/5d15ffc5ebfd9818fae488fc05d1f120ab02703c.patch
+Bug-Debian: https://bugs.debian.org/990524
+Last-Update: 2022-01-01
+
+diff --git a/deps/rabbitmq_management/priv/www/js/dispatcher.js b/deps/rabbitmq_management/priv/www/js/dispatcher.js
+index d2842c2da8a..5f1b54dbac8 100644
+--- a/deps/rabbitmq_management/priv/www/js/dispatcher.js
++++ b/deps/rabbitmq_management/priv/www/js/dispatcher.js
+@@ -189,7 +189,7 @@ dispatcher_add(function(sammy) {
+ res = sync_put(this, '/users/:username');
+ if (res) {
+ if (res.http_status === 204) {
+- username = res.req_params.username;
++ username = fmt_escape_html(res.req_params.username);
+ show_popup('warn', "Updated an existing user: '" + username + "'");
+ }
+ update();
diff -Nru rabbitmq-server-3.8.9/debian/patches/CVE-2021-32719_Escape_the_consumer-tag_value_in_federation_mgmt.patch rabbitmq-server-3.8.9/debian/patches/CVE-2021-32719_Escape_the_consumer-tag_value_in_federation_mgmt.patch
--- rabbitmq-server-3.8.9/debian/patches/CVE-2021-32719_Escape_the_consumer-tag_value_in_federation_mgmt.patch 1970-01-01 01:00:00.000000000 +0100
+++ rabbitmq-server-3.8.9/debian/patches/CVE-2021-32719_Escape_the_consumer-tag_value_in_federation_mgmt.patch 2022-01-01 18:46:04.000000000 +0100
@@ -0,0 +1,21 @@
+Description: CVE-2021-32719 Escape the consumer-tag value in federation mgmt
+ Patches persistent XSS.
+Author: Patrik Ragnarsson <patrik@starkast.net>
+Date: Sat, 19 Jun 2021 09:23:12 +0200
+Origin: upstream, https://github.com/rabbitmq/rabbitmq-server/pull/3122
+Bug-Debian: https://bugs.debian.org/990524
+Last-Update: 2021-01-01
+
+diff --git a/deps/rabbitmq_federation_management/priv/www/js/tmpl/federation-upstreams.ejs b/deps/rabbitmq_federation_management/priv/www/js/tmpl/federation-upstreams.ejs
+index 5b3e14d0638..838eac1eb3b 100644
+--- a/deps/rabbitmq_federation_management/priv/www/js/tmpl/federation-upstreams.ejs
++++ b/deps/rabbitmq_federation_management/priv/www/js/tmpl/federation-upstreams.ejs
+@@ -45,7 +45,7 @@
+ <td class="r"><%= fmt_time(upstream.value['message-ttl'], 'ms') %></td>
+ <td class="r"><%= fmt_string(upstream.value['ha-policy']) %></td>
+ <td class="r"><%= fmt_string(upstream.value['queue']) %></td>
+- <td class="r"><%= upstream.value['consumer-tag'] %></td>
++ <td class="r"><%= fmt_string(upstream.value['consumer-tag']) %></td>
+ </tr>
+ <% } %>
+ </tbody>
diff -Nru rabbitmq-server-3.8.9/debian/patches/series rabbitmq-server-3.8.9/debian/patches/series
--- rabbitmq-server-3.8.9/debian/patches/series 2021-04-10 22:59:57.000000000 +0200
+++ rabbitmq-server-3.8.9/debian/patches/series 2022-01-01 18:46:04.000000000 +0100
@@ -1,3 +1,5 @@
lets-use-python3-not-python-binary.patch
rabbitmq-dist.mk.patch
Upstream_PR2965_fixing_rabbitmqctl_parsing
+CVE-2021-32719_Escape_the_consumer-tag_value_in_federation_mgmt.patch
+CVE-2021-22116_AMQP_1.0_parser_treat_arrays_with_extra_or_missing_input_as_fatal_errors.patch
diff -Nru rabbitmq-server-3.8.9/debian/rabbitmq-server.postinst rabbitmq-server-3.8.9/debian/rabbitmq-server.postinst
--- rabbitmq-server-3.8.9/debian/rabbitmq-server.postinst 2021-04-10 22:59:57.000000000 +0200
+++ rabbitmq-server-3.8.9/debian/rabbitmq-server.postinst 2022-01-01 18:46:04.000000000 +0100
@@ -20,10 +20,6 @@
mkdir -p /etc/rabbitmq
chown rabbitmq:rabbitmq /etc/rabbitmq
- if [ -f /etc/rabbitmq/rabbitmq.conf ] && [ ! -f /etc/rabbitmq/rabbitmq-env.conf ]; then
- mv /etc/rabbitmq/rabbitmq.conf /etc/rabbitmq/rabbitmq-env.conf
- chown rabbitmq:rabbitmq /etc/rabbitmq/rabbitmq-env.conf
- fi
if [ -r /usr/share/rabbitmq/rabbitmq-env.conf ] && ! [ -e /etc/rabbitmq/rabbitmq-env.conf ] ; then
install -m 0644 -o rabbitmq -g rabbitmq /usr/share/rabbitmq/rabbitmq-env.conf /etc/rabbitmq/rabbitmq-env.conf
fi
@@ -35,9 +31,29 @@
chmod 750 /var/lib/rabbitmq/mnesia
chmod -R o-rwx,g-w /var/lib/rabbitmq/mnesia
+ # We generate the erlang cookie by ourselves, just to make sure we don't
+ # leave the job to erlang that doesn't do it with enough entropy.
+ if ! [ -e /var/lib/rabbitmq/.erlang.cookie ] ; then
+ OLD_UMASK=$(umask)
+ umask 077; openssl rand -base64 -out /var/lib/rabbitmq/.erlang.cookie 42
+ umask ${OLD_UMASK}
+ else
+ # This matches an Erlang generated cookie file: 20 upper case chars
+ if grep -q -E '^[A-Z]{20}$' /var/lib/rabbitmq/.erlang.cookie ; then
+ OLD_UMASK=$(umask)
+ umask 077; openssl rand -base64 -out /var/lib/rabbitmq/.erlang.cookie 42
+ umask ${OLD_UMASK}
+ if [ ""$(ps --no-headers -o comm 1) = "systemd" ] ; then
+ if systemctl is-active --quiet rabbitmq-server.service ; then
+ systemctl restart rabbitmq-server.service
+ fi
+ fi
+ fi
+ fi
+ chmod 0400 /var/lib/rabbitmq/.erlang.cookie
+
chown -R rabbitmq:rabbitmq /var/lib/rabbitmq
chown -R rabbitmq:rabbitmq /var/log/rabbitmq
-
fi
#DEBHELPER#
diff -Nru rabbitmq-server-3.8.9/debian/rabbitmq-server.service rabbitmq-server-3.8.9/debian/rabbitmq-server.service
--- rabbitmq-server-3.8.9/debian/rabbitmq-server.service 2021-04-10 22:59:57.000000000 +0200
+++ rabbitmq-server-3.8.9/debian/rabbitmq-server.service 2022-01-01 18:46:04.000000000 +0100
@@ -1,7 +1,7 @@
[Unit]
Description=RabbitMQ Messaging Server
-After=network.target epmd@.socket
-Wants=network.target epmd@.socket
+After=network.target epmd.socket
+Wants=network.target epmd.socket
[Service]
Type=notify
diff -Nru rabbitmq-server-3.8.9/debian/README.Debian rabbitmq-server-3.8.9/debian/README.Debian
--- rabbitmq-server-3.8.9/debian/README.Debian 1970-01-01 01:00:00.000000000 +0100
+++ rabbitmq-server-3.8.9/debian/README.Debian 2022-01-01 18:46:04.000000000 +0100
@@ -0,0 +1,134 @@
+*** WARNING ***
+
+0/ Intro
+
+RabbitMQ, in its default configuration, is insecure. A number of
+security measures are necessary to prevent remote execution of code
+from malicious actors.
+
+
+1/ Firewalling
+
+A default RabbitMQ installation opens the following ports, with the
+following authentication schemes:
+ - 4369: EPMD daemon, for port lookups; IP-based auth limited to
+ localhost
+ - 5672: AMQP protcol; username/password auth
+ - 25672: RabbitMQ "distribution" port for inter-node communication; a
+ "magic cookie" shared secret for auth
+
+Unauthorized access to all of these ports is a security risk; you
+should configure your firewall to disallow outside access to them.
+Speifically, unrestricted access to the port 25672, with the default
+weak secret before 3.9.8-3 (see below), EXPOSES YOUR SERVER TO A
+REMOTE CODE EXECUTION VULNERABILITY. Unrestricted access to port 4369
+serves to advertise that vulnerability.
+
+Though not open by default, RabbitMQ may also be configured to open
+the following ports, which are also strongly advised to be firewalled:
+ - 5671: AMQP with SSL
+ - 15671: Management port with SSL
+ - 15672: Management port without SSL
+
+
+2/ Erlang cookie
+
+Prior to Debian version 3.9.8-3, rabbitmq-server generated an Erlang
+"magic cookie" shared secret if one did not exist. This secret is
+stored in /var/lib/rabbitmq/.erlang.cookie
+
+However, due to predictable seeds and a non-cryptographic randomizer,
+the automatically-generated secret written by Erlang only supplies 20
+to 40 bits of entropy. This allows a remote attacker with access to
+port 25672 to brute-force the "magic cookie," potentially within
+minutes, authenticate as a remote node, and EXECUTE ARBITRARY CODE.
+
+Since 3.9.8-3, the rabbitmq-server node will use openssl to generate a
+cryptographically-secure cookie during first installation, mitigating
+this vulnerability.
+
+Servers which installed a prior version, and are upgrading to 3.9.8-3
+or higher, ARE STILL VULNERABLE, as the package will not regenerate
+the secret if it exists already. This is because the secret is
+designed to be shared between nodes in a cluster, and thus
+regenerating it would break existing clusters.
+
+Operators upgrading from earlier versions of rabbitmq-server are
+strongly encouraged to generate a new secret. This can be done via:
+
+ openssl rand -base64 42 >/var/lib/rabbitmq/.erlang.cookie
+
+
+3/ TLS
+
+It is strongly advised to use TLS to protect data in transit to your
+RabbitMQ cluster. Below is an example /etc/rabbitmq/rabbitmq.config
+which achieves that; note that it uses only RAM nodes in the cluster,
+which is not a recommended configuration for production, as it can
+lead to data loss.
+
+[
+ {rabbit, [
+ {loopback_users, [<<"guest">>]},
+ {cluster_nodes, {['rabbit@node1.example.com', 'rabbit@node2.example.com', 'rabbit@node3.example.com'], ram}},
+ {cluster_partition_handling, autoheal},
+ {tcp_listen_options, [
+ {backlog, 128},
+ {nodelay, true},
+ {linger, {true, 0}},
+ {exit_on_close, false}
+ ]},
+ {collect_statistics_interval, 60000},
+ {ssl_listeners, [{"10.0.1.3", 5671}]},
+ {ssl_options, [
+ {cacertfile,"/etc/ssl/certs/my-cluster-ca-chain.pem"},
+ {certfile,"/etc/rabbitmq/ssl/public/node1.example.com.crt"},
+ {keyfile,"/etc/rabbitmq/ssl/private/node1.example.com.key"},
+ {secure_renegotiate,true},
+ {reuse_sessions,true},
+ {honor_cipher_order,true},
+ {verify,verify_none},
+ {fail_if_no_peer_cert,false}
+ ]},
+ {vm_memory_high_watermark, 0.4},
+ {default_user, <<"guest">>},
+ {default_pass, <<"guest">>}
+ ]},
+ {kernel, [
+
+ ]}
+,
+ {rabbitmq_management, [
+ {listener, [
+ {ip, "10.0.1.3"},
+ {port, 15671},
+ {ssl, true},
+ {ssl_opts, [
+ {cacertfile, "/etc/ssl/certs/my-cluster-ca-chain.pem"},
+ {certfile, "/etc/rabbitmq/ssl/public/node1.example.com.crt"},
+ {keyfile, "/etc/rabbitmq/ssl/private/node1.example.com.key"},
+ {verify,verify_none},
+ {fail_if_no_peer_cert,false}
+ ]}
+ ]}
+ ]}
+].
+
+Documenting how to generate TLS certificates is out of the scope of
+this small README. However, you can see an example script to do so
+over here:
+
+https://salsa.debian.org/openstack-team/debian/openstack-cluster-installer/-/blob/debian/xena/bin/oci-root-ca-gen
+
+with the matching configuration files over here:
+
+https://salsa.debian.org/openstack-team/debian/openstack-cluster-installer/-/tree/debian/xena/etc/openstack-cluster-installer/pki
+
+
+4/ guest account
+
+The "guest" account which is pre-configured in the initial
+installation is only accessible from 127.0.0.1 or ::1; its password is
+also initially set to "guest".
+
+ -- Thomas Goirand <zigo@debian.org> Sat, 15 Jan 2022 11:52:42 +0100
Reply to: