On 02.10.2014 23:18, Adam D. Barratt wrote:
> On Thu, 2014-10-02 at 22:42 +0200, Markus Koschany wrote:
> 
>> I have prepared a new point release of axis which addresses the
>> security vulnerability CVE-2014-3596 "Insecure certificate
>> validation". [1]
> [...]
>> [1] https://bugs.debian.org/762444
> 
> At the risk of being a bit of a pain... would it be possible to have a
> diff between the current and new patches, please?
> 

Well, I'm in a good mood today. Sure. :)

Regards,

Markus

diff -Nru axis-1.4/debian/changelog axis-1.4/debian/changelog
--- axis-1.4/debian/changelog   2012-12-06 14:41:46.000000000 +0100
+++ axis-1.4/debian/changelog   2014-10-02 23:26:11.000000000 +0200
@@ -1,3 +1,19 @@
+axis (1.4-16.2+deb7u1) stable; urgency=high
+
+  * Team upload.
+  * Fix CVE-2014-3596.
+    - Replace 06-fix-CVE-2012-5784.patch with CVE-2014-3596.patch which fixes
+      both CVE issues. Thanks to Raphael Hertzog for the report.
+    - The getCN function in Apache Axis 1.4 and earlier 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-5784.
+
+ -- Markus Koschany <[email protected]>  Thu, 02 Oct 2014 22:13:16 +0200
+
 axis (1.4-16.2) unstable; urgency=low
 
   * Non-maintainer upload.
diff -Nru axis-1.4/debian/patches/06-fix-CVE-2012-5784.patch 
axis-1.4/debian/patches/06-fix-CVE-2012-5784.patch
--- axis-1.4/debian/patches/06-fix-CVE-2012-5784.patch  2012-12-06 
13:45:17.000000000 +0100
+++ axis-1.4/debian/patches/06-fix-CVE-2012-5784.patch  2014-10-02 
23:26:11.000000000 +0200
@@ -1,19 +1,25 @@
-Description: Fixed CN extraction from DN of X500 principal and wildcard 
validation
+From: David Jorm and Arun Neelicattu (Red Hat Product Security)
+Date: Thu, 25 Sep 2014 19:38:17 +0000
+Subject: CVE-2014-3596
 
- axis (1.4-16.2) unstable; urgency=low
+The getCN function in Apache Axis 1.4 and earlier 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-5784.
 
-   * Fixed CN extraction from DN of X500 principal and wildcard validation
+Forwarded: no
+Bug: https://bugs.debian.org/762444
+---
+ .../axis/components/net/JSSESocketFactory.java     | 309 ++++++++++++++++++++-
+ 1 file changed, 303 insertions(+), 6 deletions(-)
 
-Author: Alberto Fernández Martínez <[email protected]>
-
-
-Origin: other
-Bug-Debian: http://bugs.debian.org/692650
-Forwarded: https://issues.apache.org/jira/browse/AXIS-2883
-Last-Update: <2012-12-06>
-
---- axis-1.4.orig/src/org/apache/axis/components/net/JSSESocketFactory.java
-+++ axis-1.4/src/org/apache/axis/components/net/JSSESocketFactory.java
+diff --git a/src/org/apache/axis/components/net/JSSESocketFactory.java 
b/src/org/apache/axis/components/net/JSSESocketFactory.java
+index dd3f991..abffcdd 100644
+--- a/src/org/apache/axis/components/net/JSSESocketFactory.java
++++ b/src/org/apache/axis/components/net/JSSESocketFactory.java
 @@ -15,12 +15,6 @@
   */
  package org.apache.axis.components.net;
@@ -27,13 +33,14 @@
  import java.io.BufferedWriter;
  import java.io.IOException;
  import java.io.InputStream;
-@@ -28,7 +22,27 @@ import java.io.OutputStream;
+@@ -28,7 +22,33 @@ import java.io.OutputStream;
  import java.io.OutputStreamWriter;
  import java.io.PrintWriter;
  import java.net.Socket;
 +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.Hashtable;
@@ -41,9 +48,14 @@
 +import java.util.LinkedList;
 +import java.util.List;
 +import java.util.Locale;
-+import java.util.StringTokenizer;
 +import java.util.regex.Pattern;
 +
++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;
@@ -55,7 +67,7 @@
  
  
  /**
-@@ -41,6 +55,10 @@ import java.util.Hashtable;
+@@ -41,6 +61,10 @@ import java.util.Hashtable;
   */
  public class JSSESocketFactory extends DefaultSocketFactory implements 
