在SaaS应用程序中,我有一些模板用于生成通知电子邮件或某些HTML页面。到目前为止,我还没有使用百日咳,到目前为止所有模板都是硬编码的,但我很乐意改变它,以便应用程序的用户可以自己编辑这些模板。问题是如果我允许用户自己编辑模板,用户可能会调用任何Java方法,这将完全损害系统安全性。
百万美元可以“沙盒化”还是可以禁用用户编辑模板环境中所有危险的功能? (为了执行,模板只接收带有getter和setter或java.util.Map的POJO,因此调用模型上的方法不是问题)
最明显的问题是OGNL / SpringEL。这些表达的力量可能很大,但它们也非常危险。我只需要从模型中调用getter。所以我试着像这样实现我自己的表达式解析器(以下只是快速和肮脏的东西作为概念证明,它不是“完成”):
final TemplateEngine templateEngine = new TemplateEngine();
final StandardDialect dialect = new StandardDialect();
dialect.setExpressionParser(new IStandardExpressionParser() {
@Override
public IStandardExpression parseExpression(final IExpressionContext context, final String input) {
if (!input.startsWith("${") || !input.endsWith("}")) {
throw new IllegalArgumentException("Only variable expressions allowed, not " + input);
}
final String[] path = StringUtils.split(input.substring("${".length(), input.length() - "}".length()), '.');
return new IStandardExpression() {
@Override
public String getStringRepresentation() {
return "Variable " + Arrays.toString(path);
}
@Override
public Object execute(final IExpressionContext context) {
Object result = context.getVariable(path[0]);
for (int i = 1; i < path.length; i++) {
try {
result = BeanUtils.getProperty(result, path[i]);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new Error(e);
}
}
return result;
}
@Override
public Object execute(final IExpressionContext context, final StandardExpressionExecutionContext expContext) {
return execute(context);
}
};
}
});
templateEngine.setDialect(dialect);
System.out.println(templateEngine.process(
"<html xmlns:th=\"http://www.thymeleaf.org\"><p th:text=\"${someVar}\"></p></html>",
new Context(Locale.ENGLISH, Collections.singletonMap("someVar", "someValue"))
));
它看起来有效,但这还够吗?还是有其他安全漏洞?
答案 0 :(得分:0)
我认为使用Java Security Manager可以更好地解决您的用例。您将能够为负责加载,解析和解释用户模板的代码提供非常狭窄的权限。