Summary
An inverted comparison in the OpenSSL TLS backend causes IP SubjectAltName (SAN) verification to accept certificates with mismatched IP addresses and reject certificates with correct IP addresses. This allows a network attacker with a valid CA-signed certificate containing any IP SAN to perform MITM attacks against libgit2 clients connecting to IP-literal HTTPS URLs.
Details
The verify_server_cert() function in src/libgit2/streams/openssl.c uses !!memcmp() to compare IP SubjectAltName entries:
} else if (type == GEN_IPADD) {
/* Here name isn't so much a name but a binary representation of the IP */
matched = addr && !!memcmp(name, addr, namelen);
}
Since memcmp() returns 0 for matching buffers and non-zero for mismatches, applying !! inverts the logic:
- Matching IPs:
memcmp() returns 0 → !!0 = 0 → matched = 0 → certificate REJECTED
- Mismatched IPs:
memcmp() returns non-zero → !!n = 1 → matched = 1 → certificate ACCEPTED
This is the opposite of the intended behavior. The subsequent control flow at lines 437-441 then incorrectly accepts mismatched certificates (matched == 1 leads to goto cleanup) and rejects matching certificates (matched == 0 leads to goto cert_fail_name).
Conditions for exploitation:
- Target must use libgit2 built with OpenSSL (common on Linux/Unix)
- Connection must be to an IP-literal URL (e.g.,
https://203.0.113.10/repo.git)
- Attacker must have a valid CA-trusted certificate containing any IP SAN (not necessarily the target IP)
- Attacker must be in a network position to intercept traffic (MITM)
Additional impact: The inversion also causes certificates with the correct IP SAN to be rejected, meaning legitimate connections to IP-literal URLs with properly configured certificates would fail.
PoC
- Generate a CA and server certificate with IP SAN 192.0.2.1 (wrong IP)
- Start an HTTPS server on 127.0.0.1 using this certificate
- Build libgit2 with OpenSSL and attempt to connect to
https://127.0.0.1/repo.git
- Observe that the certificate with wrong IP (192.0.2.1) is incorrectly accepted
Closing
Please let me know what you think. I am happy to supply PoC upon request including a fix and/or test patch.
Impact
This is a certificate validation bypass vulnerability. It affects any application using libgit2 with OpenSSL that connects to IP-literal HTTPS URLs. A network attacker (MITM position) with a valid CA-signed certificate containing any IP SAN can intercept and modify git traffic, potentially leading to:
- Code injection via malicious repository content
- Credential theft if authentication is performed over the connection
- Supply chain attacks if used in CI/CD pipelines
The vulnerability is mitigated by the following factors:
- Only affects IP-literal URLs (domain names use DNS SAN verification which is correct)
- Only affects OpenSSL builds (macOS SecureTransport, Windows Schannel/WinHTTP, and mbedTLS are not affected)
- Attacker still needs a valid CA-trusted certificate with an IP SAN
suggested fix patch (tested, removes the vulnerability):
From: Pavel Kohout, Aisle Research, www.aisle.com
Subject: [PATCH] Fix inverted IP SubjectAltName comparison in OpenSSL backend
The verify_server_cert() function in the OpenSSL TLS backend incorrectly
uses !!memcmp() to compare IP SubjectAltName entries. Since memcmp()
returns 0 for matching buffers and non-zero for mismatches, the !!
operator inverts the logic: matching IPs result in matched=0 (rejected)
while mismatched IPs result in matched=1 (accepted). This allows a
MITM attacker with a valid CA-signed certificate containing any IP SAN
to bypass hostname verification for IP-literal HTTPS URLs.
Reported-by: Pavel Kohout, Aisle Research, www.aisle.com
---
diff --git a/src/libgit2/streams/openssl.c b/src/libgit2/streams/openssl.c
index f12b699..c97a14f 100644
--- a/src/libgit2/streams/openssl.c
+++ b/src/libgit2/streams/openssl.c
@@ -379,6 +379,7 @@ static int verify_server_cert(SSL *ssl, const char *host)
struct in6_addr addr6;
struct in_addr addr4;
void *addr = NULL;
+ size_t addrlen = 0;
int i = -1, j, error = 0;
if (SSL_get_verify_result(ssl) != X509_V_OK) {
@@ -390,10 +391,12 @@ static int verify_server_cert(SSL *ssl, const char *host)
if (p_inet_pton(AF_INET, host, &addr4)) {
type = GEN_IPADD;
addr = &addr4;
+ addrlen = sizeof(addr4);
} else {
if (p_inet_pton(AF_INET6, host, &addr6)) {
type = GEN_IPADD;
addr = &addr6;
+ addrlen = sizeof(addr6);
}
}
@@ -428,7 +431,7 @@ static int verify_server_cert(SSL *ssl, const char *host)
matched = !!check_host_name(host, name);
} else if (type == GEN_IPADD) {
/* Here name isn't so much a name but a binary representation of the IP */
- matched = addr && !!memcmp(name, addr, namelen);
+ matched = (addr && namelen == addrlen && memcmp(name, addr, namelen) == 0);
}
}
}
Summary
An inverted comparison in the OpenSSL TLS backend causes IP SubjectAltName (SAN) verification to accept certificates with mismatched IP addresses and reject certificates with correct IP addresses. This allows a network attacker with a valid CA-signed certificate containing any IP SAN to perform MITM attacks against libgit2 clients connecting to IP-literal HTTPS URLs.
Details
The
verify_server_cert()function insrc/libgit2/streams/openssl.cuses!!memcmp()to compare IP SubjectAltName entries:Since
memcmp()returns 0 for matching buffers and non-zero for mismatches, applying!!inverts the logic:memcmp()returns 0 →!!0= 0 →matched = 0→ certificate REJECTEDmemcmp()returns non-zero →!!n= 1 →matched = 1→ certificate ACCEPTEDThis is the opposite of the intended behavior. The subsequent control flow at lines 437-441 then incorrectly accepts mismatched certificates (
matched == 1leads togoto cleanup) and rejects matching certificates (matched == 0leads togoto cert_fail_name).Conditions for exploitation:
https://203.0.113.10/repo.git)Additional impact: The inversion also causes certificates with the correct IP SAN to be rejected, meaning legitimate connections to IP-literal URLs with properly configured certificates would fail.
PoC
https://127.0.0.1/repo.gitClosing
Please let me know what you think. I am happy to supply PoC upon request including a fix and/or test patch.
Impact
This is a certificate validation bypass vulnerability. It affects any application using libgit2 with OpenSSL that connects to IP-literal HTTPS URLs. A network attacker (MITM position) with a valid CA-signed certificate containing any IP SAN can intercept and modify git traffic, potentially leading to:
The vulnerability is mitigated by the following factors:
suggested fix patch (tested, removes the vulnerability):