diff mbox series

[meta-networking,dunfell] strongswan: Fix CVE-2022-40617

Message ID PN3PR01MB7382E147FEBCABB41E5918078F3B9@PN3PR01MB7382.INDPRD01.PROD.OUTLOOK.COM
State New
Headers show
Series [meta-networking,dunfell] strongswan: Fix CVE-2022-40617 | expand

Commit Message

Ranjitsinh Rathod Nov. 4, 2022, 3:39 p.m. UTC
Hi Armin,

I still not figured out why sending patch is corrupting from my company's domain and so attaching patch here in the email.


Thanks,

Best Regards,

Ranjitsinh Rathod
Technical Leader |  | KPIT Technologies Ltd.
Cellphone: +91-84606 92403
diff mbox series

Patch

From f360549886c767338e14467545d9e5ae00db326a Mon Sep 17 00:00:00 2001
From: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
Date: Thu, 3 Nov 2022 10:43:47 +0530
Subject: [PATCH] strongswan: Fix CVE-2022-40617

Add a patch to fix CVE-2022-40617 issue which allows remote attackers to
cause a denial of service in the revocation plugin by sending a crafted
end-entity (and intermediate CA) certificate that contains a CRL/OCSP
URL that points to a server (under the attacker's control) that doesn't
properly respond but (for example) just does nothing after the initial
TCP handshake, or sends an excessive amount of application data.
Link: https://nvd.nist.gov/vuln/detail/CVE-2022-40617

Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
---
 .../strongswan/files/CVE-2022-40617.patch     | 210 ++++++++++++++++++
 .../strongswan/strongswan_5.8.4.bb            |   1 +
 2 files changed, 211 insertions(+)
 create mode 100644 meta-networking/recipes-support/strongswan/files/CVE-2022-40617.patch

diff --git a/meta-networking/recipes-support/strongswan/files/CVE-2022-40617.patch b/meta-networking/recipes-support/strongswan/files/CVE-2022-40617.patch
new file mode 100644
index 000000000..66e504712
--- /dev/null
+++ b/meta-networking/recipes-support/strongswan/files/CVE-2022-40617.patch
@@ -0,0 +1,210 @@ 
+From 66d3b2e0e596a6eac1ebcd15c83a8d9368fe7b34 Mon Sep 17 00:00:00 2001
+From: Tobias Brunner <tobias@strongswan.org>
+Date: Fri, 22 Jul 2022 15:37:43 +0200
+Subject: [PATCH] credential-manager: Do online revocation checks only after
+ basic trust chain validation
+
+This avoids querying URLs of potentially untrusted certificates, e.g. if
+an attacker sends a specially crafted end-entity and intermediate CA
+certificate with a CDP that points to a server that completes the
+TCP handshake but then does not send any further data, which will block
+the fetcher thread (depending on the plugin) for as long as the default
+timeout for TCP.  Doing that multiple times will block all worker threads,
+leading to a DoS attack.
+
+The logging during the certificate verification obviously changes.  The
+following example shows the output of `pki --verify` for the current
+strongswan.org certificate:
+
+new:
+
+  using certificate "CN=www.strongswan.org"
+  using trusted intermediate ca certificate "C=US, O=Let's Encrypt, CN=R3"
+  using trusted ca certificate "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
+  reached self-signed root ca with a path length of 1
+checking certificate status of "CN=www.strongswan.org"
+  requesting ocsp status from 'http://r3.o.lencr.org' ...
+  ocsp response correctly signed by "C=US, O=Let's Encrypt, CN=R3"
+  ocsp response is valid: until Jul 27 12:59:58 2022
+certificate status is good
+checking certificate status of "C=US, O=Let's Encrypt, CN=R3"
+ocsp response verification failed, no signer certificate 'C=US, O=Let's Encrypt, CN=R3' found
+  fetching crl from 'http://x1.c.lencr.org/' ...
+  using trusted certificate "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
+  crl correctly signed by "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
+  crl is valid: until Apr 18 01:59:59 2023
+certificate status is good
+certificate trusted, lifetimes valid, certificate not revoked
+
+old:
+
+  using certificate "CN=www.strongswan.org"
+  using trusted intermediate ca certificate "C=US, O=Let's Encrypt, CN=R3"
+checking certificate status of "CN=www.strongswan.org"
+  requesting ocsp status from 'http://r3.o.lencr.org' ...
+  ocsp response correctly signed by "C=US, O=Let's Encrypt, CN=R3"
+  ocsp response is valid: until Jul 27 12:59:58 2022
+certificate status is good
+  using trusted ca certificate "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
+checking certificate status of "C=US, O=Let's Encrypt, CN=R3"
+ocsp response verification failed, no signer certificate 'C=US, O=Let's Encrypt, CN=R3' found
+  fetching crl from 'http://x1.c.lencr.org/' ...
+  using trusted certificate "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
+  crl correctly signed by "C=US, O=Internet Security Research Group, CN=ISRG Root X1"
+  crl is valid: until Apr 18 01:59:59 2023
+certificate status is good
+  reached self-signed root ca with a path length of 1
+certificate trusted, lifetimes valid, certificate not revoked
+
+Note that this also fixes an issue with the previous dual-use of the
+`trusted` flag.  It not only indicated whether the chain is trusted but
+also whether the current issuer is the root anchor (the corresponding
+flag in the `cert_validator_t` interface is called `anchor`).  This was
+a problem when building multi-level trust chains for pre-trusted
+end-entity certificates (i.e. where `trusted` is TRUE from the start).
+This caused the main loop to get aborted after the first intermediate CA
+certificate and the mentioned `anchor` flag wasn't correct in any calls
+to `cert_validator_t` implementations.
+
+Fixes: CVE-2022-40617
+
+CVE: CVE-2022-40617
+Upstream-Status: Backport [https://download.strongswan.org/security/CVE-2022-40617/strongswan-5.1.0-5.9.7_cert_online_validate.patch]
+Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
+
+---
+ .../credentials/credential_manager.c          | 54 +++++++++++++++----
+ 1 file changed, 45 insertions(+), 9 deletions(-)
+
+diff --git a/src/libstrongswan/credentials/credential_manager.c b/src/libstrongswan/credentials/credential_manager.c
+index e93b5943a3a7..798785544e41 100644
+--- a/src/libstrongswan/credentials/credential_manager.c
++++ b/src/libstrongswan/credentials/credential_manager.c
+@@ -556,7 +556,7 @@ static void cache_queue(private_credential_manager_t *this)
+  */
+ static bool check_lifetime(private_credential_manager_t *this,
+ 						   certificate_t *cert, char *label,
+-						   int pathlen, bool trusted, auth_cfg_t *auth)
++						   int pathlen, bool anchor, auth_cfg_t *auth)
+ {
+ 	time_t not_before, not_after;
+ 	cert_validator_t *validator;
+@@ -571,7 +571,7 @@ static bool check_lifetime(private_credential_manager_t *this,
+ 			continue;
+ 		}
+ 		status = validator->check_lifetime(validator, cert,
+-										   pathlen, trusted, auth);
++										   pathlen, anchor, auth);
+ 		if (status != NEED_MORE)
+ 		{
+ 			break;
+@@ -604,13 +604,13 @@ static bool check_lifetime(private_credential_manager_t *this,
+  */
+ static bool check_certificate(private_credential_manager_t *this,
+ 				certificate_t *subject, certificate_t *issuer, bool online,
+-				int pathlen, bool trusted, auth_cfg_t *auth)
++				int pathlen, bool anchor, auth_cfg_t *auth)
+ {
+ 	cert_validator_t *validator;
+ 	enumerator_t *enumerator;
+ 
+ 	if (!check_lifetime(this, subject, "subject", pathlen, FALSE, auth) ||
+-		!check_lifetime(this, issuer, "issuer", pathlen + 1, trusted, auth))
++		!check_lifetime(this, issuer, "issuer", pathlen + 1, anchor, auth))
+ 	{
+ 		return FALSE;
+ 	}
+@@ -623,7 +623,7 @@ static bool check_certificate(private_credential_manager_t *this,
+ 			continue;
+ 		}
+ 		if (!validator->validate(validator, subject, issuer,
+-								 online, pathlen, trusted, auth))
++								 online, pathlen, anchor, auth))
+ 		{
+ 			enumerator->destroy(enumerator);
+ 			return FALSE;
+@@ -726,6 +726,7 @@ static bool verify_trust_chain(private_credential_manager_t *this,
+ 	auth_cfg_t *auth;
+ 	signature_params_t *scheme;
+ 	int pathlen;
++	bool is_anchor = FALSE;
+ 
+ 	auth = auth_cfg_create();
+ 	get_key_strength(subject, auth);
+@@ -743,7 +744,7 @@ static bool verify_trust_chain(private_credential_manager_t *this,
+ 				auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer));
+ 				DBG1(DBG_CFG, "  using trusted ca certificate \"%Y\"",
+ 							  issuer->get_subject(issuer));
+-				trusted = TRUE;
++				trusted = is_anchor = TRUE;
+ 			}
+ 			else
+ 			{
+@@ -778,11 +779,18 @@ static bool verify_trust_chain(private_credential_manager_t *this,
+ 				DBG1(DBG_CFG, "  issuer is \"%Y\"",
+ 					 current->get_issuer(current));
+ 				call_hook(this, CRED_HOOK_NO_ISSUER, current);
++				if (trusted)
++				{
++					DBG1(DBG_CFG, "  reached end of incomplete trust chain for "
++						 "trusted certificate \"%Y\"",
++						 subject->get_subject(subject));
++				}
+ 				break;
+ 			}
+ 		}
+-		if (!check_certificate(this, current, issuer, online,
+-							   pathlen, trusted, auth))
++		/* don't do online verification here */
++		if (!check_certificate(this, current, issuer, FALSE,
++							   pathlen, is_anchor, auth))
+ 		{
+ 			trusted = FALSE;
+ 			issuer->destroy(issuer);
+@@ -794,7 +802,7 @@ static bool verify_trust_chain(private_credential_manager_t *this,
+ 		}
+ 		current->destroy(current);
+ 		current = issuer;
+-		if (trusted)
++		if (is_anchor)
+ 		{
+ 			DBG1(DBG_CFG, "  reached self-signed root ca with a "
+ 				 "path length of %d", pathlen);
+@@ -807,6 +815,34 @@ static bool verify_trust_chain(private_credential_manager_t *this,
+ 		DBG1(DBG_CFG, "maximum path length of %d exceeded", MAX_TRUST_PATH_LEN);
+ 		call_hook(this, CRED_HOOK_EXCEEDED_PATH_LEN, subject);
+ 	}
++	else if (trusted && online)
++	{
++		enumerator_t *enumerator;
++		auth_rule_t rule;
++
++		/* do online revocation checks after basic validation of the chain */
++		pathlen = 0;
++		current = subject;
++		enumerator = auth->create_enumerator(auth);
++		while (enumerator->enumerate(enumerator, &rule, &issuer))
++		{
++			if (rule == AUTH_RULE_CA_CERT || rule == AUTH_RULE_IM_CERT)
++			{
++				if (!check_certificate(this, current, issuer, TRUE, pathlen++,
++									   rule == AUTH_RULE_CA_CERT, auth))
++				{
++					trusted = FALSE;
++					break;
++				}
++				else if (rule == AUTH_RULE_CA_CERT)
++				{
++					break;
++				}
++				current = issuer;
++			}
++		}
++		enumerator->destroy(enumerator);
++	}
+ 	if (trusted)
+ 	{
+ 		result->merge(result, auth, FALSE);
+-- 
+2.25.1
+
diff --git a/meta-networking/recipes-support/strongswan/strongswan_5.8.4.bb b/meta-networking/recipes-support/strongswan/strongswan_5.8.4.bb
index 8a5855fb8..c11748645 100644
--- a/meta-networking/recipes-support/strongswan/strongswan_5.8.4.bb
+++ b/meta-networking/recipes-support/strongswan/strongswan_5.8.4.bb
@@ -14,6 +14,7 @@  SRC_URI = "http://download.strongswan.org/strongswan-${PV}.tar.bz2 \
            file://CVE-2021-41990.patch \
            file://CVE-2021-41991.patch \
            file://CVE-2021-45079.patch \
+           file://CVE-2022-40617.patch \
            "
 
 SRC_URI[md5sum] = "0634e7f40591bd3f6770e583c3f27d29"
-- 
2.25.1