AI_ONLY_REPORT package: glib-networking-2.80.0-3.el10 ------ Summary: Denial of Service via Infinite Loop in Circular Certificate Chain Traversal: a remote peer can supply a certificate chain whose issuer relationships form a cycle, causing unbounded traversal during certificate verification in the GnuTLS backend and resulting in a CPU-consuming handshake hang. Requirements to exploit: The attacker must be able to present a crafted certificate chain to an application using `glib-networking-2.80.0-3.el10` with the GnuTLS backend enabled and certificate verification exercised. This is most direct when a server verifies client certificates, or when a client connects to an attacker-controlled TLS server. Component affected: `glib-networking-2.80.0-3.el10`, GnuTLS backend; `tls/gnutls/gtlscertificate-gnutls.c` issuer-link construction and `tls/gnutls/gtlsdatabase-gnutls.c` `convert_certificate_chain_to_gnutls()` Version affected: `glib-networking-2.80.0-3.el10` Patch available: no released package fix established; proposed patch included below Version fixed: unknown Upstream coordination: Not notified. CVSS: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - 7.5 (HIGH) AV:N - The vulnerable path is reached during a network TLS handshake. AC:L - An attacker needs only to present a crafted certificate chain that causes cyclic issuer traversal. PR:N - No prior authentication is required to supply the peer certificate chain. UI:N - In server-side certificate verification scenarios, no separate user action is required beyond the network connection. S:U - The impact is confined to the vulnerable process performing certificate verification. C:N - No confidentiality impact is established by the available evidence. I:N - No integrity impact is established by the available evidence. A:H - The affected handshake path can loop indefinitely and consume CPU, denying service to the affected process or worker. Impact: Important. Red Hat classifies flaws that allow remote users to cause a denial of service as Important when they can compromise availability with relative ease. Here, a remote peer can trigger an infinite loop during certificate verification and tie up CPU in the handshake path. The issue does not show confidentiality, integrity, or code execution impact, and reachability depends on use of the GnuTLS backend and the relevant verification path, so Critical is not warranted. Embargo: no Reason: The currently established impact is denial of service only, with no demonstrated code execution or data exposure. Reachability is also dependent on backend and deployment choices, so prompt remediation without embargo appears proportionate. Acknowledgement: Aisle Research Vulnerability Details: In the GnuTLS backend, peer certificates are converted into `GTlsCertificateGnutls` objects and linked through issuer checks. The available code allows one peer-provided certificate to be set as the issuer of another when `gnutls_x509_crt_check_issuer()` succeeds: ```c if (j != i && gnutls_x509_crt_check_issuer (gnutls_certs[i], gnutls_certs[j])) issuer = glib_certs->pdata[j]; if (issuer) g_tls_certificate_gnutls_set_issuer (glib_certs->pdata[i], issuer); ``` If two certificates in the presented chain mutually satisfy that issuer check, the resulting in-memory chain can become cyclic rather than terminating at a `NULL` issuer. Later, verification code converts the chain for GnuTLS consumption by walking issuer links until `NULL`, but that traversal has no cycle detection and no explicit depth bound: ```c for (cert = G_TLS_CERTIFICATE (chain); cert; cert = g_tls_certificate_get_issuer (cert)) gnutls_chain->length++; for (cert = G_TLS_CERTIFICATE (chain); cert; cert = g_tls_certificate_get_issuer (cert), i++) gnutls_chain->chain[i] = g_tls_certificate_gnutls_get_cert (G_TLS_CERTIFICATE_GNUTLS (cert)); ``` The relevant call path is direct: peer certificate retrieval builds the chain, and certificate verification later calls `convert_certificate_chain_to_gnutls()`. When the issuer graph contains a cycle, traversal does not terminate, causing the handshake thread or worker to spin indefinitely and consume CPU. Based on the available evidence, this is an availability issue in the certificate verification path rather than a broader compromise. Steps to reproduce: 1. Use an application built against `glib-networking-2.80.0-3.el10` with the GnuTLS backend enabled. 2. Ensure the application performs certificate verification on a peer-supplied chain. 3. Present a crafted certificate chain containing two cross-issued certificates such that certificate A is accepted as issuer of B and certificate B is accepted as issuer of A. 4. Trigger the TLS handshake so the peer certificate chain is built and then verified. 5. Observe that control remains in the issuer-traversal loops inside `convert_certificate_chain_to_gnutls()`, with the handshake stalling and CPU usage remaining elevated. Mitigation: Until a fix is available, avoid exposing the affected GnuTLS-backed verification path to untrusted peer certificate chains where possible. In practice, this means avoiding client-certificate verification from untrusted remote parties unless necessary, preferring an alternative TLS backend if one is available in the deployment, and enforcing handshake or worker timeouts so a stuck verification path cannot tie up service resources indefinitely. Proposed Fix: Add cycle detection and a reasonable depth bound while converting the certificate chain, and fail verification cleanly if a malformed cyclic chain is detected. ```diff diff --git a/tls/gnutls/gtlsdatabase-gnutls.c b/tls/gnutls/gtlsdatabase-gnutls.c @@ static CertificateChain * convert_certificate_chain_to_gnutls (GTlsCertificateGnutls *chain) { GTlsCertificate *cert; CertificateChain *gnutls_chain; + GHashTable *seen; + const guint max_depth = 100; guint i = 0; gnutls_chain = certificate_chain_new (); + seen = g_hash_table_new (g_direct_hash, g_direct_equal); for (cert = G_TLS_CERTIFICATE (chain); cert; cert = g_tls_certificate_get_issuer (cert)) gnutls_chain->length++; + { + if (gnutls_chain->length >= max_depth || g_hash_table_contains (seen, cert)) + goto fail; + g_hash_table_add (seen, cert); + gnutls_chain->length++; + } gnutls_chain->chain = g_new (gnutls_x509_crt_t, gnutls_chain->length); + g_hash_table_remove_all (seen); for (cert = G_TLS_CERTIFICATE (chain); cert; cert = g_tls_certificate_get_issuer (cert), i++) gnutls_chain->chain[i] = g_tls_certificate_gnutls_get_cert (G_TLS_CERTIFICATE_GNUTLS (cert)); + { + if (i >= gnutls_chain->length || g_hash_table_contains (seen, cert)) + goto fail; + g_hash_table_add (seen, cert); + gnutls_chain->chain[i] = g_tls_certificate_gnutls_get_cert (G_TLS_CERTIFICATE_GNUTLS (cert)); + } g_assert (i == gnutls_chain->length); + g_hash_table_unref (seen); return gnutls_chain; + +fail: + g_hash_table_unref (seen); + certificate_chain_free (gnutls_chain); + return NULL; } @@ g_mutex_lock (&priv->mutex); gnutls_chain = convert_certificate_chain_to_gnutls (G_TLS_CERTIFICATE_GNUTLS (chain)); + if (!gnutls_chain) + { + g_mutex_unlock (&priv->mutex); + return G_TLS_CERTIFICATE_GENERIC_ERROR; + } gerr = gnutls_x509_trust_list_verify_crt (priv->trust_list, gnutls_chain->chain, gnutls_chain->length, 0, &gnutls_result, NULL); ``` ------ This report was generated using AI technology. Always review AI-generated content prior to use