Skip to content

Commit

Permalink
Partial fix for CVE-2017-12617
Browse files Browse the repository at this point in the history
This moves a check from the Default servlet where it applied to GET, POST, HEAD and OPTIONS to the resources implementation where it applies to any method that expects the resource to exist (e.g.DELETE)
Still need to address the case where the resource does not exist (e.g. PUT)

git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk@1809288 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
markt-asf committed Sep 22, 2017
1 parent ccb3bc0 commit 512a3c3
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 28 deletions.
17 changes: 0 additions & 17 deletions java/org/apache/catalina/servlets/DefaultServlet.java
Expand Up @@ -860,23 +860,6 @@ protected void serveResource(HttpServletRequest request,
return;
}

// If the resource is not a collection, and the resource path
// ends with "/" or "\", return NOT FOUND
if (cacheEntry.context == null) {
if (path.endsWith("/") || (path.endsWith("\\"))) {
// Check if we're included so we can return the appropriate
// missing resource name in the error
String requestUri = (String) request.getAttribute(
RequestDispatcher.INCLUDE_REQUEST_URI);
if (requestUri == null) {
requestUri = request.getRequestURI();
}
response.sendError(HttpServletResponse.SC_NOT_FOUND,
requestUri);
return;
}
}

// Check if the conditions specified in the optional If headers are
// satisfied.
if (cacheEntry.context == null) {
Expand Down
11 changes: 9 additions & 2 deletions java/org/apache/naming/resources/FileDirContext.java
Expand Up @@ -801,11 +801,18 @@ protected File file(String name) {
*/
protected File file(String name, boolean mustExist) {
File file = new File(base, name);
return validate(file, mustExist, absoluteBase);
return validate(file, name, mustExist, absoluteBase);
}


protected File validate(File file, boolean mustExist, String absoluteBase) {
protected File validate(File file, String name, boolean mustExist, String absoluteBase) {

// If the requested names ends in '/', the Java File API will return a
// matching file if one exists. This isn't what we want as it is not
// consistent with the Servlet spec rules for request mapping.
if (file.isFile() && name.endsWith("/")) {
return null;
}

if (!mustExist || file.exists() && file.canRead()) {

Expand Down
18 changes: 9 additions & 9 deletions java/org/apache/naming/resources/VirtualDirContext.java
Expand Up @@ -163,16 +163,16 @@ public Attributes getAttributes(String name) throws NamingException {
String resourcesDir = dirList.get(0);
if (name.equals(path)) {
File f = new File(resourcesDir);
f = validate(f, true, resourcesDir);
f = validate(f, name, true, resourcesDir);
if (f != null) {
return new FileResourceAttributes(f);
}
}
path += "/";
if (name.startsWith(path)) {
String res = name.substring(path.length());
File f = new File(resourcesDir + "/" + res);
f = validate(f, true, resourcesDir);
File f = new File(resourcesDir, res);
f = validate(f, res, true, resourcesDir);
if (f != null) {
return new FileResourceAttributes(f);
}
Expand Down Expand Up @@ -206,7 +206,7 @@ protected File file(String name, boolean mustExist) {
if (name.equals(path)) {
for (String resourcesDir : dirList) {
file = new File(resourcesDir);
file = validate(file, true, resourcesDir);
file = validate(file, name, true, resourcesDir);
if (file != null) {
return file;
}
Expand All @@ -216,7 +216,7 @@ protected File file(String name, boolean mustExist) {
String res = name.substring(path.length());
for (String resourcesDir : dirList) {
file = new File(resourcesDir, res);
file = validate(file, true, resourcesDir);
file = validate(file, res, true, resourcesDir);
if (file != null) {
return file;
}
Expand Down Expand Up @@ -252,7 +252,7 @@ protected List<NamingEntry> list(File file) {
if (res != null) {
for (String resourcesDir : dirList) {
File f = new File(resourcesDir, res);
f = validate(f, true, resourcesDir);
f = validate(f, res, true, resourcesDir);
if (f != null && f.isDirectory()) {
List<NamingEntry> virtEntries = super.list(f);
for (NamingEntry entry : virtEntries) {
Expand Down Expand Up @@ -288,7 +288,7 @@ protected Object doLookup(String name) {
if (name.equals(path)) {
for (String resourcesDir : dirList) {
File f = new File(resourcesDir);
f = validate(f, true, resourcesDir);
f = validate(f, name, true, resourcesDir);
if (f != null) {
if (f.isFile()) {
return new FileResource(f);
Expand All @@ -304,8 +304,8 @@ protected Object doLookup(String name) {
if (name.startsWith(path)) {
String res = name.substring(path.length());
for (String resourcesDir : dirList) {
File f = new File(resourcesDir + "/" + res);
f = validate(f, true, resourcesDir);
File f = new File(resourcesDir, res);
f = validate(f, res, true, resourcesDir);
if (f != null) {
if (f.isFile()) {
return new FileResource(f);
Expand Down
46 changes: 46 additions & 0 deletions test/org/apache/naming/resources/TestFileDirContext.java
@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.naming.resources;

import java.io.File;

import javax.servlet.http.HttpServletResponse;

import org.junit.Assert;
import org.junit.Test;

import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.startup.TomcatBaseTest;
import org.apache.tomcat.util.buf.ByteChunk;

public class TestFileDirContext extends TomcatBaseTest {

@Test
public void testLookupResourceWithTrailingSlash() throws Exception {
Tomcat tomcat = getTomcatInstance();

File appDir = new File("test/webapp-3.0");
// app dir is relative to server home
tomcat.addWebapp(null, "/test", appDir.getAbsolutePath());

tomcat.start();

int sc = getUrl("http://localhost:" + getPort() +
"/test/index.html/", new ByteChunk(), null);
Assert.assertEquals(HttpServletResponse.SC_NOT_FOUND, sc);
}
}

0 comments on commit 512a3c3

Please sign in to comment.