VRT 391,810 CVEs tracked · 15,472 in RASP scope · data as of 23 minutes ago

CVE-2012-6153

4.3 Medium Protected by RASP

Description

http/conn/ssl/AbstractVerifier.java in Apache Commons HttpClient before 4.2.3 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 certificate with a subject that specifies a common name in a field that is not the CN field. NOTE: this issue exists because of an incomplete fix for CVE-2012-5783.

CWE-20 · Improper input validation

Exploitation Status

No public exploit

Nothing published shows this CVE being exploited, which is not the same as ruling it out. nothing published in 12 years.

CVSS E:U

  • CISA KEV not listed
  • CISA Vulnrichment no assessment published
  • Indexed PoC none indexed
  • EPSS 5.8% chance in 30 days

Waratek Defense Posture

Protected by RASP

A Waratek agent blocks this today.

Applicable rule: CVE is covered by a multi-CVE ARMR patch rule

  • Protection full a patch rule written for this CVE
  • Action available patch rule
  • Review human armr-file
  • Record active
Decided by armr-patch-file : An ARMR patch file on disk for this CVE
Finding CVE is covered by a multi-CVE ARMR patch rule

ARMR rule files

1 file

Shipped files covering this CVE. A CVE genuinely takes more than one: separate Maven artifacts hooking different parser classes, the same patch built for two ARMR versions, or a fix at both the framework and the container.

