Moderate severityNVD Advisory· Published Aug 21, 2014· Updated May 6, 2026
CVE-2014-3577
CVE-2014-3577
Description
org.apache.http.conn.ssl.AbstractVerifier in Apache HttpComponents HttpClient before 4.3.5 and HttpAsyncClient before 4.0.2 does not properly verify that the server hostname matches a domain name in the subject's Common Name (CN) or subjectAltName field of the X.509 certificate, which allows man-in-the-middle attackers to spoof SSL servers via a "CN=" string in a field in the distinguished name (DN) of a certificate, as demonstrated by the "foo,CN=www.apache.org" string in the O field.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.apache.httpcomponents:httpclientMaven | < 4.3.5 | 4.3.5 |
Affected products
2Patches
151cc67567765Improved cert subject parsing
2 files changed · +58 −50
httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java+37 −38 modified@@ -34,14 +34,20 @@ import java.security.cert.Certificate; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Locale; -import java.util.StringTokenizer; +import javax.naming.InvalidNameException; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.ldap.LdapName; +import javax.naming.ldap.Rdn; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; @@ -253,47 +259,40 @@ boolean validCountryWildcard(final String cn) { } public static String[] getCNs(final X509Certificate cert) { - final LinkedList<String> cnList = new LinkedList<String>(); - /* - Sebastian Hauer's original StrictSSLProtocolSocketFactory used - getName() and had the following comment: - - Parses a X.500 distinguished name for the value of the - "Common Name" field. This is done a bit sloppy right - now and should probably be done a bit more according to - <code>RFC 2253</code>. - - I've noticed that toString() seems to do a better job than - getName() on these X500Principal objects, so I'm hoping that - addresses Sebastian's concern. - - For example, getName() gives me this: - 1.2.840.113549.1.9.1=#16166a756c6975736461766965734063756362632e636f6d - - whereas toString() gives me this: - EMAILADDRESS=juliusdavies@cucbc.com - - Looks like toString() even works with non-ascii domain names! - I tested it with "花子.co.jp" and it worked fine. - */ - final String subjectPrincipal = cert.getSubjectX500Principal().toString(); - final StringTokenizer st = new StringTokenizer(subjectPrincipal, ",+"); - while(st.hasMoreTokens()) { - final String tok = st.nextToken().trim(); - if (tok.length() > 3) { - if (tok.substring(0, 3).equalsIgnoreCase("CN=")) { - cnList.add(tok.substring(3)); - } - } + try { + return extractCNs(subjectPrincipal); + } catch (SSLException ex) { + return null; } - if(!cnList.isEmpty()) { - final String[] cns = new String[cnList.size()]; - cnList.toArray(cns); - return cns; - } else { + } + + static String[] extractCNs(final String subjectPrincipal) throws SSLException { + if (subjectPrincipal == null) { return null; } + final List<String> cns = new ArrayList<String>(); + try { + final LdapName subjectDN = new LdapName(subjectPrincipal); + final List<Rdn> rdns = subjectDN.getRdns(); + for (int i = rdns.size() - 1; i >= 0; i--) { + final Rdn rds = rdns.get(i); + final Attributes attributes = rds.toAttributes(); + final Attribute cn = attributes.get("cn"); + if (cn != null) { + try { + final Object value = cn.get(); + if (value != null) { + cns.add(value.toString()); + } + } catch (NamingException ignore) { + } + } + } + } catch (InvalidNameException e) { + throw new SSLException(subjectPrincipal + " is not a valid X500 distinguished name"); + } + return cns.isEmpty() ? null : cns.toArray(new String[ cns.size() ]); } /**
httpclient/src/test/java/org/apache/http/conn/ssl/TestHostnameVerifier.java+21 −12 modified@@ -29,7 +29,6 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; -import java.security.Principal; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Arrays; @@ -38,7 +37,6 @@ import org.junit.Assert; import org.junit.Test; -import org.mockito.Mockito; /** * Unit tests for {@link X509HostnameVerifier}. @@ -349,16 +347,27 @@ public void testHTTPCLIENT_1255() { checkMatching(shv, "mail.a.b.c.com", cns, alt, false); // OK } - public void testGetCNs() { - final Principal principal = Mockito.mock(Principal.class); - final X509Certificate cert = Mockito.mock(X509Certificate.class); - Mockito.when(cert.getSubjectDN()).thenReturn(principal); - Mockito.when(principal.toString()).thenReturn("bla, bla, blah"); - Assert.assertArrayEquals(new String[] {}, AbstractVerifier.getCNs(cert)); - Mockito.when(principal.toString()).thenReturn("Cn=, Cn= , CN, OU=CN="); - Assert.assertArrayEquals(new String[] {}, AbstractVerifier.getCNs(cert)); - Mockito.when(principal.toString()).thenReturn(" Cn=blah, CN= blah , OU=CN=yada"); - Assert.assertArrayEquals(new String[] {"blah", " blah"}, AbstractVerifier.getCNs(cert)); + @Test + public void testExtractCN() throws Exception { + Assert.assertArrayEquals(new String[] {"blah"}, AbstractVerifier.extractCNs("cn=blah, ou=blah, o=blah")); + Assert.assertArrayEquals(new String[] {"blah", "yada", "booh"}, AbstractVerifier.extractCNs("cn=blah, cn=yada, cn=booh")); + Assert.assertArrayEquals(new String[] {"blah"}, AbstractVerifier.extractCNs("c = pampa , cn = blah , ou = blah , o = blah")); + Assert.assertArrayEquals(new String[] {"blah"}, AbstractVerifier.extractCNs("cn=\"blah\", ou=blah, o=blah")); + Assert.assertArrayEquals(new String[] {"blah blah"}, AbstractVerifier.extractCNs("cn=\"blah blah\", ou=blah, o=blah")); + Assert.assertArrayEquals(new String[] {"blah, blah"}, AbstractVerifier.extractCNs("cn=\"blah, blah\", ou=blah, o=blah")); + Assert.assertArrayEquals(new String[] {"blah, blah"}, AbstractVerifier.extractCNs("cn=blah\\, blah, ou=blah, o=blah")); + Assert.assertArrayEquals(new String[] {"blah"}, AbstractVerifier.extractCNs("c = cn=uuh, cn=blah, ou=blah, o=blah")); + Assert.assertArrayEquals(new String[] {""}, AbstractVerifier.extractCNs("cn= , ou=blah, o=blah")); + } + + @Test(expected = SSLException.class) + public void testExtractCNInvalid1() throws Exception { + AbstractVerifier.extractCNs("blah,blah"); + } + + @Test(expected = SSLException.class) + public void testExtractCNInvalid2() throws Exception { + AbstractVerifier.extractCNs("cn,o=blah"); } }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
61- packetstormsecurity.com/files/127913/Apache-HttpComponents-Man-In-The-Middle.htmlnvdExploitThird Party AdvisoryVDB EntryWEB
- seclists.org/fulldisclosure/2014/Aug/48nvdExploitMailing ListThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2014-1146.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2014-1166.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2014-1833.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2014-1834.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2014-1835.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2014-1836.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2014-1891.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2014-1892.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2015-0125.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2015-0158.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2015-0675.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2015-0720.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2015-0765.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2015-0850.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2015-0851.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2015-1176.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2015-1177.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2015-1888.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2016-1773.htmlnvdThird Party AdvisoryWEB
- rhn.redhat.com/errata/RHSA-2016-1931.htmlnvdThird Party AdvisoryWEB
- secunia.com/advisories/60466nvdThird Party Advisory
- secunia.com/advisories/60589nvdThird Party Advisory
- secunia.com/advisories/60713nvdThird Party Advisory
- www.securityfocus.com/bid/69258nvdThird Party AdvisoryVDB Entry
- www.securitytracker.com/id/1030812nvdThird Party AdvisoryVDB Entry
- www.ubuntu.com/usn/USN-2769-1nvdThird Party AdvisoryWEB
- access.redhat.com/solutions/1165533nvdThird Party AdvisoryWEB
- exchange.xforce.ibmcloud.com/vulnerabilities/95327nvdThird Party AdvisoryVDB EntryWEB
- github.com/advisories/GHSA-cfh5-3ghh-wfjxghsaADVISORY
- h20566.www2.hpe.com/portal/site/hpsc/public/kb/docDisplaynvdThird Party Advisory
- h20566.www2.hpe.com/portal/site/hpsc/public/kb/docDisplaynvdThird Party Advisory
- nvd.nist.gov/vuln/detail/CVE-2014-3577ghsaADVISORY
- lists.opensuse.org/opensuse-security-announce/2020-11/msg00032.htmlnvdWEB
- lists.opensuse.org/opensuse-security-announce/2020-11/msg00033.htmlnvdWEB
- www.openwall.com/lists/oss-security/2021/10/06/1nvdWEB
- www.oracle.com/technetwork/security-advisory/cpujul2018-4258247.htmlnvdWEB
- www.osvdb.org/110143nvdBroken Link
- github.com/apache/httpcomponents-client/commit/51cc67567765d67f878f0dcef61b5ded454d3122ghsaWEB
- lists.apache.org/thread.html/519eb0fd45642dcecd9ff74cb3e71c20a4753f7d82e2f07864b5108f@%3Cdev.drill.apache.org%3EghsaWEB
- lists.apache.org/thread.html/b0656d359c7d40ec9f39c8cc61bca66802ef9a2a12ee199f5b0c1442@%3Cdev.drill.apache.org%3EghsaWEB
- lists.apache.org/thread.html/f9bc3e55f4e28d1dcd1a69aae6d53e609a758e34d2869b4d798e13cc@%3Cissues.drill.apache.org%3EghsaWEB
- lists.apache.org/thread.html/r36e44ffc1a9b365327df62cdfaabe85b9a5637de102cea07d79b2dbf@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rc774278135816e7afc943dc9fc78eb0764f2c84a2b96470a0187315c@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rd49aabd984ed540c8ff7916d4d79405f3fa311d2fdbcf9ed307839a6@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rec7160382badd3ef4ad017a22f64a266c7188b9ba71394f0d321e2d4@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rfb87e0bf3995e7d560afeed750fac9329ff5f1ad49da365129b7f89e@%3Ccommits.cxf.apache.org%3EghsaWEB
- lists.apache.org/thread.html/rff42cfa5e7d75b7c1af0e37589140a8f1999e578a75738740b244bd4@%3Ccommits.cxf.apache.org%3EghsaWEB
- security.netapp.com/advisory/ntap-20231027-0003ghsaWEB
- svn.apache.org/viewvcghsaWEB
- lists.apache.org/thread.html/519eb0fd45642dcecd9ff74cb3e71c20a4753f7d82e2f07864b5108f%40%3Cdev.drill.apache.org%3Envd
- lists.apache.org/thread.html/b0656d359c7d40ec9f39c8cc61bca66802ef9a2a12ee199f5b0c1442%40%3Cdev.drill.apache.org%3Envd
- lists.apache.org/thread.html/f9bc3e55f4e28d1dcd1a69aae6d53e609a758e34d2869b4d798e13cc%40%3Cissues.drill.apache.org%3Envd
- lists.apache.org/thread.html/r36e44ffc1a9b365327df62cdfaabe85b9a5637de102cea07d79b2dbf%40%3Ccommits.cxf.apache.org%3Envd
- lists.apache.org/thread.html/rc774278135816e7afc943dc9fc78eb0764f2c84a2b96470a0187315c%40%3Ccommits.cxf.apache.org%3Envd
- lists.apache.org/thread.html/rd49aabd984ed540c8ff7916d4d79405f3fa311d2fdbcf9ed307839a6%40%3Ccommits.cxf.apache.org%3Envd
- lists.apache.org/thread.html/rec7160382badd3ef4ad017a22f64a266c7188b9ba71394f0d321e2d4%40%3Ccommits.cxf.apache.org%3Envd
- lists.apache.org/thread.html/rfb87e0bf3995e7d560afeed750fac9329ff5f1ad49da365129b7f89e%40%3Ccommits.cxf.apache.org%3Envd
- lists.apache.org/thread.html/rff42cfa5e7d75b7c1af0e37589140a8f1999e578a75738740b244bd4%40%3Ccommits.cxf.apache.org%3Envd
- security.netapp.com/advisory/ntap-20231027-0003/nvd
News mentions
0No linked articles in our index yet.