[ 
https://issues.apache.org/jira/browse/JEXL-381?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17627881#comment-17627881
 ] 

Dmitri Blinov commented on JEXL-381:
------------------------------------

[~henrib] The sandbox is not part of Jexl, rather part of some project that 
incorporates Jexl, since there are some project specific pecularities. As I 
personally prefer subclassing to delegation, it comprises primaraly of 
extensions to Permissions and Uberspect. I don't think it will be of much use 
to others as is, but since you're asking I can publish it with some omissions. 
The Uberspect deals with some magic around j.n.URI class to override toURL() 
method for file schemes. The permissions extension is as follows  
{code:java}
public class MyPermissions extends Permissions {

    protected static final Set<String> restrictedConstructors = 
Collections.unmodifiableSet(new LinkedHashSet<String>(Arrays.asList(
       "java.io.File", "java.io.FileDescriptor", "java.io.FileInputStream", 
"java.io.FileOutputStream", 
       "java.io.FilePermission", "java.io.FileReader", "java.io.FileWriter", 
"java.io.PrintStream", "java.io.PrintWriter", 
       "java.io.RandomAccessFile", "java.io.ObjectInputStream", 
"java.util.zip.ZipFile", "java.util.jar.JarFile",
       "java.net.URL", "java.net.URLClassLoader"
    )));

    protected boolean isAllowedMethod(Method m) {

      if (!Modifier.isPublic(m.getModifiers()))
         return false;

      if (m.isSynthetic())
         return false;

      Class<?> clazz = m.getDeclaringClass();
      String method = m.getName();

      // Prevent direct invocation
      if (Class.class.isAssignableFrom(clazz) && ("forName".equals(method) || 
"getClassLoader".equals(method)))
         return false;

      // Prevent direct invocation
      if (Method.class.isAssignableFrom(clazz) && ("invoke".equals(method) || 
"setAccessible".equals(method)))
         return false;

      // Prevent direct invocation
      if (MethodHandle.class.isAssignableFrom(clazz) && 
("invoke".equals(method) || "invokeExact".equals(method)))
         return false;

      // Prevent direct invocation
      if (Constructor.class.isAssignableFrom(clazz) && 
"newInstance".equals(method))
         return false;

      // Prevent direct invocation
      if (File.class.isAssignableFrom(clazz) && 
("createTempFile".equals(method) || "listRoots".equals(method)))
         return false;

      // Prevent direct invocation
      if (URL.class.isAssignableFrom(clazz) && 
"setURLStreamHandlerFactory".equals(method))
         return false;

      // Prevent direct invocation
      if (URLConnection.class.isAssignableFrom(clazz) && 
("setContentHandlerFactory".equals(method) || 
"setDefaultAllowUserInteraction".equals(method) || 
          "setDefaultRequestProperty".equals(method) || 
"setFileNameMap".equals(method)))
         return false;

       // Prevent static method invocations on restricted classes
      String name = clazz.getName();

      if (MyDefaultContext.PackageResolver.restrictedNames.contains(name) && 
Modifier.isStatic(m.getModifiers()))
         return false;

      MyPermission msyc = clazz.getAnnotation(MyPermission.class);
      MyScripting permission = (msyc != null) ? msyc.scripting() : 
MyScripting.ALLOW;

      MyPermission msyp = m.getAnnotation(MyPermission.class);

      if (msyp != null)
         permission = msyp.scripting();

      if (permission == MyScripting.RESTRICT)
         return false;

      return true;
    }

    /**
     * Checks whether a method disallows introspection.
     * <p>Since methods can be overridden, this also checks that no superclass 
or interface
     * explictly disallows this methods.</p>
     * @param method the method to check
     * @return true if JEXL is allowed to introspect, false otherwise
     */
    @Override
    public boolean allow(Method method) {

        if (method == null) 
            return false;

        if (!isAllowedMethod(method))
            return false;

        return super.allow(method);
    }

    /**
     * Checks whether a constructor disallows introspection.
     * @param ctor the constructor to check
     * @return true if JEXL is allowed to introspect, false otherwise
     */
    @Override
    public boolean allow(Constructor<?> ctor) {

        if (ctor == null)
            return false;

        if (!Modifier.isPublic(ctor.getModifiers()))
            return false;

        Class<?> clazz = ctor.getDeclaringClass();

        if (!allow(clazz))
            return false;

        String name = clazz.getName();

        if (restrictedConstructors.contains(name))
            return false;

        if (MyDefaultContext.PackageResolver.restrictedNames.contains(name))
            return false;

        return true;
    }

}{code}
 

> Change default JEXL configuration to a more security-friendly behaviour 
> ------------------------------------------------------------------------
>
>                 Key: JEXL-381
>                 URL: https://issues.apache.org/jira/browse/JEXL-381
>             Project: Commons JEXL
>          Issue Type: Improvement
>    Affects Versions: 3.2.1
>            Reporter: Henri Biestro
>            Assignee: Henri Biestro
>            Priority: Major
>             Fix For: 3.3
>
>
> WHAT:
> JEXL's default builder allows accessing and calling any public method, field 
> or constructor of any public class. This might not be desirable since a quick 
> exploration of JEXL will quickly conclude the library allows arbitrary 
> execution through commands (ProcessBuilder) or getting to the file-system 
> through URL or File. This improvement goal is to change JEXL's permeability 
> as an explicit option and user decision, not a default behaviour.
> HOW:
> By changing the current JexlBuilder to use a restricted set of permissions 
> whilst instantiating the Uberspect, we can ensure a minimal useful set of 
> classes can be accessed and only those by default. By removing access to 
> almost all classes that interact with the JVM host and file-system, we ensure 
> a default isolation that would significantly reduce the ability to use JEXL 
> as an attack vector.
> CAVEAT:
> This change will likely break many scripts that were dependant upon the 
> default permeability.
> [~ggregory], [~dmitri_blinov] your opinions are welcome :-)
> https://lists.apache.org/thread/kgh0kfkcvllp5mj7kwnpdqrbrfcyyopd



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to