Как запустить Javascript с помощью Rhino для Java в песочнице?
Часть нашего приложения Java должна запускать javascript, который написан не разработчиками. Эти не-разработчики используют javascript для форматирования данных. (Простая логика и конкатенация строк в основном).
Мой вопрос заключается в том, как настроить выполнение этих сценариев, чтобы убедиться, что ошибки в сценариях не оказывают серьезного негативного влияния на остальную часть приложения.
- Нужно защищать от бесконечных циклов
- Охрана против появления новых потоков.
- Ограничить доступ к службам и среде
- Файловая система (пример: если недовольный script писатель решил удалить файлы)
- База данных (эта же вещь удаляет записи базы данных)
В основном мне нужно настроить область javascript, чтобы включать только то, что им нужно, и не более.
Ответы
Ответ 1
Чтобы защититься от бесконечных циклов, вам нужно поместить его в отдельный процесс, чтобы его можно было убить.
Чтобы защититься от создания потоков, вам необходимо расширить SecurityManager (реализация по умолчанию позволяет ненадежному коду получать доступ к группам без корневого потока).
Безопасность Java позволяет вам запретить доступ к файловой системе.
Для ограничений базы данных вы можете использовать стандартную безопасность SQL-пользователей, но это довольно слабо. В противном случае вам необходимо предоставить API, который будет выполнять ваши ограничения.
Изменить: я должен указать, что версия Rhino, поставляемая с JDK6, провела над ней работу по безопасности, но не включает компилятор.
Ответ 2
Чтобы защититься от бесконечных циклов, вы можете наблюдать за подсчетом команд как с запуском script (это работает только с интерпретируемыми скриптами, а не с скомпилированными).
В этом примере в Rhino JavaDocs предотвращается запуск script более десяти секунд:
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();
}
}
Ответ 3
Чтобы заблокировать доступ к классу Java и методам, посмотрите...
http://codeutopia.net/blog/2009/01/02/sandboxing-rhino-in-java/
Ответ 4
Я просто наткнулся на это сообщение в блоге, которое, по-видимому, полезно для песочницы более или менее всего (не только для носорога):
http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html
Ответ 5
Если вы ищете только функции только JavaScript, вот решение, основанное на встроенной библиотеке Rhino, встроенной в JDK, без импорта каких-либо сторонних библиотек:
- Найти JavaScript script engine factory имя класса с помощью ScriptEngineManager # getEngineFactories
- Загрузите класс script engine factory в новый загрузчик классов, в котором будут игнорироваться JavaMembers или другие связанные классы.
- Вызов #getScriptEngine в загруженном script engine factory и eval скриптах на возвращенном script двигателе.
Если данный script содержит Java script, загрузчик классов попытается загрузить JavaMembers или другие классы и вызвать исключение класса класса. Таким образом, злонамеренные скрипты будут игнорироваться без выполнения.
Подробнее читайте файлы ConfigJSParser.java и ConfigJSClassLoader.java:
https://github.com/webuzz/simpleconfig/tree/master/src/im/webuzz/config
Ответ 6
Javascript является однопоточным и не может получить доступ к файловой системе, поэтому я не думаю, что вам нужно беспокоиться об этом. Я не уверен, есть ли способ установить тайм-аут для защиты от бесконечных циклов, но вы всегда можете порождать (Java) поток, который выполняет script, а затем убивать поток через столько времени.