Skip to content

Commit

Permalink
Issue #6497 - Implement the AllowedResourceAliasChecker to improve Sa…
Browse files Browse the repository at this point in the history
…meFileAliasChecker

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
  • Loading branch information
lachlan-roberts committed Jul 9, 2021
1 parent 40535f1 commit a1bb8f3
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 0 deletions.
@@ -0,0 +1,57 @@
package org.eclipse.jetty.server;

import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;

import java.io.File;

/**
* This will approve an alias to any resource which is not a protected target.
*/
public class AllowedResourceAliasChecker implements ContextHandler.AliasCheck
{
private static final Logger LOG = Log.getLogger(AllowedResourceAliasChecker.class);
private final ContextHandler _contextHandler;

public AllowedResourceAliasChecker(ContextHandler contextHandler)
{
_contextHandler = contextHandler;
}

@Override
public boolean check(String uri, Resource resource)
{
try
{
String baseResourcePath = _contextHandler.getBaseResource().getFile().getCanonicalPath();
String resourcePath = resource.getFile().getCanonicalPath();
if (!resourcePath.startsWith(baseResourcePath))
return false;

for (String s : _contextHandler.getProtectedTargets())
{
String protectedTarget = new File(_contextHandler.getBaseResource().getFile(), s).getCanonicalPath();
if (StringUtil.startsWithIgnoreCase(resourcePath, protectedTarget))
{
if (resourcePath.length() == protectedTarget.length())
return false;

// Check that the target prefix really is a path segment.
char c = resourcePath.charAt(protectedTarget.length());
if (c == File.separatorChar)
return false;
}
}
}
catch (Throwable t)
{
LOG.warn(t);
return false;
}

return true;
}
}
@@ -0,0 +1,62 @@
package org.eclipse.jetty.test;

import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.server.AllowedResourceAliasChecker;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.resource.Resource;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.net.URI;
import java.net.URL;

public class TestClass
{
private Server _server;
private HttpClient _client;

@BeforeEach
public void before() throws Exception
{
_server = new Server(8080);

URL webRootLocation = TestClass.class.getClassLoader().getResource("webroot/index.html");
URI webRootUri = URI.create(webRootLocation.toURI().toASCIIString().replaceFirst("/index.html$","/"));
System.err.printf("Web Root URI: %s%n",webRootUri);

ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
context.setBaseResource(Resource.newResource(webRootUri));
context.setWelcomeFiles(new String[] { "index.html" });
context.setProtectedTargets(new String[]{"/web-inf", "/meta-inf"});
context.getMimeTypes().addMimeMapping("txt","text/plain;charset=utf-8");

context.addAliasCheck(new AllowedResourceAliasChecker(context));
_server.setHandler(context);
context.addServlet(DefaultServlet.class,"/");
_server.start();

_client = new HttpClient();
_client.start();
}


@AfterEach
public void after() throws Exception
{
_client.stop();
_server.stop();
}

@Test
public void test() throws Exception
{
// ContentResponse response = _client.GET("http://localhost:8080/\\WEB-INF\\web.xml");
// System.err.println(response);

_server.join();
}
}
@@ -0,0 +1 @@
should not be able to access this file.
4 changes: 4 additions & 0 deletions tests/test-integration/src/test/resources/webroot/index.html
@@ -0,0 +1,4 @@
<html>
<h1>hello world</h1>
<p>body of index.html</p>
</html>
@@ -0,0 +1 @@
this is test .txt file and safe to access

0 comments on commit a1bb8f3

Please sign in to comment.