marcsaeg    01/07/16 21:25:56

  Modified:    src/share/org/apache/tomcat/core Tag: tomcat_32
                        ContextManager.java
               src/share/org/apache/tomcat/request Tag: tomcat_32
                        AccessInterceptor.java
               src/share/org/apache/tomcat/util Tag: tomcat_32 URLUtil.java
  Log:
  This fixes several security related problems.
  
  1)  Non-normalized URIs bypass security-contraints
  
  2)  HTTP method (e.g. GET, POST, ...) comparisons in the AccessInterceptor were case 
sensitive.  Thus, using telnet to issue "get 
/examples/jsp/security/protected/index.jsp"
  would bypass the security constraint, but "GET 
/examples/jsp/security/protected/index.jsp" would not.
  
  3)  Special chars (%25, %2e, %2f, %5c) in URIs are forbidden.
  
  PR:  2612
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.100.2.26 +16 -1     
jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java
  
  Index: ContextManager.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java,v
  retrieving revision 1.100.2.25
  retrieving revision 1.100.2.26
  diff -u -r1.100.2.25 -r1.100.2.26
  --- ContextManager.java       2001/07/11 05:24:14     1.100.2.25
  +++ ContextManager.java       2001/07/17 04:25:54     1.100.2.26
  @@ -740,7 +740,22 @@
        *  XXX make sure the alghoritm is right, deal with response codes
        */
       public void service( Request req, Response res ) {
  -     internalService( req, res );
  +
  +    /**
  +     * XXX Normalize and validate the request URI.  This is important
  +     * to prevent non-normalized URIs from causing security constraints
  +     * from being bypassed.  For example, 
/examples/jsp/../jsp/security/protected/index.jsp
  +     * would not trigger the AccessInterceptor.  Also, encoded special chars
  +     * ., /, \ and % are forbidden in URIs to prevent additional security problems.
  +     */
  +    req.setRequestURI(URLUtil.normalizeURI(req.getRequestURI()));
  +    String ucURI = req.getRequestURI().toUpperCase();
  +    if(ucURI.indexOf("%25") >= 0 || ucURI.indexOf("%2E") >= 0 || 
  +       ucURI.indexOf("%2F") >= 0 || ucURI.indexOf("%5C") >=0){
  +        res.setStatus(404);
  +    }
  +
  +    internalService( req, res );
        // clean up
        try {
            res.finish();
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.12.2.9  +1 -1      
jakarta-tomcat/src/share/org/apache/tomcat/request/Attic/AccessInterceptor.java
  
  Index: AccessInterceptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/Attic/AccessInterceptor.java,v
  retrieving revision 1.12.2.8
  retrieving revision 1.12.2.9
  diff -u -r1.12.2.8 -r1.12.2.9
  --- AccessInterceptor.java    2001/07/15 23:09:31     1.12.2.8
  +++ AccessInterceptor.java    2001/07/17 04:25:55     1.12.2.9
  @@ -314,7 +314,7 @@
        if( ctMethods != null && ctMethods.length > 0 ) {
            boolean ok=false;
            for( int i=0; i< ctMethods.length; i++ ) {
  -             if( method.equals( ctMethods[i] ) ) {
  +             if( method.equalsIgnoreCase( ctMethods[i] ) ) {
                    ok=true;
                    break;
                }
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.7.2.3   +90 -3     
jakarta-tomcat/src/share/org/apache/tomcat/util/Attic/URLUtil.java
  
  Index: URLUtil.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/Attic/URLUtil.java,v
  retrieving revision 1.7.2.2
  retrieving revision 1.7.2.3
  diff -u -r1.7.2.2 -r1.7.2.3
  --- URLUtil.java      2001/04/08 01:37:57     1.7.2.2
  +++ URLUtil.java      2001/07/17 04:25:55     1.7.2.3
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/Attic/URLUtil.java,v 1.7.2.2 
2001/04/08 01:37:57 marcsaeg Exp $
  - * $Revision: 1.7.2.2 $
  - * $Date: 2001/04/08 01:37:57 $
  + * $Header: 
/home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/Attic/URLUtil.java,v 1.7.2.3 
2001/07/17 04:25:55 marcsaeg Exp $
  + * $Revision: 1.7.2.3 $
  + * $Date: 2001/07/17 04:25:55 $
    *
    * ====================================================================
    *
  @@ -205,4 +205,91 @@
   
           return hasEscape;
       }
  +
  +    // Based on Apache's path normalization code
  +    public static String normalizeURI(String URI)
  +    {
  +        int start=0;
  +        int end=URI.length();
  +        char buff[] = new char[URI.length()];
  +        URI.getChars(0, URI.length(), buff, 0);
  +        int i=0;
  +        int j=0;
  +    
  +        // remove //
  +        for( i=start, j=start; i<end-1; i++ ) {
  +            if( buff[i]== '/' && buff[i+1]=='/' ) {
  +                while( buff[i+1]=='/' ) i++;
  +            }
  +            buff[j++]=buff[i];
  +        }
  +        if( i!=j ) {
  +            buff[j++]=buff[end-1];
  +            end=j;
  +        }
  +    
  +        // remove /./
  +        for( i=start, j=start; i<end-1; i++ ) {
  +            if( buff[i]== '.' && buff[i+1]=='/' &&
  +                ( i==0 || buff[i-1]=='/' )) {
  +                // "/./"
  +                i+=1;
  +                if( i==end-1 ) j--; // cut the ending /
  +            } else {
  +                buff[j++]=buff[i];
  +            }
  +        }
  +        if( i!=j ) {
  +            buff[j++]=buff[end-1];
  +            end=j;
  +        }
  +    
  +        // remove  /. at the end
  +        j=end;
  +        if( end==start+1 && buff[start]== '.' )
  +            end--;
  +        else if( end > start+1 && buff[ end-1 ] == '.' &&
  +                 buff[end-2]=='/' ) {
  +            end=end-2;
  +        }
  +    
  +        // remove /../
  +        for( i=start, j=start; i<end-2; i++ ) {
  +            if( buff[i] == '.' &&
  +                buff[i+1] == '.' &&
  +                buff[i+2]== '/' &&
  +                ( i==0 || buff[ i-1 ] == '/' ) ) {
  +    
  +                i+=1;
  +                // look for the previous /
  +                j=j-2;
  +                while( j>0 && buff[j]!='/' ) {
  +                    j--;
  +                }
  +            } else {
  +                buff[j++]=buff[i];
  +            }
  +        }
  +        if( i!=j ) {
  +            buff[j++]=buff[end-2];
  +            buff[j++]=buff[end-1];
  +            end=j;
  +        }
  +    
  +    
  +        // remove trailing xx/..
  +        j=end;
  +        if( end>start + 3 &&
  +            buff[end-1]=='.' &&
  +            buff[end-2]=='.' &&
  +            buff[end-3]=='/' ) {
  +            end-=4;
  +            while( end>0 &&  buff[end]!='/' )
  +                end--; 
  +        }
  +
  +        String result = new String(buff, 0, end);
  +        return result;
  +    }
  +    
   }
  
  
  

Reply via email to