SecureSocketFactory {
  
@@ -66,7 +78,7 @@
      /** Field sslFactory           */
      protected SSLSocketFactory sslFactory = null;
  
-@@ -187,6 +205,260 @@ public class JSSESocketFactory extends D
+@@ -187,6 +211,279 @@ public class JSSESocketFactory extends 
DefaultSocketFactory implements SecureSoc
          if (log.isDebugEnabled()) {
              log.debug(Messages.getMessage("createdSSL00"));
          }
@@ -74,8 +86,8 @@
          return sslSocket;
      }
 +    /**
-+     * Verifies that the given hostname in certicifate is the hostname we are 
trying to connect to
-+     * http://www.cvedetails.com/cve/CVE-2012-5783/
++     * Verifies that the given hostname in certicifate is the hostname we are 
trying to connect to.
++     * This resolves CVE-2012-5784 and CVE-2014-3596
 +     * @param host
 +     * @param ssl
 +     * @throws IOException
@@ -139,9 +151,9 @@
 +        // to establish the socket to the hostname in the certificate.
 +        // Don't trim the CN, though.
 +        
-+              String cn = getCN(cert);
++              String[] cns = getCNs(cert);
 +              String[] subjectAlts = getDNSSubjectAlts(cert);
-+              verifyHostName(host, cn.toLowerCase(Locale.US), subjectAlts);
++              verifyHostName(host, cns, subjectAlts);
 +
 +      }
 +
@@ -188,7 +200,7 @@
 +       * @throws SSLException
 +       */
 +
-+      private static void verifyHostName(final String host, String cn, 
String[] subjectAlts)throws SSLException{
++      private static void verifyHostName(final String host, String[] cns, 
String[] subjectAlts)throws SSLException{
 +              StringBuffer cnTested = new StringBuffer();
 +
 +              for (int i = 0; i < subjectAlts.length; i++){
@@ -201,13 +213,18 @@
 +                              cnTested.append("/").append(name);
 +                      }                               
 +              }
-+              if (cn != null && verifyHostName(host, cn)){
-+                      return;
-+              }
-+              cnTested.append("/").append(cn);
++        for (int i = 0; i < cns.length; i++) {
++            String cn = cns[i];
++            if (cn != null) {
++                cn = cn.toLowerCase(Locale.US);
++                if (verifyHostName(host, cn)) {
++                    return;
++                }
++                cnTested.append("/").append(cn);
++            }
++        }
 +              throw new SSLException("hostname in certificate didn't match: <"
 +                                      + host + "> != <" + cnTested + ">");
-+              
 +      }               
 +      
 +      private static boolean verifyHostName(final String host, final String 
cn){
@@ -270,7 +287,7 @@
 +              boolean match = false;
 +              String firstpart = parts[0];
 +              if (firstpart.length() > 1) {
-+                      // server∗
++                      // server∗
 +                      // e.g. server
 +                      String prefix =  firstpart.substring(0, 
firstpart.length() - 1);
 +                      // skipwildcard part from cn
@@ -282,8 +299,8 @@
 +                      match = hostName.endsWith(cn.substring(1));
 +              }
 +              if (match) {
-+                      // I f we ’ r e i n s t r i c t mode ,
-+                      // [ ∗.foo.com] is not allowed to match [a.b.foo.com]
++                      // I f we ’ r e i n s t r i c t mode ,
++                      // [ ∗.foo.com] is not allowed to match [a.b.foo.com]
 +                      match = countDots(hostName) == countDots(cn);
 +              }
 +              return match;
@@ -300,7 +317,7 @@
 +      }
 +
 +
-+      private static String getCN(X509Certificate cert) {
++      private static String[] getCNs(X509Certificate cert) {
 +          // Note:  toString() seems to do a better job than getName()
 +          //
 +          // For example, getName() gives me this:
@@ -310,20 +327,34 @@
 +          // [email protected]        
 +              String subjectPrincipal = 
cert.getSubjectX500Principal().toString();
 +              
-+              return getCN(subjectPrincipal);
++              return getCNs(subjectPrincipal);
 +
 +      }
-+      private static String getCN(String subjectPrincipal) {
-+              StringTokenizer st = new StringTokenizer(subjectPrincipal, ",");
-+              while(st.hasMoreTokens()) {
-+                      String tok = st.nextToken().trim();
-+                      if (tok.length() > 3) {
-+                              if (tok.substring(0, 
3).equalsIgnoreCase("CN=")) {
-+                                      return tok.substring(3);
-+                              }
-+                      }
-+              }
-+              return null;
++      private static String[] getCNs(String subjectPrincipal) {
++        if (subjectPrincipal == null) {
++            return null;
++        }
++        final List cns = new ArrayList();
++        try {
++            final LdapName subjectDN = new LdapName(subjectPrincipal);
++            final List rdns = subjectDN.getRdns();
++            for (int i = rdns.size() - 1; i >= 0; i--) {
++                final Rdn rds = (Rdn) 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 ignore) { }
++        return cns.isEmpty() ? null : (String[]) cns.toArray(new String[ 
cns.size() ]);
 +      }
 +
  }

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to