Как вы можете запустить Javascript, используя Rhino для Java в песочнице?
Часть нашего java-приложения должна запускать javascript, написанный не разработчиками. Эти не разработчики используют JavaScript для форматирования данных. (Простая логика и в основном конкатенация строк).
Мой вопрос заключается в том, как настроить выполнение этих сценариев, чтобы ошибки сценариев не оказывали серьезного негативного влияния на остальную часть приложения.
- Нужно остерегаться бесконечных петель
- Остерегайтесь появления новых тем.
- Ограничить доступ к услугам и окружающей среде
- Файловая система (пример: если недовольный сценарист решил удалить файлы)
- База данных (то же самое, что удалить записи базы данных)
По сути, мне нужно настроить область JavaScript, чтобы включить только то, что им нужно, и не более.
6 ответов
Чтобы защититься от бесконечных циклов, вам нужно поместить его в отдельный процесс, чтобы его можно было убить.
Чтобы защититься от создания потоков, вам нужно расширить SecurityManager (реализация по умолчанию позволяет ненадежному коду получать доступ к группам потоков без полномочий root).
Безопасность Java позволяет вам запретить доступ к файловой системе.
Для ограничений базы данных вы можете использовать стандартную пользовательскую безопасность SQL, но она довольно слабая. В противном случае вам необходимо предоставить API, который обеспечивает соблюдение ваших ограничений.
Изменить: Я должен отметить, что версия Rhino, поставляемая с JDK6, была выполнена работа по безопасности, но не включает компилятор.
Чтобы защититься от бесконечных циклов, вы можете наблюдать за количеством команд во время выполнения скрипта (это работает только с интерпретированными скриптами, а не скомпилированными).
Этот пример в JavaDocs Rhino запрещает запуск сценария более десяти секунд:
protected void observeInstructionCount(Context cx, int instructionCount)
{
MyContext mcx = (MyContext)cx;
long currentTime = System.currentTimeMillis();
if (currentTime - mcx.startTime > 10*1000) {
// More then 10 seconds from Context creation time:
// it is time to stop the script.
// Throw Error instance to ensure that script will never
// get control back through catch or finally.
throw new Error();
}
}
Чтобы заблокировать доступ к классам и методам Java, взгляните на...
http://codeutopia.net/blog/2009/01/02/sandboxing-rhino-in-java/
Я только что наткнулся на это сообщение в блоге, которое, кажется, полезно для песочницы более или менее всего (не только Rhino):
http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html
Если вы ищете только чистые функции JavaScript, вот решение, основанное на встроенной в JDK библиотеке Rhino без импорта сторонних библиотек:
- Узнайте имя класса фабрики обработчика сценариев JavaScript по ScriptEngineManager#getEngineFactories
- Загрузите класс фабрики обработчика сценариев в новый загрузчик классов, в котором JavaMembers или другие связанные классы будут игнорироваться.
- Вызовите #getScriptEngine для загруженной фабрики обработчиков сценариев и eval скриптов для возвращенной обработчика скриптов.
Если данный скрипт содержит Java-скрипт, загрузчик классов попытается загрузить JavaMembers или другие классы и вызвать исключение исключений для класса. Таким образом, вредоносные скрипты будут игнорироваться без выполнения.
Пожалуйста, прочтите файлы ConfigJSParser.java и ConfigJSClassLoader.java для более подробной информации:
https://github.com/webuzz/simpleconfig/tree/master/src/im/webuzz/config
Javascript является однопоточным и не может получить доступ к файловой системе, поэтому я не думаю, что вам нужно беспокоиться об этом. Я не уверен, есть ли способ установить тайм-аут для защиты от бесконечных циклов, но вы всегда можете создать поток (Java), который выполняет сценарий, а затем убить поток через столько времени.