rules/libraries/apache/commons/CVE-2012-5783/patch/2.6/CVE-2012-5783.armr patch rule added 2020-06-25 updated 2026-03-04
app("APACHE COMMONS"):
    requires(version: "ARMR/2.6")

    /***************************************************************************
        CVE-2012-5783 (APACHE COMMONS)

        CVSS 2.0 metrics:
            Base Score          | 5.8 MEDIUM
            Access Vector       | Network
            Access Complexity   | Medium
            Authentication      | None
            Confidentiality     | Partial
            Integrity           | Partial
            Availability        | None

        Description:
            Apache Commons HttpClient 3.x, as used in Amazon Flexible Payments
            Service (FPS) merchant Java SDK and other products, does not 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 an arbitrary valid
            certificate.

        Resources:
            https://bugzilla.redhat.com/show_bug.cgi?id=873317
            https://issues.apache.org/jira/browse/HTTPCLIENT-1265
            http://svn.apache.org/viewvc/httpcomponents/oac.hc3x/trunk/src/java/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java?view=markup
    ****************************************************************************
        CVE-2012-6153 (APACHE COMMONS)

        CVSS 2.0 metrics:
            Base Score        | 4.3 MEDIUM
            Access Vector     | Network
            Access Complexity | Medium
            Authentication    | None
            Confidentiality   | None
            Integrity         | Partial
            Availability      | None

        Description:
            http/conn/ssl/AbstractVerifier.java in Apache Commons HttpClient before
            4.2.3 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 certificate with a subject that specifies a common name in
            a field that is not the CN field. NOTE: this issue exists because of an
            incomplete fix for CVE-2012-5783.

        Resources:
            https://bugzilla.redhat.com/show_bug.cgi?id=1129916
            http://svn.apache.org/viewvc?view=revision&revision=1411705
    ****************************************************************************
        CVE-2014-3577 (APACHE COMMONS)

        CVSS 2.0 metrics:
            Base Score        | 5.8 MEDIUM
            Access Vector     | Network
            Access Complexity | Medium
            Authentication    | None
            Confidentiality   | Partial
            Integrity         | Partial
            Availability      | None

        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.

        Resources:
            https://bugzilla.redhat.com/show_bug.cgi?id=1129074
            http://svn.apache.org/viewvc?view=revision&revision=1614064
    ****************************************************************************
        Affected Operating Systems:
            Any

        Affected Versions:
            Apache commons-httpclient 3.x

        Tested Versions:
            3.1

        Protection Provided:
            Functional

        Patch Version:
            1.0
    ***************************************************************************/

    patch("CVE-2012-5783 :01"):
        function("org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.createSocket(Ljava/lang/String;ILjava/net/InetAddress;ILorg/apache/commons/httpclient/params/HttpConnectionParams;)Ljava/net/Socket;",
            checksums: ["464eb9fd68"])  // commons-httpclient:3.1
        exit()

        code(language: java,   import: ["javax.naming.InvalidNameException",
                                        "javax.naming.NamingException",
                                        "javax.naming.directory.Attribute",
                                        "javax.naming.directory.Attributes",
                                        "javax.naming.ldap.LdapName",
                                        "javax.naming.ldap.Rdn",
                                        "javax.net.ssl.SSLException",
                                        "javax.net.ssl.SSLSession",
                                        "javax.net.ssl.SSLSocket",
                                        "java.io.IOException",
                                        "java.io.InputStream",
                                        "java.net.InetAddress",
                                        "java.net.UnknownHostException",
                                        "java.security.cert.Certificate",
                                        "java.security.cert.CertificateParsingException",
                                        "java.security.cert.X509Certificate",
                                        "java.util.ArrayList",
                                        "java.util.Arrays",
                                        "java.util.Collection",
                                        "java.util.Iterator",
                                        "java.util.LinkedList",
                                        "java.util.List",
                                        "java.util.Locale",
                                        "java.util.NoSuchElementException",
                                        "java.util.regex.Pattern"]):
            private final static String[] BAD_COUNTRY_2LDS =
                    {"ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
                            "lg", "ne", "net", "or", "org"};

            private static final Pattern IPV4_PATTERN =
                    Pattern.compile("^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");

            private static final Pattern IPV6_STD_PATTERN =
                    Pattern.compile("^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");

            private static final Pattern IPV6_HEX_COMPRESSED_PATTERN =
                    Pattern.compile("^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$");

            public void patch(JavaFrame frame) {
                String host = frame.loadStringVariable(1);
                SSLSocket sslSocket = (SSLSocket) frame.loadObjectOperand(0);

                try {
                    verifyHostName(host, sslSocket);
                    frame.returnObject(sslSocket);
                } catch (IOException ex) {
                    frame.raiseException(ex);
                } catch (RuntimeException ex) {
                    frame.raiseException(ex);
                }
            }

            private static void verifyHostName(String host, SSLSocket ssl)
                    throws IOException {
                if (host == null) {
                    throw new IllegalArgumentException("host to verify was null");
                }

                SSLSession session = ssl.getSession();
                if (session == null) {
                    InputStream in = ssl.getInputStream();
                    in.available();
                    session = ssl.getSession();
                    if (session == null) {
                        ssl.startHandshake();
                        session = ssl.getSession();
                    }
                }

                Certificate[] certs = session.getPeerCertificates();
                verifyHostName(host.trim().toLowerCase(Locale.US), (X509Certificate) certs[0]);
            }

            private static void verifyHostName(final String host, X509Certificate cert)
                    throws SSLException {
                String[] cns = getCNs(cert);
                String[] subjectAlts = getSubjectAlts(cert, host);
                verifyHostName(host, cns, subjectAlts);
            }

            private static void verifyHostName(final String host, String[] cns, String[] subjectAlts)
                    throws SSLException {

                final LinkedList<String> names = new LinkedList<String>();
                if (cns != null && cns.length > 0 && cns[0] != null) {
                    names.add(cns[0]);
                }
                if (subjectAlts != null) {
                    for (final String subjectAlt : subjectAlts) {
                        if (subjectAlt != null) {
                            names.add(subjectAlt);
                        }
                    }
                }

                if (names.isEmpty()) {
                    final String msg = "Certificate for <" + host + "> doesn't contain CN or DNS subjectAlt";
                    throw new SSLException(msg);
                }

                final StringBuffer buf = new StringBuffer();
                final String hostName = normaliseIPv6Address(host.trim().toLowerCase(Locale.ENGLISH));
                boolean match = false;

                for (final Iterator<String> it = names.iterator(); it.hasNext(); ) {
                    String cn = it.next();
                    cn = cn.toLowerCase(Locale.ENGLISH);
                    buf.append(" <");
                    buf.append(cn);
                    buf.append('>');
                    if (it.hasNext()) {
                        buf.append(" OR");
                    }

                    final String[] parts = cn.split("\\.");
                    final boolean doWildcard =
                            parts.length >= 3 && parts[0].endsWith("*") &&
                                    validCountryWildcard(cn) && !isIPAddress(host);

                    if (doWildcard) {
                        final String firstpart = parts[0];
                        if (firstpart.length() > 1) {
                            final String prefix = firstpart.substring(0, firstpart.length() - 1);
                            final String suffix = cn.substring(firstpart.length());
                            final String hostSuffix = hostName.substring(prefix.length());
                            match = hostName.startsWith(prefix) && hostSuffix.endsWith(suffix);
                        } else {
                            match = hostName.endsWith(cn.substring(1));
                        }
                        if (match) {
                            match = countDots(hostName) == countDots(cn);
                        }
                    } else {
                        match = hostName.equals(normaliseIPv6Address(cn));
                    }
                    if (match) {
                        break;
                    }
                }
                if (!match) {
                    throw new SSLException("hostname in certificate didn't match: <" + host + "> !=" + buf);
                }
            }

            private static boolean isIPAddress(final String hostname) {
                return hostname != null
                        && (
                        IPV4_PATTERN.matcher(hostname).matches()
                                || IPV6_STD_PATTERN.matcher(hostname).matches()
                                || IPV6_HEX_COMPRESSED_PATTERN.matcher(hostname).matches()
                );

            }

            private static int countDots(final String data) {
                int dots = 0;
                for (int i = 0; i < data.length(); i++) {
                    if (data.charAt(i) == '.') {
                        dots += 1;
                    }
                }
                return dots;
            }

            private static boolean validCountryWildcard(final String cn) {
                final String[] parts = cn.split("\\.");
                if (parts.length != 3 || parts[2].length() != 2) {
                    return true;
                }
                return Arrays.binarySearch(BAD_COUNTRY_2LDS, parts[1]) < 0;
            }

            private static String[] getCNs(final X509Certificate cert) {
                final String subjectPrincipal = cert.getSubjectX500Principal().toString();
                try {
                    return extractCNs(subjectPrincipal);
                } catch (SSLException ex) {
                    return null;
                }
            }

            private 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 (NoSuchElementException ignore) {
                            } 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[0]);
            }

            private static String[] getSubjectAlts(
                    final X509Certificate cert, final String hostname) {
                final int subjectType;
                if (isIPAddress(hostname)) {
                    subjectType = 7;
                } else {
                    subjectType = 2;
                }

                final LinkedList<String> subjectAltList = new LinkedList<String>();
                Collection<List<?>> c = null;
                try {
                    c = cert.getSubjectAlternativeNames();
                } catch (final CertificateParsingException cpe) {
                }
                if (c != null) {
                    for (final List<?> aC : c) {
                        final List<?> list = aC;
                        final int type = (Integer) list.get(0);
                        if (type == subjectType) {
                            final String s = (String) list.get(1);
                            subjectAltList.add(s);
                        }
                    }
                }
                if (!subjectAltList.isEmpty()) {
                    final String[] subjectAlts = new String[subjectAltList.size()];
                    subjectAltList.toArray(subjectAlts);
                    return subjectAlts;
                } else {
                    return null;
                }
            }

            private static String normaliseIPv6Address(final String hostname) {
                if (hostname == null || !isIPv6Address(hostname)) {
                    return hostname;
                }
                try {
                    final InetAddress inetAddress = InetAddress.getByName(hostname);
                    return inetAddress.getHostAddress();
                } catch (final UnknownHostException uhe) {
                    return hostname;
                }
            }

            private static boolean isIPv6Address(final String input) {
                return IPV6_STD_PATTERN.matcher(input).matches() || isIPv6HexCompressedAddress(input);
            }

            private static boolean isIPv6HexCompressedAddress(final String input) {
                int colonCount = 0;
                for (int i = 0; i < input.length(); i++) {
                    if (input.charAt(i) == ':') {
                        colonCount++;
                    }
                }
                return  colonCount <= 7 && IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches();
            }
        endcode
    endpatch

    patch("CVE-2012-5783 :02"):
        function("org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.createSocket(Ljava/lang/String;ILjava/net/InetAddress;ILorg/apache/commons/httpclient/params/HttpConnectionParams;)Ljava/net/Socket;",
            checksums: ["464eb9fd68"])  // commons-httpclient:3.1
        exit()

        code(language: java,   import: ["javax.naming.InvalidNameException",
                                        "javax.naming.NamingException",
                                        "javax.naming.directory.Attribute",
                                        "javax.naming.directory.Attributes",
                                        "javax.naming.ldap.LdapName",
                                        "javax.naming.ldap.Rdn",
                                        "javax.net.ssl.SSLException",
                                        "javax.net.ssl.SSLSession",
                                        "javax.net.ssl.SSLSocket",
                                        "java.io.IOException",
                                        "java.io.InputStream",
                                        "java.net.InetAddress",
                                        "java.net.UnknownHostException",
                                        "java.security.cert.Certificate",
                                        "java.security.cert.CertificateParsingException",
                                        "java.security.cert.X509Certificate",
                                        "java.util.ArrayList",
                                        "java.util.Arrays",
                                        "java.util.Collection",
                                        "java.util.Iterator",
                                        "java.util.LinkedList",
                                        "java.util.List",
                                        "java.util.Locale",
                                        "java.util.NoSuchElementException",
                                        "java.util.regex.Pattern"]):
            private final static String[] BAD_COUNTRY_2LDS =
                    {"ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
                            "lg", "ne", "net", "or", "org"};

            private static final Pattern IPV4_PATTERN =
                    Pattern.compile("^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");

            private static final Pattern IPV6_STD_PATTERN =
                    Pattern.compile("^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");

            private static final Pattern IPV6_HEX_COMPRESSED_PATTERN =
                    Pattern.compile("^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$");

            public void patch(JavaFrame frame) {
                String host = frame.loadStringVariable(1);
                SSLSocket sslSocket = (SSLSocket) frame.loadObjectOperand(0);

                try {
                    verifyHostName(host, (SSLSocket) sslSocket);
                    frame.returnObject(sslSocket);
                } catch (IOException ex) {
                    frame.raiseException(ex);
                } catch (RuntimeException ex) {
                    frame.raiseException(ex);
                }
            }

            private static void verifyHostName(String host, SSLSocket ssl)
                    throws IOException {
                if (host == null) {
                    throw new IllegalArgumentException("host to verify was null");
                }

                SSLSession session = ssl.getSession();
                if (session == null) {
                    InputStream in = ssl.getInputStream();
                    in.available();
                    session = ssl.getSession();
                    if (session == null) {
                        ssl.startHandshake();
                        session = ssl.getSession();
                    }
                }

                Certificate[] certs = session.getPeerCertificates();
                verifyHostName(host.trim().toLowerCase(Locale.US), (X509Certificate) certs[0]);
            }

            private static void verifyHostName(final String host, X509Certificate cert)
                    throws SSLException {
                String[] cns = getCNs(cert);
                String[] subjectAlts = getSubjectAlts(cert, host);
                verifyHostName(host, cns, subjectAlts);
            }

            private static void verifyHostName(final String host, String[] cns, String[] subjectAlts)
                    throws SSLException {

                final LinkedList<String> names = new LinkedList<String>();
                if (cns != null && cns.length > 0 && cns[0] != null) {
                    names.add(cns[0]);
                }
                if (subjectAlts != null) {
                    for (final String subjectAlt : subjectAlts) {
                        if (subjectAlt != null) {
                            names.add(subjectAlt);
                        }
                    }
                }

                if (names.isEmpty()) {
                    final String msg = "Certificate for <" + host + "> doesn't contain CN or DNS subjectAlt";
                    throw new SSLException(msg);
                }

                final StringBuffer buf = new StringBuffer();
                final String hostName = normaliseIPv6Address(host.trim().toLowerCase(Locale.ENGLISH));
                boolean match = false;

                for (final Iterator<String> it = names.iterator(); it.hasNext(); ) {
                    String cn = it.next();
                    cn = cn.toLowerCase(Locale.ENGLISH);
                    buf.append(" <");
                    buf.append(cn);
                    buf.append('>');
                    if (it.hasNext()) {
                        buf.append(" OR");
                    }

                    final String[] parts = cn.split("\\.");
                    final boolean doWildcard =
                            parts.length >= 3 && parts[0].endsWith("*") &&
                                    validCountryWildcard(cn) && !isIPAddress(host);

                    if (doWildcard) {
                        final String firstpart = parts[0];
                        if (firstpart.length() > 1) {
                            final String prefix = firstpart.substring(0, firstpart.length() - 1);
                            final String suffix = cn.substring(firstpart.length());
                            final String hostSuffix = hostName.substring(prefix.length());
                            match = hostName.startsWith(prefix) && hostSuffix.endsWith(suffix);
                        } else {
                            match = hostName.endsWith(cn.substring(1));
                        }
                        if (match) {
                            match = countDots(hostName) == countDots(cn);
                        }
                    } else {
                        match = hostName.equals(normaliseIPv6Address(cn));
                    }
                    if (match) {
                        break;
                    }
                }
                if (!match) {
                    throw new SSLException("hostname in certificate didn't match: <" + host + "> !=" + buf);
                }
            }

            private static boolean isIPAddress(final String hostname) {
                return hostname != null
                        && (
                        IPV4_PATTERN.matcher(hostname).matches()
                                || IPV6_STD_PATTERN.matcher(hostname).matches()
                                || IPV6_HEX_COMPRESSED_PATTERN.matcher(hostname).matches()
                );

            }

            private static int countDots(final String data) {
                int dots = 0;
                for (int i = 0; i < data.length(); i++) {
                    if (data.charAt(i) == '.') {
                        dots += 1;
                    }
                }
                return dots;
            }

            private static boolean validCountryWildcard(final String cn) {
                final String[] parts = cn.split("\\.");
                if (parts.length != 3 || parts[2].length() != 2) {
                    return true;
                }
                return Arrays.binarySearch(BAD_COUNTRY_2LDS, parts[1]) < 0;
            }

            private static String[] getCNs(final X509Certificate cert) {
                final String subjectPrincipal = cert.getSubjectX500Principal().toString();
                try {
                    return extractCNs(subjectPrincipal);
                } catch (SSLException ex) {
                    return null;
                }
            }

            private 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 (NoSuchElementException ignore) {
                            } 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[0]);
            }

            private static String[] getSubjectAlts(
                    final X509Certificate cert, final String hostname) {
                final int subjectType;
                if (isIPAddress(hostname)) {
                    subjectType = 7;
                } else {
                    subjectType = 2;
                }

                final LinkedList<String> subjectAltList = new LinkedList<String>();
                Collection<List<?>> c = null;
                try {
                    c = cert.getSubjectAlternativeNames();
                } catch (final CertificateParsingException cpe) {
                }
                if (c != null) {
                    for (final List<?> aC : c) {
                        final List<?> list = aC;
                        final int type = (Integer) list.get(0);
                        if (type == subjectType) {
                            final String s = (String) list.get(1);
                            subjectAltList.add(s);
                        }
                    }
                }
                if (!subjectAltList.isEmpty()) {
                    final String[] subjectAlts = new String[subjectAltList.size()];
                    subjectAltList.toArray(subjectAlts);
                    return subjectAlts;
                } else {
                    return null;
                }
            }

            private static String normaliseIPv6Address(final String hostname) {
                if (hostname == null || !isIPv6Address(hostname)) {
                    return hostname;
                }
                try {
                    final InetAddress inetAddress = InetAddress.getByName(hostname);
                    return inetAddress.getHostAddress();
                } catch (final UnknownHostException uhe) {
                    return hostname;
                }
            }

            private static boolean isIPv6Address(final String input) {
                return IPV6_STD_PATTERN.matcher(input).matches() || isIPv6HexCompressedAddress(input);
            }

            private static boolean isIPv6HexCompressedAddress(final String input) {
                int colonCount = 0;
                for (int i = 0; i < input.length(); i++) {
                    if (input.charAt(i) == ':') {
                        colonCount++;
                    }
                }
                return  colonCount <= 7 && IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches();
            }
        endcode
    endpatch

    patch("CVE-2012-5783 :03"):
        function("org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.createSocket(Ljava/lang/String;I)Ljava/net/Socket;",
            checksums: ["464eb9fd68"])  // commons-httpclient:3.1
        exit()

        code(language: java,   import: ["javax.naming.InvalidNameException",
                                        "javax.naming.NamingException",
                                        "javax.naming.directory.Attribute",
                                        "javax.naming.directory.Attributes",
                                        "javax.naming.ldap.LdapName",
                                        "javax.naming.ldap.Rdn",
                                        "javax.net.ssl.SSLException",
                                        "javax.net.ssl.SSLSession",
                                        "javax.net.ssl.SSLSocket",
                                        "java.io.IOException",
                                        "java.io.InputStream",
                                        "java.net.InetAddress",
                                        "java.net.UnknownHostException",
                                        "java.security.cert.Certificate",
                                        "java.security.cert.CertificateParsingException",
                                        "java.security.cert.X509Certificate",
                                        "java.util.ArrayList",
                                        "java.util.Arrays",
                                        "java.util.Collection",
                                        "java.util.Iterator",
                                        "java.util.LinkedList",
                                        "java.util.List",
                                        "java.util.Locale",
                                        "java.util.NoSuchElementException",
                                        "java.util.regex.Pattern"]):
            private final static String[] BAD_COUNTRY_2LDS =
                    {"ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
                            "lg", "ne", "net", "or", "org"};

            private static final Pattern IPV4_PATTERN =
                    Pattern.compile("^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");

            private static final Pattern IPV6_STD_PATTERN =
                    Pattern.compile("^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");

            private static final Pattern IPV6_HEX_COMPRESSED_PATTERN =
                    Pattern.compile("^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$");

            public void patch(JavaFrame frame) {
                String host = frame.loadStringVariable(1);
                SSLSocket sslSocket = (SSLSocket) frame.loadObjectOperand(0);

                try {
                    verifyHostName(host, (SSLSocket) sslSocket);
                    frame.returnObject(sslSocket);
                } catch (IOException ex) {
                    frame.raiseException(ex);
                } catch (RuntimeException ex) {
                    frame.raiseException(ex);
                }
            }

            private static void verifyHostName(String host, SSLSocket ssl)
                    throws IOException {
                if (host == null) {
                    throw new IllegalArgumentException("host to verify was null");
                }

                SSLSession session = ssl.getSession();
                if (session == null) {
                    InputStream in = ssl.getInputStream();
                    in.available();
                    session = ssl.getSession();
                    if (session == null) {
                        ssl.startHandshake();
                        session = ssl.getSession();
                    }
                }

                Certificate[] certs = session.getPeerCertificates();
                verifyHostName(host.trim().toLowerCase(Locale.US), (X509Certificate) certs[0]);
            }

            private static void verifyHostName(final String host, X509Certificate cert)
                    throws SSLException {
                String[] cns = getCNs(cert);
                String[] subjectAlts = getSubjectAlts(cert, host);
                verifyHostName(host, cns, subjectAlts);
            }

            private static void verifyHostName(final String host, String[] cns, String[] subjectAlts)
                    throws SSLException {

                final LinkedList<String> names = new LinkedList<String>();
                if (cns != null && cns.length > 0 && cns[0] != null) {
                    names.add(cns[0]);
                }
                if (subjectAlts != null) {
                    for (final String subjectAlt : subjectAlts) {
                        if (subjectAlt != null) {
                            names.add(subjectAlt);
                        }
                    }
                }

                if (names.isEmpty()) {
                    final String msg = "Certificate for <" + host + "> doesn't contain CN or DNS subjectAlt";
                    throw new SSLException(msg);
                }

                final StringBuffer buf = new StringBuffer();
                final String hostName = normaliseIPv6Address(host.trim().toLowerCase(Locale.ENGLISH));
                boolean match = false;

                for (final Iterator<String> it = names.iterator(); it.hasNext(); ) {
                    String cn = it.next();
                    cn = cn.toLowerCase(Locale.ENGLISH);
                    buf.append(" <");
                    buf.append(cn);
                    buf.append('>');
                    if (it.hasNext()) {
                        buf.append(" OR");
                    }

                    final String[] parts = cn.split("\\.");
                    final boolean doWildcard =
                            parts.length >= 3 && parts[0].endsWith("*") &&
                                    validCountryWildcard(cn) && !isIPAddress(host);

                    if (doWildcard) {
                        final String firstpart = parts[0];
                        if (firstpart.length() > 1) {
                            final String prefix = firstpart.substring(0, firstpart.length() - 1);
                            final String suffix = cn.substring(firstpart.length());
                            final String hostSuffix = hostName.substring(prefix.length());
                            match = hostName.startsWith(prefix) && hostSuffix.endsWith(suffix);
                        } else {
                            match = hostName.endsWith(cn.substring(1));
                        }
                        if (match) {
                            match = countDots(hostName) == countDots(cn);
                        }
                    } else {
                        match = hostName.equals(normaliseIPv6Address(cn));
                    }
                    if (match) {
                        break;
                    }
                }
                if (!match) {
                    throw new SSLException("hostname in certificate didn't match: <" + host + "> !=" + buf);
                }
            }

            private static boolean isIPAddress(final String hostname) {
                return hostname != null
                        && (
                        IPV4_PATTERN.matcher(hostname).matches()
                                || IPV6_STD_PATTERN.matcher(hostname).matches()
                                || IPV6_HEX_COMPRESSED_PATTERN.matcher(hostname).matches()
                );

            }

            private static int countDots(final String data) {
                int dots = 0;
                for (int i = 0; i < data.length(); i++) {
                    if (data.charAt(i) == '.') {
                        dots += 1;
                    }
                }
                return dots;
            }

            private static boolean validCountryWildcard(final String cn) {
                final String[] parts = cn.split("\\.");
                if (parts.length != 3 || parts[2].length() != 2) {
                    return true;
                }
                return Arrays.binarySearch(BAD_COUNTRY_2LDS, parts[1]) < 0;
            }

            private static String[] getCNs(final X509Certificate cert) {
                final String subjectPrincipal = cert.getSubjectX500Principal().toString();
                try {
                    return extractCNs(subjectPrincipal);
                } catch (SSLException ex) {
                    return null;
                }
            }

            private 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 (NoSuchElementException ignore) {
                            } 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[0]);
            }

            private static String[] getSubjectAlts(
                    final X509Certificate cert, final String hostname) {
                final int subjectType;
                if (isIPAddress(hostname)) {
                    subjectType = 7;
                } else {
                    subjectType = 2;
                }

                final LinkedList<String> subjectAltList = new LinkedList<String>();
                Collection<List<?>> c = null;
                try {
                    c = cert.getSubjectAlternativeNames();
                } catch (final CertificateParsingException cpe) {
                }
                if (c != null) {
                    for (final List<?> aC : c) {
                        final List<?> list = aC;
                        final int type = (Integer) list.get(0);
                        if (type == subjectType) {
                            final String s = (String) list.get(1);
                            subjectAltList.add(s);
                        }
                    }
                }
                if (!subjectAltList.isEmpty()) {
                    final String[] subjectAlts = new String[subjectAltList.size()];
                    subjectAltList.toArray(subjectAlts);
                    return subjectAlts;
                } else {
                    return null;
                }
            }

            private static String normaliseIPv6Address(final String hostname) {
                if (hostname == null || !isIPv6Address(hostname)) {
                    return hostname;
                }
                try {
                    final InetAddress inetAddress = InetAddress.getByName(hostname);
                    return inetAddress.getHostAddress();
                } catch (final UnknownHostException uhe) {
                    return hostname;
                }
            }

            private static boolean isIPv6Address(final String input) {
                return IPV6_STD_PATTERN.matcher(input).matches() || isIPv6HexCompressedAddress(input);
            }

            private static boolean isIPv6HexCompressedAddress(final String input) {
                int colonCount = 0;
                for (int i = 0; i < input.length(); i++) {
                    if (input.charAt(i) == ':') {
                        colonCount++;
                    }
                }
                return  colonCount <= 7 && IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches();
            }
        endcode
    endpatch

    patch("CVE-2012-5783 :04"):
        function("org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.createSocket(Ljava/net/Socket;Ljava/lang/String;IZ)Ljava/net/Socket;",
            checksums: ["464eb9fd68"])  // commons-httpclient:3.1
        exit()

        code(language: java,   import: ["javax.naming.InvalidNameException",
                                        "javax.naming.NamingException",
                                        "javax.naming.directory.Attribute",
                                        "javax.naming.directory.Attributes",
                                        "javax.naming.ldap.LdapName",
                                        "javax.naming.ldap.Rdn",
                                        "javax.net.ssl.SSLException",
                                        "javax.net.ssl.SSLSession",
                                        "javax.net.ssl.SSLSocket",
                                        "java.io.IOException",
                                        "java.io.InputStream",
                                        "java.net.InetAddress",
                                        "java.net.UnknownHostException",
                                        "java.security.cert.Certificate",
                                        "java.security.cert.CertificateParsingException",
                                        "java.security.cert.X509Certificate",
                                        "java.util.ArrayList",
                                        "java.util.Arrays",
                                        "java.util.Collection",
                                        "java.util.Iterator",
                                        "java.util.LinkedList",
                                        "java.util.List",
                                        "java.util.Locale",
                                        "java.util.NoSuchElementException",
                                        "java.util.regex.Pattern"]):
            private final static String[] BAD_COUNTRY_2LDS =
                    {"ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
                            "lg", "ne", "net", "or", "org"};

            private static final Pattern IPV4_PATTERN =
                    Pattern.compile("^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");

            private static final Pattern IPV6_STD_PATTERN =
                    Pattern.compile("^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");

            private static final Pattern IPV6_HEX_COMPRESSED_PATTERN =
                    Pattern.compile("^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$");

            public void patch(JavaFrame frame) {
                String host = frame.loadStringVariable(1);
                SSLSocket sslSocket = (SSLSocket) frame.loadObjectOperand(0);

                try {
                    verifyHostName(host, (SSLSocket) sslSocket);
                    frame.returnObject(sslSocket);
                } catch (IOException ex) {
                    frame.raiseException(ex);
                } catch (RuntimeException ex) {
                    frame.raiseException(ex);
                }
            }

            private static void verifyHostName(String host, SSLSocket ssl)
                    throws IOException {
                if (host == null) {
                    throw new IllegalArgumentException("host to verify was null");
                }

                SSLSession session = ssl.getSession();
                if (session == null) {
                    InputStream in = ssl.getInputStream();
                    in.available();
                    session = ssl.getSession();
                    if (session == null) {
                        ssl.startHandshake();
                        session = ssl.getSession();
                    }
                }

                Certificate[] certs = session.getPeerCertificates();
                verifyHostName(host.trim().toLowerCase(Locale.US), (X509Certificate) certs[0]);
            }

            private static void verifyHostName(final String host, X509Certificate cert)
                    throws SSLException {
                String[] cns = getCNs(cert);
                String[] subjectAlts = getSubjectAlts(cert, host);
                verifyHostName(host, cns, subjectAlts);
            }

            private static void verifyHostName(final String host, String[] cns, String[] subjectAlts)
                    throws SSLException {

                final LinkedList<String> names = new LinkedList<String>();
                if (cns != null && cns.length > 0 && cns[0] != null) {
                    names.add(cns[0]);
                }
                if (subjectAlts != null) {
                    for (final String subjectAlt : subjectAlts) {
                        if (subjectAlt != null) {
                            names.add(subjectAlt);
                        }
                    }
                }

                if (names.isEmpty()) {
                    final String msg = "Certificate for <" + host + "> doesn't contain CN or DNS subjectAlt";
                    throw new SSLException(msg);
                }

                final StringBuffer buf = new StringBuffer();
                final String hostName = normaliseIPv6Address(host.trim().toLowerCase(Locale.ENGLISH));
                boolean match = false;

                for (final Iterator<String> it = names.iterator(); it.hasNext(); ) {
                    String cn = it.next();
                    cn = cn.toLowerCase(Locale.ENGLISH);
                    buf.append(" <");
                    buf.append(cn);
                    buf.append('>');
                    if (it.hasNext()) {
                        buf.append(" OR");
                    }

                    final String[] parts = cn.split("\\.");
                    final boolean doWildcard =
                            parts.length >= 3 && parts[0].endsWith("*") &&
                                    validCountryWildcard(cn) && !isIPAddress(host);

                    if (doWildcard) {
                        final String firstpart = parts[0];
                        if (firstpart.length() > 1) {
                            final String prefix = firstpart.substring(0, firstpart.length() - 1);
                            final String suffix = cn.substring(firstpart.length());
                            final String hostSuffix = hostName.substring(prefix.length());
                            match = hostName.startsWith(prefix) && hostSuffix.endsWith(suffix);
                        } else {
                            match = hostName.endsWith(cn.substring(1));
                        }
                        if (match) {
                            match = countDots(hostName) == countDots(cn);
                        }
                    } else {
                        match = hostName.equals(normaliseIPv6Address(cn));
                    }
                    if (match) {
                        break;
                    }
                }
                if (!match) {
                    throw new SSLException("hostname in certificate didn't match: <" + host + "> !=" + buf);
                }
            }

            private static boolean isIPAddress(final String hostname) {
                return hostname != null
                        && (
                        IPV4_PATTERN.matcher(hostname).matches()
                                || IPV6_STD_PATTERN.matcher(hostname).matches()
                                || IPV6_HEX_COMPRESSED_PATTERN.matcher(hostname).matches()
                );

            }

            private static int countDots(final String data) {
                int dots = 0;
                for (int i = 0; i < data.length(); i++) {
                    if (data.charAt(i) == '.') {
                        dots += 1;
                    }
                }
                return dots;
            }

            private static boolean validCountryWildcard(final String cn) {
                final String[] parts = cn.split("\\.");
                if (parts.length != 3 || parts[2].length() != 2) {
                    return true;
                }
                return Arrays.binarySearch(BAD_COUNTRY_2LDS, parts[1]) < 0;
            }

            private static String[] getCNs(final X509Certificate cert) {
                final String subjectPrincipal = cert.getSubjectX500Principal().toString();
                try {
                    return extractCNs(subjectPrincipal);
                } catch (SSLException ex) {
                    return null;
                }
            }

            private 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 (NoSuchElementException ignore) {
                            } 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[0]);
            }

            private static String[] getSubjectAlts(
                    final X509Certificate cert, final String hostname) {
                final int subjectType;
                if (isIPAddress(hostname)) {
                    subjectType = 7;
                } else {
                    subjectType = 2;
                }

                final LinkedList<String> subjectAltList = new LinkedList<String>();
                Collection<List<?>> c = null;
                try {
                    c = cert.getSubjectAlternativeNames();
                } catch (final CertificateParsingException cpe) {
                }
                if (c != null) {
                    for (final List<?> aC : c) {
                        final List<?> list = aC;
                        final int type = (Integer) list.get(0);
                        if (type == subjectType) {
                            final String s = (String) list.get(1);
                            subjectAltList.add(s);
                        }
                    }
                }
                if (!subjectAltList.isEmpty()) {
                    final String[] subjectAlts = new String[subjectAltList.size()];
                    subjectAltList.toArray(subjectAlts);
                    return subjectAlts;
                } else {
                    return null;
                }
            }

            private static String normaliseIPv6Address(final String hostname) {
                if (hostname == null || !isIPv6Address(hostname)) {
                    return hostname;
                }
                try {
                    final InetAddress inetAddress = InetAddress.getByName(hostname);
                    return inetAddress.getHostAddress();
                } catch (final UnknownHostException uhe) {
                    return hostname;
                }
            }

            private static boolean isIPv6Address(final String input) {
                return IPV6_STD_PATTERN.matcher(input).matches() || isIPv6HexCompressedAddress(input);
            }

            private static boolean isIPv6HexCompressedAddress(final String input) {
                int colonCount = 0;
                for (int i = 0; i < input.length(); i++) {
                    if (input.charAt(i) == ':') {
                        colonCount++;
                    }
                }
                return  colonCount <= 7 && IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches();
            }
        endcode
    endpatch

