craigmcc    00/12/11 17:01:06

  Modified:    .        Tag: TOMCAT_31_BRANCH build.xml
               src/admin/WEB-INF Tag: TOMCAT_31_BRANCH web.xml
               src/etc  Tag: TOMCAT_31_BRANCH web.xml
               src/examples/WEB-INF Tag: TOMCAT_31_BRANCH web.xml
               src/examples/WEB-INF/classes/examples Tag: TOMCAT_31_BRANCH
                        ShowSource.java
               src/share/org/apache/jasper/runtime Tag: TOMCAT_31_BRANCH
                        JspServlet.java
               src/share/org/apache/tomcat/service/connector Tag:
                        TOMCAT_31_BRANCH Ajp12ConnectionHandler.java
               src/share/org/apache/tomcat/servlets Tag: TOMCAT_31_BRANCH
                        DefaultServlet.java
               src/share/org/apache/tomcat/util Tag: TOMCAT_31_BRANCH
                        SessionIdGenerator.java SessionUtil.java
  Log:
  Fixes for security vulnerabilities in Tomcat 3.1 (final), and proposed
  release notes for a Tomcat 3.1.1 maintenance release that *only* fixes the
  security related problems.
  
  The identified (and fixed) vulnerabilities are:
  - Administrative application enabled by default (removed)
  - Case insensitive matches on static files under Windows
  - Snoop servlet mappings in example application
  - JSP "Show Source" could show WEB-INF files
  - Requesting unknown JSP pages showed disk file pathname
  - Session ID generation algorithm subject to attack (replaced
    with the algorithm from 3.2).
  - Tomcat 3.1 could be shut down remotely.
  
  See separate commits for security issues related to 3.2, and discussion of
  recommended course of action.
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.44.4.1  +6 -0      jakarta-tomcat/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/build.xml,v
  retrieving revision 1.44
  retrieving revision 1.44.4.1
  diff -u -r1.44 -r1.44.4.1
  --- build.xml 2000/04/05 03:16:15     1.44
  +++ build.xml 2000/12/12 01:00:59     1.44.4.1
  @@ -91,11 +91,13 @@
              classpath="${tomcat.build}/classes"/>
   
       <!-- admin context -->
  +<!-- Commented out by default because of limited ability to protect usage
       <mkdir dir="${tomcat.build}/webapps/admin"/>
       <copydir src="src/admin" dest="${tomcat.build}/webapps/admin"/>
       <javac srcdir="src/admin/WEB-INF/classes"
              destdir="${tomcat.build}/webapps/admin/WEB-INF/classes"
              classpath="${tomcat.build}/classes"/>
  +-->
   
       <!-- Test application -->
       <mkdir dir="${tomcat.build}/webapps/test"/>
  @@ -126,6 +128,7 @@
            includes="org/apache/jasper/**"/>
   
       <!-- Add Tomcat internal javadoc -->
  +<!-- Commented out to avoid incompatibilities with current Ant and Java2
       <mkdir dir="${tomcat.home}/webapps/ROOT/javadoc" />
       <javadoc packagenames="org.apache.tomcat.core"
                sourcepath="src/share"
  @@ -137,6 +140,7 @@
                doctitle="Tomcat internal"
                bottom="Copyright &#169; 2000 Apache Software Foundation. All Rights 
