Control: found 1035542 4.3-1+deb11u3 Control: tags 1035542 + patch Thanks for the documentation of CVE-2023-30570 on https://bugs.debian.org/1035542, Salvatore.
fwiw, i don't think this is particularly serious -- the vulnerability only appears to be dangerous if the libreswan endpoint is configured to allow IKEv1 in aggressive mode. Since 4.5-2, libreswan's ikev1-policy has defaulted to "drop", and we've heard no complaints from users that this has been an impediment, so i have my doubts about how many people have such a configuration. That said, in bullseye, it is still a plausible choice. I'm attaching the patch here for bullseye (against v4.3), which i can upload to bullseye-security whenever you you think is appropriate. For v4.10 (which is in bookworm, about to be stable) i think the best move is to just ship v4.11 directly. I'm also attaching here the diff between upstream's v4.10 and v4.11 -- it is a narrowly-targeted bugfix release. i think it makes more sense to just ship v4.11 as a security update to bookworm (since i missed the freeze cutoff, apologies) rather than to try to ship v4.10 plus basically the same patch. Here's the patch against v4.3 that i intend to send to bullseye-security:
From: Daniel Kahn Gillmor <d...@fifthhorseman.net> Date: Thu, 1 Jun 2023 16:12:50 -0400 Subject: Resolve CVE-2023-30570 see https://libreswan.org/security/CVE-2023-30570/CVE-2023-30570.txt This patch was ported from https://libreswan.org/security/CVE-2023-30570/CVE-2023-30570-libreswan-4.x.patch --- programs/pluto/ikev1.c | 60 ++++++++++++++++++++++++++++++++++++++++++--- programs/pluto/ikev1_aggr.c | 5 ++-- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/programs/pluto/ikev1.c b/programs/pluto/ikev1.c index 2a06c2c..bb6c7be 100644 --- a/programs/pluto/ikev1.c +++ b/programs/pluto/ikev1.c @@ -1249,10 +1249,20 @@ void process_v1_packet(struct msg_digest *md) struct state *st = NULL; enum state_kind from_state = STATE_UNDEFINED; /* state we started in */ + /* + * For the initial responses, don't leak the responder's SPI. + * Hence the use of send_v1_notification_from_md(). + * + * AGGR mode is a mess in that the R0->R1 transition happens + * well before the transition succeeds. + */ #define SEND_NOTIFICATION(t) \ { \ pstats(ikev1_sent_notifies_e, t); \ - if (st != NULL) \ + if (st != NULL && \ + st->st_state->kind != STATE_AGGR_R0 && \ + st->st_state->kind != STATE_AGGR_R1 && \ + st->st_state->kind != STATE_MAIN_R0) \ send_notification_from_state(st, from_state, t); \ else \ send_notification_from_md(md, t); \ @@ -1322,17 +1332,26 @@ void process_v1_packet(struct msg_digest *md) from_state = (md->hdr.isa_xchg == ISAKMP_XCHG_IDPROT ? STATE_MAIN_R0 : STATE_AGGR_R0); } else { - /* not an initial message */ + /* + * Possibly not an initial message. Possibly + * from initiator. Possibly from responder. + * + * Possibly. Which is probably hopeless. + */ st = find_state_ikev1(&md->hdr.isa_ike_spis, md->hdr.isa_msgid); if (st == NULL) { /* - * perhaps this is a first message + * Perhaps this is a first message * from the responder and contains a * responder cookie that we've not yet * seen. + * + * Perhaps this is a random message + * with a bogus non-zero responder IKE + * SPI. */ st = find_state_ikev1_init(&md->hdr.isa_ike_initiator_spi, md->hdr.isa_msgid); @@ -1343,6 +1362,21 @@ void process_v1_packet(struct msg_digest *md) /* XXX Could send notification back */ return; } + if (st->st_state->kind == STATE_AGGR_R0) { + /* + * The only way for this to + * happen is for the attacker + * to guess the responder's + * IKE SPI that hasn't been + * sent over the wire? + * + * Well that or played 1/2^32 + * odds. + */ + log_pexpect(HERE, + "phase 1 message matching AGGR_R0 state"); + return; + } } from_state = st->st_state->kind; } @@ -3027,6 +3061,26 @@ void complete_v1_state_transition(struct state *st, struct msg_digest *md, stf_s delete_state(st); /* wipe out dangling pointer to st */ md->st = NULL; + } else if (st->st_state->kind == STATE_AGGR_R0 || + st->st_state->kind == STATE_AGGR_R1 || + st->st_state->kind == STATE_MAIN_R0) { + /* + * + * Wipe out the incomplete larval state. + * + * ARGH! In <=v4.10, the aggr code flipped the + * larval state to R1 right at the start of + * the transition and not the end, so using + * state to figure things out is close to + * useless. + * + * Deleting the state means that pluto has no + * way to detect and ignore amplification + * attacks. + */ + delete_state(st); + /* wipe out dangling pointer to st */ + md->st = NULL; } break; } diff --git a/programs/pluto/ikev1_aggr.c b/programs/pluto/ikev1_aggr.c index 98f6ba8..d4cb115 100644 --- a/programs/pluto/ikev1_aggr.c +++ b/programs/pluto/ikev1_aggr.c @@ -161,7 +161,7 @@ stf_status aggr_inI1_outR1(struct state *unused_st UNUSED, struct ike_sa *ike = new_v1_rstate(c, md); struct state *st = &ike->sa; md->st = st; /* (caller will reset cur_state) */ - change_state(st, STATE_AGGR_R1); + change_state(st, STATE_AGGR_R0); /* warn for especially dangerous Aggressive Mode and PSK */ if (LIN(POLICY_PSK, c->policy) && LIN(POLICY_AGGRESSIVE, c->policy)) { @@ -178,7 +178,8 @@ stf_status aggr_inI1_outR1(struct state *unused_st UNUSED, if (!v1_decode_certs(md)) { log_state(RC_LOG, st, "X509: CERT payload bogus or revoked"); - return false; + /* XXX notification is in order! */ + return STF_FAIL + INVALID_ID_INFORMATION; } /*
And here's the upstream patch from v4.10 to v4.11:
diff --git a/CHANGES b/CHANGES index e28ae02802..130bf910e6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,7 @@ See also https://libreswan.org/ +v4.11 (May 3, 2023) +* SECURITY IKEv1: Fixes https://libreswan.org/security/CVE-2023-30570 v4.10 (February 28, 2023) * SECURITY IKEv2: Fixes https://libreswan.org/security/CVE-2023-23009 diff --git a/mk/version.mk b/mk/version.mk index a0cf3fcd03..e983ec1434 100644 --- a/mk/version.mk +++ b/mk/version.mk @@ -1 +1 @@ -IPSECBASEVERSION?=4.10 +IPSECBASEVERSION?=4.11 diff --git a/packaging/debian/changelog b/packaging/debian/changelog index 58fa9dfcc7..d392003da2 100644 --- a/packaging/debian/changelog +++ b/packaging/debian/changelog @@ -1,6 +1,6 @@ -libreswan (4.10-1) unstable; urgency=low +libreswan (4.11-1) unstable; urgency=low - * Release 4.10-1 + * Release 4.11-1 - -- Libreswan Team <t...@libreswan.org> Tue, 28 Feb 2023 01:00:00 +0200 + -- Libreswan Team <t...@libreswan.org> Wed, 3 May 2023 01:00:00 +0200 diff --git a/packaging/devuan/changelog b/packaging/devuan/changelog index 557aafd865..fc7d315fa4 100644 --- a/packaging/devuan/changelog +++ b/packaging/devuan/changelog @@ -1,7 +1,7 @@ -libreswan (4.10-1) unstable; urgency=low +libreswan (4.11-1) unstable; urgency=low - * Release 4.10-1 + * Release 4.11-1 - -- Libreswan Team <t...@libreswan.org> Tue, 28 Feb 2023 01:00:00 +0200 + -- Libreswan Team <t...@libreswan.org> Wed, 3 May 2023 01:00:00 +0200 diff --git a/packaging/fedora/libreswan.spec b/packaging/fedora/libreswan.spec index 470d8aaa25..7d3ea2c4fc 100644 --- a/packaging/fedora/libreswan.spec +++ b/packaging/fedora/libreswan.spec @@ -30,7 +30,7 @@ Name: libreswan Summary: Internet Key Exchange (IKEv1 and IKEv2) implementation for IPsec # version is generated in the release script -Version: 4.10 +Version: 4.11 Release: %{?prever:0.}1%{?prever:.%{prever}}%{?dist} License: GPLv2 Url: https://libreswan.org/ @@ -199,5 +199,5 @@ certutil -N -d sql:$tmpdir --empty-password %doc %{_mandir}/*/* %changelog -* Tue Feb 28 2023 Team Libreswan <t...@libreswan.org> - 4.10-1 +* Wed May 3 2023 Team Libreswan <t...@libreswan.org> - 4.11-1 - Automated build from release tar ball diff --git a/packaging/rhel/7/libreswan.spec b/packaging/rhel/7/libreswan.spec index 8cd2af2bab..b2a68746ec 100644 --- a/packaging/rhel/7/libreswan.spec +++ b/packaging/rhel/7/libreswan.spec @@ -33,7 +33,7 @@ Name: libreswan Summary: Internet Key Exchange (IKEv1 and IKEv2) implementation for IPsec -Version: 4.10 +Version: 4.11 Release: %{?prever:0.}1%{?prever:.%{prever}}%{?dist} License: GPLv2 Url: https://libreswan.org/ @@ -209,5 +209,5 @@ certutil -N -d sql:$tmpdir --empty-password %doc %{_mandir}/*/* %changelog -* Tue Feb 28 2023 Team Libreswan <t...@libreswan.org> - 4.10-1 +* Wed May 3 2023 Team Libreswan <t...@libreswan.org> - 4.11-1 - Automated build from release tar ball diff --git a/packaging/rhel/8/libreswan.spec b/packaging/rhel/8/libreswan.spec index 29fde0dc43..0d4df14fe4 100644 --- a/packaging/rhel/8/libreswan.spec +++ b/packaging/rhel/8/libreswan.spec @@ -37,7 +37,7 @@ Name: libreswan Summary: IPsec implementation with IKEv1 and IKEv2 keying protocols # version is generated in the release script -Version: 4.10 +Version: 4.11 Release: %{?prever:0.}1%{?prever:.%{prever}}%{?dist} License: GPLv2 Url: https://libreswan.org/ @@ -200,5 +200,5 @@ certutil -N -d sql:$tmpdir --empty-password %attr(0644,root,root) %doc %{_mandir}/*/* %changelog -* Tue Feb 28 2023 Team Libreswan <t...@libreswan.org> - 4.10-1 +* Wed May 3 2023 Team Libreswan <t...@libreswan.org> - 4.11-1 - Automated build from release tar ball diff --git a/programs/pluto/ikev1.c b/programs/pluto/ikev1.c index e0615323ed..401618b6dd 100644 --- a/programs/pluto/ikev1.c +++ b/programs/pluto/ikev1.c @@ -1101,10 +1101,20 @@ void process_v1_packet(struct msg_digest *md) struct state *st = NULL; enum state_kind from_state = STATE_UNDEFINED; /* state we started in */ + /* + * For the initial responses, don't leak the responder's SPI. + * Hence the use of send_v1_notification_from_md(). + * + * AGGR mode is a mess in that the R0->R1 transition happens + * well before the transition succeeds. + */ #define SEND_NOTIFICATION(t) \ { \ pstats(ikev1_sent_notifies_e, t); \ - if (st != NULL) \ + if (st != NULL && \ + st->st_state->kind != STATE_AGGR_R0 && \ + st->st_state->kind != STATE_AGGR_R1 && \ + st->st_state->kind != STATE_MAIN_R0) \ send_v1_notification_from_state(st, from_state, t); \ else \ send_v1_notification_from_md(md, t); \ @@ -1168,17 +1178,26 @@ void process_v1_packet(struct msg_digest *md) from_state = (md->hdr.isa_xchg == ISAKMP_XCHG_IDPROT ? STATE_MAIN_R0 : STATE_AGGR_R0); } else { - /* not an initial message */ + /* + * Possibly not an initial message. Possibly + * from initiator. Possibly from responder. + * + * Possibly. Which is probably hopeless. + */ st = find_state_ikev1(&md->hdr.isa_ike_spis, md->hdr.isa_msgid); if (st == NULL) { /* - * perhaps this is a first message + * Perhaps this is a first message * from the responder and contains a * responder cookie that we've not yet * seen. + * + * Perhaps this is a random message + * with a bogus non-zero responder IKE + * SPI. */ st = find_state_ikev1_init(&md->hdr.isa_ike_initiator_spi, md->hdr.isa_msgid); @@ -1189,6 +1208,21 @@ void process_v1_packet(struct msg_digest *md) /* XXX Could send notification back */ return; } + if (st->st_state->kind == STATE_AGGR_R0) { + /* + * The only way for this to + * happen is for the attacker + * to guess the responder's + * IKE SPI that hasn't been + * sent over the wire? + * + * Well that or played 1/2^32 + * odds. + */ + llog_pexpect(md->md_logger, HERE, + "phase 1 message matching AGGR_R0 state"); + return; + } } from_state = st->st_state->kind; } @@ -2870,7 +2904,28 @@ void complete_v1_state_transition(struct state *st, struct msg_digest *md, stf_s delete_state(st); /* wipe out dangling pointer to st */ md->v1_st = NULL; + } else if (st->st_state->kind == STATE_AGGR_R0 || + st->st_state->kind == STATE_AGGR_R1 || + st->st_state->kind == STATE_MAIN_R0) { + /* + * + * Wipe out the incomplete larval state. + * + * ARGH! In <=v4.10, the aggr code flipped the + * larval state to R1 right at the start of + * the transition and not the end, so using + * state to figure things out is close to + * useless. + * + * Deleting the state means that pluto has no + * way to detect and ignore amplification + * attacks. + */ + delete_state(st); + /* wipe out dangling pointer to st */ + md->v1_st = NULL; } + break; } } diff --git a/programs/pluto/ikev1_aggr.c b/programs/pluto/ikev1_aggr.c index 2732951beb..87be80cb6c 100644 --- a/programs/pluto/ikev1_aggr.c +++ b/programs/pluto/ikev1_aggr.c @@ -169,7 +169,7 @@ stf_status aggr_inI1_outR1(struct state *null_st UNUSED, /* Set up state */ struct ike_sa *ike = new_v1_rstate(c, md); md->v1_st = &ike->sa; /* (caller will reset cur_state) */ - change_v1_state(&ike->sa, STATE_AGGR_R1); + change_v1_state(&ike->sa, STATE_AGGR_R0); /* * Warn when peer is expected to use especially dangerous @@ -197,7 +197,8 @@ stf_status aggr_inI1_outR1(struct state *null_st UNUSED, if (!v1_decode_certs(md)) { llog_sa(RC_LOG, ike, "X509: CERT payload bogus or revoked"); - return false; + /* XXX notification is in order! */ + return STF_FAIL_v1N + v1N_INVALID_ID_INFORMATION; } /* diff --git a/security/CVE-2023-30570.txt b/security/CVE-2023-30570.txt new file mode 100644 index 0000000000..4ee1f7c8c9 --- /dev/null +++ b/security/CVE-2023-30570.txt @@ -0,0 +1,105 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +Release date: Wednesday, May 3, 2023 +Contact: secur...@libreswan.org +PGP key: 907E790F25C1E8E561CD73B585FF4B43B30FC6F9 + +=========================================================================== +CVE-2023-30570: Malicious IKEv1 Aggressive Mode packets can crash libreswan +=========================================================================== + +This alert (and any updates) are available at the following URLs: +https://libreswan.org/security/CVE-2023-30570/ + +The Libreswan Project was notified by github user "XU-huai" of an +issue with receiving a malformed IKEv1 Aggressive Mode packet that +would cause a crash and restart of the libreswan pluto daemon. When +sent continuously, this could lead to a denial of service attack. + +Vulnerable versions : libreswan 3.28 - 4.10 +Not vulnerable : libreswan 3.0 - 3.27, 4.11+ + +Vulnerability information +========================= +When an IKEv1 Aggressive Mode packet is received with only unacceptable +crypto algorithms, the response packet is not sent with a zero responder +SPI. When a subsequent packet is received where the sender re-uses the +libreswan responder SPI, the pluto daemon state machine crashes. No +remote code execution is possible. + +Exploitation +============ +This vulnerability requires that pluto is configured with at least one +potentially matching IKEv1 Aggressive Mode connection. Per default, +pluto only accepts IKEv2 packets. When IKEv1 is enabled, only Main Mode +packets are accepted unless the connection is configured explicitely +with aggressive=yes or via its older name aggrmode=yes. + +When an IKEv1 Aggressive Mode connection is enabled, a malicious peer +needs to send an IKEv1 Aggressive Mode packet with an unsupported +algorithm, such as DH2. Then the malicious peer needs to be able to +receive the reply so it can resend the packet with the received responder +SPI added to cause the libreswan pluto daemon to crash and restart. + +The vulnerable code has been in the code base since 2003 (then still +named "openswan") but only became reachable since an IKEv1 Aggressive +Mode change that was introduced in libreswan 3.28. + +Workaround +========== +IKEv1 Aggressive Mode connections could be converted to IKEv2 or IKEv1 Main Mode +connections. If this is not feasable, patching or upgrading is the only other +alternative. + +History +======= +* 2003 Vulnerable code introduced in openswan-1.0.0 but unreachable +* 2022-04-25 IKEv1 Aggresive Mode change caused vulnerable code to be reachable +* 2023-03-16 Initial report via https://github.com/libreswan/libreswan/issues/1039 +* 2023-04-16 Prerelease of CVE notification and patches to support customers +* 2023-05-03 Release of patch and libreswan 4.11 + +Credits +======= +This vulnerability was found and reported by github user XU-huai + +Upgrading +========= +To address this vulnerability, please upgrade to libreswan 4.11 or later. +For those who cannot upgrade, patches are provided at the above URL. + + +About libreswan (https://libreswan.org/) +======================================== +Libreswan is a free implementation of the Internet Key Exchange (IKE) +protocols IKEv1 and IKEv2. It is a descendant (continuation fork) of +openswan 2.6.38. IKE is used to establish IPsec VPN connections. + +IPsec uses strong cryptography to provide both authentication and +encryption services. These services allow you to build secure tunnels +through untrusted networks. Everything passing through the untrusted +network is encrypted by the IPsec gateway machine, and decrypted by +the gateway at the other end of the tunnel. The resulting tunnel is a +virtual private network (VPN). + +Patches +======= +Due to the size of the patch, it is not included inline to this advisory. +-----BEGIN PGP SIGNATURE----- + +iQJHBAEBCgAxFiEEkH55DyXB6OVhzXO1hf9LQ7MPxvkFAmRSzNYTHHRlYW1AbGli +cmVzd2FuLm9yZwAKCRCF/0tDsw/G+Z88D/9YuPoEvk7cMrSN7jV0z9liNiAR/gYB +gj8CjXkIw4mNaQIcpvhArlFMYov0MXh+nOJDiALx6/dsb6nvgzg/vvVOSU5jSRtg +cEC8STA/rvLRSlj5mChKNAayVUmSgOxSg4AFr6zvG+/iQzC3vT2mlmwLXVKw5F+n +Nn00Ov1EklqCRlSBUYhuKY2zyhRfxPajZW9s8VcKiUs36qzTjjp/EsUTln3uNHk4 +nFIL+6cxEkUIVKtfZVpoB/zLg73tsnUEAdKeXl0H3BqLLohrbkPNEYh7HZsxrD1v +g8Z/omf41wfN9p/JJkMK84qN55Nis90TiU5esf4gnl0vOf1dH4vMd7a082ee07UC +wPeDL2zpxviIGdnFFzXOnlj88Xa7FsAcB7XU5wcpQcN9GFn8YbiSQvRbKFrrmpNf +10JXYPbMTze8QdrXI4E6mXGbgs9i4BxqYNrSFv0Xuyth+LSAL499adH+SZcG0kc2 +XiQ1ZmGqBtQg68CPUdhuP1C4mixwTZ6wJQOyZlagebTDgJVPx52aSYAqoeakTzJ5 +YpnVsYBbZXRZTvRasR9sdLp6ZiIzmIy3TF40GwoKvVWKburAaLp53FW2/s5Tvb5G +BzlFcusnGd4xteUQklfOow4NJZZxUlEljQgu+yKZaNziYngaFwsy/shfM3STNlth +1mSorpVmVanqiw== +=DgY+ +-----END PGP SIGNATURE-----
I've pushed the appropriate changes to the debian/unstable and debian/bullseye branches in https://salsa.debian.org/debian/libreswan. If they look good to you, i'll sign and upload them, and publish the appropriate tags. --dkg
signature.asc
Description: PGP signature