endapp

CVSS

4.3 v2.0 AV:N/AC:M/Au:N/C:N/I:P/A:N 1 metric

VRT selects the newest version's highest entry and publishes it as cvssScore, newest rather than largest because scores are not comparable across versions, and highest rather than first because the first entry is frequently a CNA placeholder scoring 0.0 over NVD's own analysis.

VersionScoreBandVectorAssignerType
CVSS 2.0 4.3 no band published AV:N/AC:M/Au:N/C:N/I:P/A:N NVD Primary published

Affected Software & Releases

☕ Maven Library Packages

Artifact coordinates and fix boundaries from OSV.dev
Package CoordinateIntroducedFixedLast affected
org.apache.httpcomponents:httpclient 0 4.2.3 unbounded

🖥️ Product CPEs & Version Ranges

2 product(s) over 2 version claims (uncapped)
SourceVendorProductSchemeAffected Versions
nvd apache commons-httpclient generic ≥ 4.0 and ≤ 4.2.2
osv org.apache.httpcomponents httpclient generic < 4.2.3

References

URLTags
https://github.com/apache/httpcomponents-client/commit/6e14fc146a66e0f3eb362f45f95d1a58ee18886a WEB
https://github.com/apache/httpcomponents-client/commit/b930227f907af1198765fc47beabbddae344ca7b WEB
https://access.redhat.com/solutions/1165533 WEB
https://bugzilla.redhat.com/show_bug.cgi?id=1129916 WEB
https://github.com/advisories/GHSA-2x83-r56g-cv47 ADVISORY
https://h20566.www2.hpe.com/portal/site/hpsc/public/kb/docDisplay?docId=emr_na-c05103564 WEB
http://rhn.redhat.com/errata/RHSA-2014-1098.html WEB
http://rhn.redhat.com/errata/RHSA-2014-1833.html WEB
http://rhn.redhat.com/errata/RHSA-2014-1834.html WEB
http://rhn.redhat.com/errata/RHSA-2014-1835.html WEB

Timeline

Published 2014-09-04 Last modified 2026-06-16
Published2014-09-04By the CVE Program.
ARMR remediation created2020-06-25Earliest commit adding this CVE's ARMR patch or security rule.
ARMR remediation last updated2026-03-04Most recent commit touching this CVE's ARMR patch or security rule.
Last VRT activity2026-03-04Most recent commit touching this CVE's classification, patch or rule file.
NVD record modified2026-06-16NVD's own last-modified date for this record.