Reserved."
       />
  +-->
   
       <deltree dir="${tomcat.home}/classes"/>
   
  @@ -147,10 +151,12 @@
              includes="**" /> 
       <deltree dir="${tomcat.home}/webapps/examples"/>
   
  +<!--
       <jar   jarfile="${tomcat.home}/webapps/admin.war"
              basedir="${tomcat.home}/webapps/admin"
              includes="**" /> 
       <deltree dir="${tomcat.home}/webapps/admin"/>
  +-->
   
       <jar   jarfile="${tomcat.home}/webapps/ROOT.war"
              basedir="${tomcat.home}/webapps/ROOT"
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.1.6.1   +15 -0     jakarta-tomcat/src/admin/WEB-INF/web.xml
  
  Index: web.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/admin/WEB-INF/web.xml,v
  retrieving revision 1.1
  retrieving revision 1.1.6.1
  diff -u -r1.1 -r1.1.6.1
  --- web.xml   2000/02/18 18:33:03     1.1
  +++ web.xml   2000/12/12 01:01:00     1.1.6.1
  @@ -5,4 +5,19 @@
       "http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
   
   <web-app>
  +
  +    <security-constraint>
  +      <web-resource-collection>
  +        <url-pattern>/*</url-pattern>
  +      </web-resource-collection>
  +      <auth-constraint>
  +        <role-name>admin</role-name>
  +      </auth-constraint>
  +    </security-constraint>
  +
  +    <login-config>
  +      <auth-method>BASIC</auth-method>
  +      <realm-name>Tomcat Administrative Application</realm-name>
  +    </login-config>
  +
   </web-app>
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.1.6.1   +12 -0     jakarta-tomcat/src/etc/web.xml
  
  Index: web.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/etc/web.xml,v
  retrieving revision 1.1
  retrieving revision 1.1.6.1
  diff -u -r1.1 -r1.1.6.1
  --- web.xml   2000/02/09 23:26:28     1.1
  +++ web.xml   2000/12/12 01:01:01     1.1.6.1
  @@ -12,6 +12,18 @@
           <servlet-class>
               org.apache.tomcat.servlets.DefaultServlet
           </servlet-class>
  +        <init-param>
  +            <param-name>
  +                caseSensitive
  +            </param-name>
  +            <param-value>
  +                true
  +            </param-value>
  +            <description>
  +                Set to true for case-sensitive filename comparisons,
  +                even on non-case-sensitive platforms such as Windows.
  +            </description>
  +        </init-param>
        <load-on-startup>
               -2147483646
        </load-on-startup>
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.9.4.1   +2 -0      jakarta-tomcat/src/examples/WEB-INF/web.xml
  
  Index: web.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/examples/WEB-INF/web.xml,v
  retrieving revision 1.9
  retrieving revision 1.9.4.1
  diff -u -r1.9 -r1.9.4.1
  --- web.xml   2000/04/07 22:59:00     1.9
  +++ web.xml   2000/12/12 01:01:02     1.9.4.1
  @@ -27,6 +27,7 @@
             servletToJsp
         </servlet-class>
       </servlet>
  +<!--
       <servlet-mapping>
           <servlet-name>
               snoop
  @@ -43,6 +44,7 @@
               *.snp
           </url-pattern>
       </servlet-mapping>
  +-->
       <servlet-mapping>
           <servlet-name>
               servletToJsp
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.4.6.1   +3 -1      
jakarta-tomcat/src/examples/WEB-INF/classes/examples/ShowSource.java
  
  Index: ShowSource.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/examples/WEB-INF/classes/examples/ShowSource.java,v
  retrieving revision 1.4
  retrieving revision 1.4.6.1
  diff -u -r1.4 -r1.4.6.1
  --- ShowSource.java   2000/03/07 19:53:39     1.4
  +++ ShowSource.java   2000/12/12 01:01:03     1.4.6.1
  @@ -20,7 +20,9 @@
       }
   
       public int doEndTag() throws JspException {
  -     if (jspFile.indexOf( ".." ) >= 0)
  +     if ((jspFile.indexOf( ".." ) >= 0) ||
  +            (jspFile.toUpperCase().indexOf("/WEB-INF/") != 0) ||
  +            (jspFile.toUpperCase().indexOf("/META-INF/") != 0))
            throw new JspTagException("Invalid JSP file " + jspFile);
   
           InputStream in
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.21.4.1  +1 -1      
jakarta-tomcat/src/share/org/apache/jasper/runtime/Attic/JspServlet.java
  
  Index: JspServlet.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/jasper/runtime/Attic/JspServlet.java,v
  retrieving revision 1.21
  retrieving revision 1.21.4.1
  diff -u -r1.21 -r1.21.4.1
  --- JspServlet.java   2000/04/05 03:36:42     1.21
  +++ JspServlet.java   2000/12/12 01:01:03     1.21.4.1
  @@ -178,7 +178,7 @@
                   response.sendError(HttpServletResponse.SC_NOT_FOUND, 
                                      Constants.getString("jsp.error.file.not.found", 
                                                          new Object[] {
  -                                                           ex.getMessage()
  +                                                           jspUri
                                                          }));
                   
                   return;
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.21.4.1  +39 -1     
jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Attic/Ajp12ConnectionHandler.java
  
  Index: Ajp12ConnectionHandler.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Attic/Ajp12ConnectionHandler.java,v
  retrieving revision 1.21
  retrieving revision 1.21.4.1
  diff -u -r1.21 -r1.21.4.1
  --- Ajp12ConnectionHandler.java       2000/04/06 23:11:36     1.21
  +++ Ajp12ConnectionHandler.java       2000/12/12 01:01:04     1.21.4.1
  @@ -354,8 +354,11 @@
                    } else {
                        try {
                            // close the socket connection before handling any signal
  +                            InetAddress serverAddr = socket.getLocalAddress();
  +                            InetAddress clientAddr = socket.getInetAddress();
                            sin.close();
  -                         if ( signal== 15 ) {
  +                         if ( (signal== 15) &&
  +                                  isSameAddress(serverAddr, clientAddr) ) {
                                // Shutdown - probably apache was stoped with 
apachectl stop
                                contextM.stop();
                                // same behavior as in past, because it seems that
  @@ -424,6 +427,41 @@
        // XXX
        // Support persistent connection in AJP21
        //moreRequests = false;
  +    }
  +
  +    /**
  +     * Return <code>true</code> if the specified client and server addresses
  +     * are the same.  This method works around a bug in the IBM 1.1.8 JVM on
  +     * Linux, where the address bytes are returned reversed in some
  +     * circumstances.
  +     *
  +     * @param server The server's InetAddress
  +     * @param client The client's InetAddress
  +     */
  +    private boolean isSameAddress(InetAddress server, InetAddress client) {
  +
  +     // Compare the byte array versions of the two addresses
  +     byte serverAddr[] = server.getAddress();
  +     byte clientAddr[] = client.getAddress();
  +     if (serverAddr.length != clientAddr.length)
  +         return (false);
  +     boolean match = true;
  +     for (int i = 0; i < serverAddr.length; i++) {
  +         if (serverAddr[i] != clientAddr[i]) {
  +             match = false;
  +             break;
  +         }
  +     }
  +     if (match)
  +         return (true);
  +
  +     // Compare the reversed form of the two addresses
  +     for (int i = 0; i < serverAddr.length; i++) {
  +         if (serverAddr[i] != clientAddr[(serverAddr.length-1)-i])
  +             return (false);
  +     }
  +     return (true);
  +
       }
   
   }
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.13.2.1.2.1 +21 -3     
jakarta-tomcat/src/share/org/apache/tomcat/servlets/Attic/DefaultServlet.java
  
  Index: DefaultServlet.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/servlets/Attic/DefaultServlet.java,v
  retrieving revision 1.13.2.1
  retrieving revision 1.13.2.1.2.1
  diff -u -r1.13.2.1 -r1.13.2.1.2.1
  --- DefaultServlet.java       2000/04/13 12:46:37     1.13.2.1
  +++ DefaultServlet.java       2000/12/12 01:01:05     1.13.2.1.2.1
  @@ -82,6 +82,7 @@
       private Context context;
       String docBase;
       int debug=0;
  +    boolean caseSensitive = true;
   
       public void init() throws ServletException {
        contextF = getServletContext();
  @@ -100,6 +101,18 @@
        // debug
        String dbg=getServletConfig().getInitParameter("debug");
        if( dbg!=null) debug=1;
  +
  +        // case sensitivity on Windows
  +        String value = getServletConfig().getInitParameter("caseSensitive");
  +        if (value != null) {
  +            if ("true".equalsIgnoreCase(value) ||
  +                "yes".equalsIgnoreCase(value) ||
  +                "on".equalsIgnoreCase(value))
  +                caseSensitive = true;
  +            else
  +                caseSensitive = false;
  +        }
  +
       }
   
       public String getServletInfo() {
  @@ -273,11 +286,16 @@
        // So, a check for File.separatorChar='\\' ..... It hopefully
        // happens on flavors of Windows.
        if (File.separatorChar  == '\\') {
  -             // On Windows check ignore case....
  -             if(!absPath.equalsIgnoreCase(canPath)) {
  +            // On Windows check case if requested ....
  +            boolean result;
  +            if (caseSensitive)
  +                result = !absPath.equals(canPath);
  +            else
  +                result = !absPath.equalsIgnoreCase(canPath);
  +            if (result) {
                response.sendError(response.SC_NOT_FOUND);
                return;
  -             }
  +            }
        } else {
                // The following code on Non Windows disallows ../
                // in the path but also disallows symlinks....
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.1.1.1.8.1 +113 -41   
jakarta-tomcat/src/share/org/apache/tomcat/util/SessionIdGenerator.java
  
  Index: SessionIdGenerator.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/SessionIdGenerator.java,v
  retrieving revision 1.1.1.1
  retrieving revision 1.1.1.1.8.1
  diff -u -r1.1.1.1 -r1.1.1.1.8.1
  --- SessionIdGenerator.java   1999/10/09 00:20:56     1.1.1.1
  +++ SessionIdGenerator.java   2000/12/12 01:01:05     1.1.1.1.8.1
  @@ -1,13 +1,13 @@
   /*
  - * $Header: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/SessionIdGenerator.java,v 
1.1.1.1 1999/10/09 00:20:56 duncan Exp $
  - * $Revision: 1.1.1.1 $
  - * $Date: 1999/10/09 00:20:56 $
  + * $Header: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/SessionIdGenerator.java,v 
1.1.1.1.8.1 2000/12/12 01:01:05 craigmcc Exp $
  + * $Revision: 1.1.1.1.8.1 $
  + * $Date: 2000/12/12 01:01:05 $
    *
    * ====================================================================
    *
    * The Apache Software License, Version 1.1
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -15,7 +15,7 @@
    * are met:
    *
    * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer. 
  + *    notice, this list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in
  @@ -23,15 +23,15 @@
    *    distribution.
    *
    * 3. The end-user documentation included with the redistribution, if
  - *    any, must include the following acknowlegement:  
  - *       "This product includes software developed by the 
  + *    any, must include the following acknowlegement:
  + *       "This product includes software developed by the
    *        Apache Software Foundation (http://www.apache.org/)."
    *    Alternately, this acknowlegement may appear in the software itself,
    *    if and wherever such third-party acknowlegements normally appear.
    *
    * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
    *    Foundation" must not be used to endorse or promote products derived
  - *    from this software without prior written permission. For written 
  + *    from this software without prior written permission. For written
    *    permission, please contact [EMAIL PROTECTED]
    *
    * 5. Products derived from this software may not be called "Apache"
  @@ -59,50 +59,122 @@
    *
    * [Additional notices, if required by prior licensing conditions]
    *
  - */ 
  + */
   
   
   package org.apache.tomcat.util;
   
   /**
  - * Generates sesssion ids for the system. The ids produced by this
  - * class aren't very sophisticated being just a random number followed
  - * by a synchronized counter.
  + * This class generates a unique 10+ character id. This is good
  + * for authenticating users or tracking users around.
  + * <p>
  + * This code was borrowed from Apache JServ.JServServletManager.java.
  + * It is what Apache JServ uses to generate session ids for users.
  + * Unfortunately, it was not included in Apache JServ as a class
  + * so I had to create one here in order to use it.
    *
    * @author James Duncan Davidson [[EMAIL PROTECTED]]
    * @author Jason Hunter [[EMAIL PROTECTED]]
  + * @author Jon S. Stevens <a href="mailto:[EMAIL PROTECTED]">[EMAIL PROTECTED]</a>
  + * @author Shai Fultheim [[EMAIL PROTECTED]]
    */
  -
   public class SessionIdGenerator {
   
  -    private static int counter = 1010;
  -    
  -    public static synchronized String generateId() {
  -
  -     // XXX
  -     // This code is not very secure at all. It's good enough
  -     // for a reference implementation where you want to make
  -     // sure to not repeat under most circumstances -- but its
  -     // not anything that could be considered to be safe for
  -     // military or banking use.
  -
  -     // maybe.....
  -     // replace with some sort of MD5 hash so that it is impossible
  -     // to figure out which is the counter and which is the random
  -     
  -        Integer i = new Integer(counter++);
  -        StringBuffer buf = new StringBuffer();
  -        String dString = Double.toString(Math.abs(Math.random()));
  -
  -        // we do the substring to get rid of the initial '0.'
  -        // characters.
  -
  -        buf.append("To");
  -        buf.append(i);
  -        buf.append("mC");
  -        buf.append(dString.substring(2, dString.length()));
  -        buf.append("At");
  +    /*
  +     * Create a suitable string for session identification
  +     * Use synchronized count and time to ensure uniqueness.
  +     * Use random string to ensure timestamp cannot be guessed
  +     * by programmed attack.
  +     *
  +     * format of id is <6 chars random><3 chars time><1+ char count>
  +     */
  +    static private int session_count = 0;
  +    static private long lastTimeVal = 0;
  +    static private java.util.Random randomSource;
  +
  +    // MAX_RADIX is 36
  +    /*
  +     * we want to have a random string with a length of
  +     * 6 characters. Since we encode it BASE 36, we've to
  +     * modulo it with the following value:
  +     */
  +    public final static long maxRandomLen = 2176782336L; // 36 ** 6
  +
  +    /*
  +     * The session identifier must be unique within the typical lifespan
  +     * of a Session, the value can roll over after that. 3 characters:
  +     * (this means a roll over after over an day which is much larger
  +     *  than a typical lifespan)
  +     */
  +    public final static long maxSessionLifespanTics = 46656; // 36 ** 3
  +
  +    /*
  +     *  millisecons between different tics. So this means that the
  +     *  3-character time string has a new value every 2 seconds:
  +     */
  +    public final static long ticDifference = 2000;
  +
  +    // ** NOTE that this must work together with get_jserv_session_balance()
  +    // ** in jserv_balance.c
  +    static synchronized public String getIdentifier (String jsIdent)
  +    {
  +        StringBuffer sessionId = new StringBuffer();
  +        
  +        if (randomSource == null) {
  +            String className = System.getProperty("tomcat.sessionid.randomclass");
  +            if (className != null) {
  +                try {
  +                    Class randomClass = Class.forName(className);
  +                    randomSource = (java.util.Random)randomClass.newInstance();
  +                }
  +                catch (Exception e) {
  +                    e.printStackTrace();
  +                }
  +            }
  +            if (randomSource == null)
  +                randomSource = new java.security.SecureRandom();
  +        }
  +
  +        // random value ..
  +        long n = randomSource.nextLong();
  +        if (n < 0) n = -n;
  +        n %= maxRandomLen;
  +        // add maxLen to pad the leading characters with '0'; remove
  +        // first digit with substring.
  +        n += maxRandomLen;
  +        sessionId.append (Long.toString(n, Character.MAX_RADIX)
  +                  .substring(1));
  +
  +        long timeVal = (System.currentTimeMillis() / ticDifference);
  +        // cut..
  +        timeVal %= maxSessionLifespanTics;
  +        // padding, see above
  +        timeVal += maxSessionLifespanTics;
  +
  +        sessionId.append (Long.toString (timeVal, Character.MAX_RADIX)
  +                  .substring(1));
  +
  +        /*
  +         * make the string unique: append the session count since last
  +         * time flip.
  +         */
  +        // count sessions only within tics. So the 'real' session count
  +        // isn't exposed to the public ..
  +        if (lastTimeVal != timeVal) {
  +          lastTimeVal = timeVal;
  +          session_count = 0;
  +        }
  +        sessionId.append (Long.toString (++session_count,
  +                     Character.MAX_RADIX));
  +
  +        if (jsIdent != null && jsIdent.length() > 0) {
  +            return sessionId.toString()+"."+jsIdent;
  +        }
  +        return sessionId.toString();
  +    }
   
  -        return buf.toString();
  +    public static synchronized String generateId(String jsIdent) {
  +        return getIdentifier(jsIdent);
       }
  +
   }
  
  
  
  1.3.4.1   +5 -24     
jakarta-tomcat/src/share/org/apache/tomcat/util/Attic/SessionUtil.java
  
  Index: SessionUtil.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/Attic/SessionUtil.java,v
  retrieving revision 1.3
  retrieving revision 1.3.4.1
  diff -u -r1.3 -r1.3.4.1
  --- SessionUtil.java  2000/02/14 04:59:43     1.3
  +++ SessionUtil.java  2000/12/12 01:01:06     1.3.4.1
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/Attic/SessionUtil.java,v 1.3 
2000/02/14 04:59:43 costin Exp $
  - * $Revision: 1.3 $
  - * $Date: 2000/02/14 04:59:43 $
  + * $Header: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/Attic/SessionUtil.java,v 
1.3.4.1 2000/12/12 01:01:06 craigmcc Exp $
  + * $Revision: 1.3.4.1 $
  + * $Date: 2000/12/12 01:01:06 $
    *
    * ====================================================================
    *
  @@ -75,21 +75,12 @@
    * <code>Session</code> implementations.
    *
    * @author Craig R. McClanahan
  - * @version $Revision: 1.3 $ $Date: 2000/02/14 04:59:43 $
  + * @version $Revision: 1.3.4.1 $ $Date: 2000/12/12 01:01:06 $
    */
   
   public final class SessionUtil {
   
   
  -    // ------------------------------------------------------- Static Variables
  -
  -
  -    /**
  -     * Private counter used in generating session identifiers.
  -     */
  -    private static int counter = 1010;
  -
  -
       // --------------------------------------------------------- Public Methods
   
   
  @@ -182,18 +173,8 @@
        * is not at all sophisticated or secure.
        */
       public static String generateSessionId() {
  -
  -     Integer i = new Integer(counter++);
  -     StringBuffer buf = new StringBuffer();
  -     String dString = Double.toString(Math.abs(Math.random()));
  -
  -     buf.append("To");
  -     buf.append(i);
  -     buf.append("mC");
  -     buf.append(dString.substring(2));       // Skip "0." at the start
  -     buf.append("At");
   
  -     return (buf.toString());
  +        return (SessionIdGenerator.generateId(null));
   
       }
   
  
  
  

Reply via email to