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 © 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));
}