Skip to content

HTTP: Ensure url path expansion only works inside of plugins #10815

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 27, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions src/main/java/org/elasticsearch/http/HttpServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,13 @@ void handlePluginSite(HttpRequest request, HttpChannel channel) throws IOExcepti
sitePath = sitePath.replace("/", separator);
// this is a plugin provided site, serve it as static files from the plugin location
Path file = FileSystemUtils.append(siteFile, PathUtils.get(sitePath), 0);
if (!Files.exists(file) || Files.isHidden(file)) {

// return not found instead of forbidden to prevent malicious requests to find out if files exist or dont exist
if (!Files.exists(file) || Files.isHidden(file) || !file.toAbsolutePath().normalize().startsWith(siteFile.toAbsolutePath())) {
channel.sendResponse(new BytesRestResponse(NOT_FOUND));
return;
}

BasicFileAttributes attributes = Files.readAttributes(file, BasicFileAttributes.class);
if (!attributes.isRegularFile()) {
// If it's not a dir, we send a 403
Expand All @@ -196,10 +198,7 @@ void handlePluginSite(HttpRequest request, HttpChannel channel) throws IOExcepti
return;
}
}
if (!file.toAbsolutePath().startsWith(siteFile.toAbsolutePath())) {
channel.sendResponse(new BytesRestResponse(FORBIDDEN));
return;
}

try {
byte[] data = Files.readAllBytes(file);
channel.sendResponse(new BytesRestResponse(OK, guessMimeType(sitePath), data));
Expand Down
31 changes: 31 additions & 0 deletions src/test/java/org/elasticsearch/plugins/SitePluginTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope;
Expand Down Expand Up @@ -86,6 +89,34 @@ public void testAnyPage() throws Exception {
assertThat(response.getBody(), containsString("<title>Dummy Site Plugin</title>"));
}

/**
* Test normalizing of path
*/
@Test
public void testThatPathsAreNormalized() throws Exception {
// more info: https://www.owasp.org/index.php/Path_Traversal
List<String> notFoundUris = new ArrayList<>();
notFoundUris.add("/_plugin/dummy/../../../../../log4j.properties");
notFoundUris.add("/_plugin/dummy/../../../../../%00log4j.properties");
notFoundUris.add("/_plugin/dummy/..%c0%af..%c0%af..%c0%af..%c0%af..%c0%aflog4j.properties");
notFoundUris.add("/_plugin/dummy/%2E%2E/%2E%2E/%2E%2E/%2E%2E/index.html");
notFoundUris.add("/_plugin/dummy/%2e%2e/%2e%2e/%2e%2e/%2e%2e/index.html");
notFoundUris.add("/_plugin/dummy/%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2findex.html");
notFoundUris.add("/_plugin/dummy/%2E%2E/%2E%2E/%2E%2E/%2E%2E/index.html");
notFoundUris.add("/_plugin/dummy/..\\..\\..\\..\\..\\log4j.properties");

for (String uri : notFoundUris) {
HttpResponse response = httpClient().path(uri).execute();
String message = String.format(Locale.ROOT, "URI [%s] expected to be not found", uri);
assertThat(message, response.getStatusCode(), equalTo(RestStatus.NOT_FOUND.getStatus()));
}

// using relative path inside of the plugin should work
HttpResponse response = httpClient().path("/_plugin/dummy/dir1/../dir1/../index.html").execute();
assertThat(response.getStatusCode(), equalTo(RestStatus.OK.getStatus()));
assertThat(response.getBody(), containsString("<title>Dummy Site Plugin</title>"));
}

/**
* Test case for #4845: https://github.com/elasticsearch/elasticsearch/issues/4845
* Serving _site plugins do not pick up on index.html for sub directories
Expand Down
Empty file.