Подтвердить что ты не робот

Подходящий язык для запуска кода клиента в песочнице

Я хочу имитировать (небезопасный) клиентский код на моем сервере, и я ищу подходящий язык для этого. Я бы предпочел, чтобы клиенты писали на том же языке, что и для имитации.

  • Безопасность является основной задачей
  • желательно хорошо известный язык (легко для клиентов изучить синтаксис)
  • должно быть легко отключить/включить языковые функции, используемые в песочнице
  • будет плюсом, если я смогу реально имитировать код шаг за шагом

В идеале я бы просто построил несколько интерфейсов (и опубликовал их), загрузил код клиентов и смоделировал этот код, разрешив ему использовать только мои интерфейсы + подмножество стандартного API, который я тщательно выбрал.

Во время этого моделирования я должен иметь возможность ограничить ресурсы (время и память), используемые кодом клиентов. Бонус был бы, если бы я мог имитировать код шаг за шагом, таким образом я всегда мог бы вернуть детерминированное решение.

Производительность на самом деле не проблема. Идея состоит в том, чтобы позволить клиентам писать пользовательский ИИ для небольшой игры/головоломки. Игра будет смоделирована (на сервере!), А результат будет возвращен пользователю.

Первоначально я думал о создании внешнего DSL самостоятельно, включая анализатор и оценщик, но, возможно, есть готовое к использованию решение?

4b9b3361

Ответ 1

Моим вариантом было бы использовать некоторые языки сценариев, которые можно использовать без автоматического предоставления доступа к некоторой расширенной структуре (например,.Net или Java) - проще добавлять функции, чем ограничивать их. Язык сценариев игрового движка, например LUA, может быть вариантом и обычно поставляется с реализациями для использования несколькими платформами.

Общие соображения:

Независимо от выбранного языка/структуры, убедитесь, что вы можете восстановить/принять риск:

  • фатальные исключения (например, переполнение стека из-за рекурсивных функций)
  • неограниченные выделения памяти/исключения из памяти
  • длинные задачи

Остерегайтесь разоблачения API-интерфейсов, которые позволяют пользователям создавать новые потоки/задачи/объекты синхронизации (блокировки/семафоры) вне вашего контроля или строить на платформе, которая предоставляет такой API. Разрешение таких методов может открыть ресурсы вашего сервера для неограниченного потребления или DOS/взаимоблокировок...

Обратите внимание, что задачи с длительным запуском - проблема с любым разумным языком, так как вы не можете определить, заканчивается ли программа, глядя на нее - проблема с остановкой. Вы должны найти решение независимо от того, какую платформу вы выберете.

.Net/С#:

Вы можете проверить Terrarium, который делает именно это .Net - запуск ненадежного кода на пользовательском компьютере в изолированной среде.

.Net предоставляет способ ограничить использование нескольких API-интерфейсов - Практическое руководство. Запуск частично доверенного кода в песочнице является хорошей отправной точкой. Обратите внимание, что, как указывает @Andrew, рекомендуется проверить, не содержит ли сборка, предоставленная пользователем (напрямую или скомпилированная из пользовательских источников) API, которые вам не нравятся (или даже наоборот), использует только API-интерфейсы что вы разрешаете) в дополнение к базовой песочнице. Частично доверенный код, запущенный в отдельном AppDomain, дает вам хорошую защиту от не слишком враждебного кода.

Переполнение стека трудно предотвратить вообще и требует, чтобы пользовательский хост обрабатывал .Net. Долгосрочные задачи могут быть завершены с помощью Thread.Abort или закрытия AppDomain с кодом пользователя.

Ответ 2

Я бы порекомендовал .NET(С#, VB и F #). Вы можете воспользоваться JIT, чтобы сервер программно компилировал код, использовал отражение для его анализа и каждый клиент запускался в отдельном AppDomain для защиты и изоляции кода.

Ответ 3

Java имеет концепцию SecurityManager, которая позволяет вам точно настроить то, что может или не может быть запущено на вашей виртуальной машине.

Он также позволяет compile код и load результирующие классы во время выполнения. Затем вы можете запустить любой код в этих классах, если SecurityManager не выдает исключение SecurityException, потому что операция не разрешена.

Этот пост показывает надуманный пример, который компилирует, загружает и запускает некоторый код (предоставляется как текстовый исходный код) во время выполнения.

В этом другом сообщении даны указания для запуска ненадежного (и потенциально злонамеренного) кода.

Ответ 4

Если вы хотите запустить код, предоставленный конечными пользователями, и хотите, чтобы он использовал язык, который, вероятно, уже знает, почему бы не JavaScript?

Это возможно для песочницы JavaScript в WebWorker (параллельный поток, который изолирован от основного приложения JavaScript и не имеет доступа к общей памяти или глобальным объектам, таким как объект Window и DOM, и только один канал для связи с основным нить).

Единственная проблема с безопасностью, о которой я могу думать, будет ограничивать аппаратные ресурсы, потребляемые одним, но я не смотрел на это - это может быть очень возможно с одной из версий JavaScript. Вы также хотели бы найти способ не допустить, чтобы один WebWorker не создавал дополнительных. Вы должны добавить дополнительный код, чтобы убедиться, что кто-то WebWorker автоматически отключается через определенное время.

Я еще не пробовал серверные WebWorkers, но из-за его внешнего вида NodeJS, Rhino и PhantomJS все поддерживают его. Node и Rhino предоставляют разные среды, чем обычный веб-браузер, в то время как PhantomJS - это полный браузер (WebKit), работающий без головы. С точки зрения WebWorker они, вероятно, будут выглядеть одинаково.

Ответ 5

Если вы действительно хотите "хорошо знать", ADsafe является подмножеством JavaScript, который эффективно изолирован, хотя у него есть несколько причуд ( например, избегая this).

В Java есть "загрузчики классов", которые могут ограничивать классы, к которым имеет доступ класс (см. SecureClassLoader). Я немного туманна в деталях, но это, по сути, то, что использовалось для обеспечения безопасности Java-апплета. Я не знаю, может ли это ограничить использование памяти, но ограничение времени процессора не является слишком сложным (не позволяйте ему запускать потоки и убивать поток, выполняющий ненадежный код после таймаута).

(Я с любовью напоминаю Robocode, в котором выполняется ненадежный ИИ, пытающийся убить другого ненадежного ИИ в пределах ограничений игры. разница в том, что он предназначался для работы на компьютерах конечных пользователей, хотя были сайты, занимающиеся автоматическим ранжированием. Это было мое введение в Java, хотя я отмечаю, что теперь он поддерживает .NET, вероятно, из-за сходства двух языков. )