Java 如何创建安全的JEXL(脚本)沙盒?
我正在为JEXL脚本创建一个沙盒,以便恶意用户无法访问我们授予他们访问权限的变量之外的数据,也无法对服务器执行DOS攻击。我想为其他也这样做的人记录这一点,并让其他人对该方法进行输入 以下是我知道需要解决的事项列表:Java 如何创建安全的JEXL(脚本)沙盒?,java,jexl,Java,Jexl,我正在为JEXL脚本创建一个沙盒,以便恶意用户无法访问我们授予他们访问权限的变量之外的数据,也无法对服务器执行DOS攻击。我想为其他也这样做的人记录这一点,并让其他人对该方法进行输入 以下是我知道需要解决的事项列表: 仅允许使用白名单上的“new”实例化类 不允许在任何类上访问getClass方法,因为这样可以调用forName,并且可以访问任何类 限制对文件等资源的访问 只允许表达式执行一定的时间,这样我们就可以限制它所消耗的资源量 这不适用于JEXL,但可能适用于您正在使用的脚本语言: 不允
更新:这一切都是使用JEXL 2.0.1完成的。您可能需要对此进行调整,以使其适用于较新版本。 以下是我处理这些案件的方法。我已经创建了单元测试来测试这些案例中的每一个,并且我已经验证了它们的有效性
class MyUberspectImpl extends UberspectImpl {
public MyUberspectImpl(Log jexlLog) {
super(jexlLog);
}
@Override
public JexlPropertyGet getPropertyGet(Object obj, Object identifier, JexlInfo info) {
// for security we do not allow access to .class property
if ("class".equals(identifier)) throw new RuntimeException("Access to getClass() method is not allowed");
JexlPropertyGet propertyGet = super.getPropertyGet(obj, identifier, info);
return propertyGet;
}
@Override
public JexlMethod getMethod(Object obj, String method, Object[] args, JexlInfo info) {
// for security we do not allow access to .getClass() method
if ("getClass".equals(method)) throw new RuntimeException("Access to getClass() method is not allowed");
return super.getMethod(obj, method, args, info);
}
}
System.out.println("java.security.policy=" + System.getProperty("java.security.policy"));
System.setSecurityManager(new SecurityManager());
try {
Permissions perms = new Permissions();
perms.add(new RuntimePermission("accessDeclaredMembers"));
ProtectionDomain domain = new ProtectionDomain(new CodeSource( null, (Certificate[]) null ), perms );
AccessControlContext restrictedAccessControlContext = new AccessControlContext(new ProtectionDomain[] { domain } );
JexlEngine jexlEngine = new JexlEngine();
final Script finalExpression = jexlEngine.createScript(
"i = 0; intClazz = i.class; "
+ "clazz = intClazz.forName(\"java.lang.System\"); "
+ "m = clazz.methods; m[0].invoke(null, 1); c");
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
return finalExpression.execute(new MapContext());
}
}, restrictedAccessControlContext);
}
catch (Throwable ex) {
ex.printStackTrace();
}
下面是我如何实例化JetEngine的:
Log jexlLog = LogFactory.getLog("JEXL");
Map <String, Object> functions = new HashMap();
jexlEngine = new JexlEngine(new MyUberspectImpl(jexlLog), new MyJexlArithmetic(false), functions, jexlLog);
Log jexlLog=LogFactory.getLog(“JEXL”);
Map functions=newhashmap();
jexlEngine=新的jexlEngine(新的myuberceppectmpl(jexlLog)、新的myjexl算法(false)、函数、jexlLog);
如何处理forName
可能利用脚本达到恶意目的的情况?Uberspect也没有帮助。或者可能是我用错了。我创建了一个具有自定义Uberspect类的JetEngine,但它从未验证.class
的使用情况。我将添加有关我的实现的更多信息。此外,我确信我使用的JEXL版本比您的版本旧得多。
Log jexlLog = LogFactory.getLog("JEXL");
Map <String, Object> functions = new HashMap();
jexlEngine = new JexlEngine(new MyUberspectImpl(jexlLog), new MyJexlArithmetic(false), functions, jexlLog);