SOLR-14015: remove blanket filesystem read access from solr-tests.policy

Restrict this to only minimal paths like lucene. It is the defense for directory traversal attacks.
It will also help find bad bugs where things are reading filesystem in the wrong locations.
This commit is contained in:
Robert Muir 2019-12-04 23:16:19 -05:00
parent f71c2c8e92
commit c4126ef858
5 changed files with 57 additions and 5 deletions

View File

@ -1094,6 +1094,8 @@
<!-- Restrict access to certain Java features and install security manager: --> <!-- Restrict access to certain Java features and install security manager: -->
<sysproperty key="common.dir" file="${common.dir}" /> <sysproperty key="common.dir" file="${common.dir}" />
<sysproperty key="common-solr.dir" file="${common.dir}/../solr" />
<sysproperty key="ant.library.dir" file="${ant.library.dir}" />
<sysproperty key="clover.db.dir" file="${clover.db.dir}" /> <sysproperty key="clover.db.dir" file="${clover.db.dir}" />
<syspropertyset> <syspropertyset>
<propertyref prefix="java.security.manager"/> <propertyref prefix="java.security.manager"/>

View File

@ -104,6 +104,30 @@ public final class TestSecurityManager extends SecurityManager {
super.checkWrite(file); super.checkWrite(file);
} }
/**
* {@inheritDoc}
* <p>This method implements hacks to workaround hadoop's garbage FileUtil code
*/
@Override
public void checkRead(String file) {
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
// hadoop "createPermissionsDiagnosisString" method doesn't handle securityexception and fails completely.
// it insists on climbing up full directory tree!
// so, lie to it, and tell it we will happily read, so it does not crash.
if ("org.apache.hadoop.hdfs.MiniDFSCluster".equals(element.getClassName()) &&
"createPermissionsDiagnosisString".equals(element.getMethodName())) {
return;
}
// hadoop "canRead" method doesn't handle securityexception and fails completely.
// so, lie to it, and tell it we will happily read, so it does not crash.
if ("org.apache.hadoop.fs.FileUtil".equals(element.getClassName()) &&
"canRead".equals(element.getMethodName())) {
return;
}
}
super.checkRead(file);
}
/** /**
* {@inheritDoc} * {@inheritDoc}
* <p>This method inspects the stack trace and checks who is calling * <p>This method inspects the stack trace and checks who is calling

View File

@ -18,8 +18,14 @@
// Policy file for solr tests. Please keep minimal and avoid wildcards. // Policy file for solr tests. Please keep minimal and avoid wildcards.
grant { grant {
// permissions for file access, write access only to sandbox: // contain read access to only what we need:
permission java.io.FilePermission "<<ALL FILES>>", "read"; // 3rd party jar resources (where symlinks are not supported), test-files/ resources
permission java.io.FilePermission "${common.dir}${/}-", "read";
permission java.io.FilePermission "${common-solr.dir}${/}-", "read";
// 3rd party jar resources (where symlinks are supported)
permission java.io.FilePermission "${user.home}${/}.ivy2${/}cache${/}-", "read";
// system jar resources
permission java.io.FilePermission "${java.home}${/}-", "read";
permission java.io.FilePermission "${junit4.childvm.cwd}", "read"; permission java.io.FilePermission "${junit4.childvm.cwd}", "read";
permission java.io.FilePermission "${junit4.childvm.cwd}${/}temp", "read,write,delete"; permission java.io.FilePermission "${junit4.childvm.cwd}${/}temp", "read,write,delete";
permission java.io.FilePermission "${junit4.childvm.cwd}${/}temp${/}-", "read,write,delete"; permission java.io.FilePermission "${junit4.childvm.cwd}${/}temp${/}-", "read,write,delete";
@ -27,6 +33,22 @@ grant {
permission java.io.FilePermission "${junit4.tempDir}${/}*", "read,write,delete"; permission java.io.FilePermission "${junit4.tempDir}${/}*", "read,write,delete";
permission java.io.FilePermission "${clover.db.dir}${/}-", "read,write,delete"; permission java.io.FilePermission "${clover.db.dir}${/}-", "read,write,delete";
permission java.io.FilePermission "${tests.linedocsfile}", "read"; permission java.io.FilePermission "${tests.linedocsfile}", "read";
// hadoop
permission java.io.FilePermission "${ant.library.dir}${/}-", "read";
permission java.io.FilePermission "${user.home}${/}.ant${/}lib${/}-", "read";
permission java.io.FilePermission "${user.home}${/}hadoop-metrics2.properties", "read";
permission java.io.FilePermission "${user.home}${/}hadoop-metrics2-namenode.properties", "read";
// kerberos
permission java.io.FilePermission "${user.home}${/}.java.login.config", "read";
// SolrTestCaseJ4 explicitly uses these
permission java.io.FilePermission "/dev/./urandom", "read";
permission java.io.FilePermission "/dev/random", "read";
// DirectoryFactoryTest messes with these (wtf?)
permission java.io.FilePermission "/tmp/inst1/conf/solrcore.properties", "read";
permission java.io.FilePermission "/path/to/myinst/conf/solrcore.properties", "read";
// TestConfigSets messes with these (wtf?)
permission java.io.FilePermission "/path/to/solr/home/lib", "read";
permission java.nio.file.LinkPermission "hard"; permission java.nio.file.LinkPermission "hard";
// all possibilities of accepting/binding connections on localhost with ports >=1024: // all possibilities of accepting/binding connections on localhost with ports >=1024:

View File

@ -18,6 +18,7 @@ package org.apache.solr.cloud.rule;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -82,8 +83,9 @@ public class RulesTest extends SolrCloudTestCase {
5, cluster.getJettySolrRunners().size()); 5, cluster.getJettySolrRunners().size());
final long minGB = (random().nextBoolean() ? 1 : 0); final long minGB = (random().nextBoolean() ? 1 : 0);
final Path toTest = Paths.get("").toAbsolutePath();
assumeTrue("doIntegrationTest needs minGB="+minGB+" usable disk space", assumeTrue("doIntegrationTest needs minGB="+minGB+" usable disk space",
ImplicitSnitch.getUsableSpaceInGB(Paths.get("/")) > minGB); ImplicitSnitch.getUsableSpaceInGB(toTest) > minGB);
String rulesColl = "rulesColl"; String rulesColl = "rulesColl";
CollectionAdminRequest.createCollectionWithImplicitRouter(rulesColl, "conf", "shard1", 2) CollectionAdminRequest.createCollectionWithImplicitRouter(rulesColl, "conf", "shard1", 2)
@ -323,13 +325,14 @@ public class RulesTest extends SolrCloudTestCase {
@Test @Test
public void testModifyColl() throws Exception { public void testModifyColl() throws Exception {
final Path toTest = Paths.get("").toAbsolutePath();
final long minGB1 = (random().nextBoolean() ? 1 : 0); final long minGB1 = (random().nextBoolean() ? 1 : 0);
final long minGB2 = 5; final long minGB2 = 5;
assumeTrue("testModifyColl needs minGB1="+minGB1+" usable disk space", assumeTrue("testModifyColl needs minGB1="+minGB1+" usable disk space",
ImplicitSnitch.getUsableSpaceInGB(Paths.get("/")) > minGB1); ImplicitSnitch.getUsableSpaceInGB(toTest) > minGB1);
assumeTrue("testModifyColl needs minGB2="+minGB2+" usable disk space", assumeTrue("testModifyColl needs minGB2="+minGB2+" usable disk space",
ImplicitSnitch.getUsableSpaceInGB(Paths.get("/")) > minGB2); ImplicitSnitch.getUsableSpaceInGB(toTest) > minGB2);
String rulesColl = "modifyColl"; String rulesColl = "modifyColl";
CollectionAdminRequest.createCollection(rulesColl, "conf", 1, 2) CollectionAdminRequest.createCollection(rulesColl, "conf", 1, 2)

View File

@ -87,6 +87,7 @@ public class TestSystemIdResolver extends SolrTestCaseJ4 {
resolver.resolveEntity(null, null, "solrres:/solrconfig.xml", path); resolver.resolveEntity(null, null, "solrres:/solrconfig.xml", path);
}); });
assertTrue(ioe.getMessage().startsWith("Can't find resource") assertTrue(ioe.getMessage().startsWith("Can't find resource")
|| ioe.getMessage().contains("access denied")
|| ioe.getMessage().contains("is outside resource loader dir")); || ioe.getMessage().contains("is outside resource loader dir"));
} }
} }