Pytanie Odpowiedni język do uruchamiania kodu klienta w piaskownicy


Chcę symulować (niebezpieczny) kod klienta na moim serwerze i szukam odpowiedniego języka, aby to zrobić. Wolałbym, aby klienci pisali w tym samym języku, w którym będę używał do symulacji.

  • bezpieczeństwo jest główną troską
  • najlepiej dobrze znany język (łatwy dla klientów do nauki składni)
  • powinno być łatwe do wyłączenia / włączenia funkcji językowych przydatnych w piaskownicy
  • byłby plus, gdybym mógł symulować kod krok po kroku

Idealnie byłoby po prostu skonstruować kilka interfejsów (i opublikować je), załadować kod klienta i zasymulować ten kod, pozwalając mu używać tylko moich interfejsów + podzestaw standardowego interfejsu API, który starannie wybrałem.

Podczas tej symulacji powinienem móc ograniczyć zasoby (czas i pamięć) używane przez kod klienta. Bonus byłby, gdybym mógł symulować kod krok po kroku, w ten sposób zawsze mogłem zwrócić deterministyczne rozwiązanie.

Wydajność nie jest tak naprawdę problemem. Pomysł polega na umożliwieniu klientom napisania niestandardowej sztucznej inteligencji dla małej gry / układanki. Gra zostanie zasymulowana (na serwerze!), A wynik zostanie zwrócony użytkownikowi.

Początkowo zastanawiałem się nad skonstruowaniem zewnętrznego DSL, w tym parsera i ewaluatora, ale być może istnieje gotowe do użycia rozwiązanie?


12
2018-01-21 02:20


pochodzenie




Odpowiedzi:


Moim wyborem jest użycie języka skryptowego, który może być używany bez automatycznego udostępniania dostępu do obszernej struktury (takiej jak .Net lub Java) - łatwiej jest dodawać funkcje, niż je ograniczać. Języki skryptów silnika gier, takie jak LUA może być opcjonalną opcją i zwykle zawiera implementacje dla wielu platform, które mogą z nich korzystać.

Uwagi ogólne:

Niezależnie od wybranego języka / frameworku, upewnij się, że możesz odzyskać / zaakceptować ryzyko:

  • krytyczne wyjątki (takie jak przepełnienie stosu spowodowane funkcjami rekursywnymi)
  • nielimitowane alokacje pamięci / wyjątki pamięci
  • długo działające zadania

Uważaj na eksponowanie interfejsów API, które umożliwiają użytkownikom tworzenie nowych obiektów wątków / zadań / synchronizacji (blokad / semaforów) poza kontrolą lub budowanie na platformie zapewniającej takie API. Pozwolenie na takie metody może otworzyć zasoby twojego serwera na nieograniczoną konsumpcję lub DOS / zakleszczenia ...

Zauważ, że długie zadania są problemem z każdym rozsądnym językiem, ponieważ nie możesz ustalić, czy program kiedykolwiek się kończy, patrząc na niego - problem z zatrzymaniem. Musisz znaleźć rozwiązanie bez względu na wybraną platformę.

.Net / C #:

Możesz sprawdzić Terrarium co robi dokładnie to w .Net - uruchamianie niezaufanego kodu na komputerze użytkownika w środowisku piaskownicy.

.Net zapewnia sposób na ograniczenie korzystania z wielu interfejsów API - Jak: uruchomić częściowo zaufany kod w piaskownicy to dobry punkt wyjścia. Zauważ, że jak zauważa @Andrew, warto sprawdzić, czy zestaw dostarczony przez użytkownika (bezpośrednio lub skompilowany ze źródeł użytkownika) nie korzysta z interfejsów API, których nie lubisz (lub odwrotnie - używa tylko interfejsów API) na które zezwolisz) oprócz podstawowej piaskownicy. Częściowo zaufany kod działający w osobnej domenie AppDomain zapewnia ochronę przed nieprzyjaznym kodem.

Przepełnienie stosu Trudno ogólnie zapobiegać i wymagać niestandardowego hosta do obsługi w .Net. Długotrwałe zadania można zakończyć za pomocą wątku. Przerywanie lub wyłączanie AppDomain za pomocą kodu użytkownika.


3
2018-01-31 06:24





Polecam .NET (C #, VB i F #). Możesz skorzystać z JIT, aby mieć programowo skompilowany kod serwera, użyć refleksji do analizy i kazać każdemu klientowi działać w oddzielnym AppDomain dla bezpieczeństwa i izolacji kodu.


1
2018-01-27 00:30



Chciałbym uniknąć konieczności użycia refleksji nad dostarczonym kodem. Miałem nadzieję, że znajdę język / środowisko, które po prostu skompiluje kod dla mnie, sprawdzając, czy spełnia moje ograniczenia i odrzuca lub akceptuje ten fragment kodu. Zaakceptowany kod powinien być bezpieczny do uruchomienia (tyle razy ile lubię). - Antiz
.NET pozwala programowo skompilować twój kod. Sądzę, że możesz również dodać atrybuty bezpieczeństwa do swojej klasy abstrakcyjnej, co powinno również pozwolić na pewną kontrolę. - Andrew
AppDomains wyglądają interesująco, mając nadzieję, że inne osoby z doświadczeniem mogą wpaść w wasze opinie. - Antiz
+1. Dodałem więcej linków .Net w moim poście. Zauważ, że "odbicie" wydaje się być używane w szerszej perspektywie - do analizy skompilowanego kodu potrzebny jest czytnik IL. - Alexei Levenkov


Java ma koncepcję Menadżer ochrony co pozwala precyzyjnie dostroić to, co może lub nie może być uruchomione na maszynie wirtualnej.

Pozwala również na skompilować kod i obciążenie wynikowe klasy w czasie wykonywania. Następnie można uruchomić dowolny kod w tych klasach, pod warunkiem, że menedżer zabezpieczeń nie rzuci wyjątku SecurityException, ponieważ operacja nie jest dozwolona.

Ten post pokazuje przykład, który kompiluje, ładuje i uruchamia pewien kod (dostarczony jako tekstowy kod źródłowy) w czasie wykonywania.

Ten inny post podaje wskazówki, jak uruchomić niezaufany (i potencjalnie złośliwy) kod.


1
2018-01-30 16:03



+1. Czy mógłbyś sprawdzić / skomentować, czy problemy, o których wspomniałem w mojej odpowiedzi (SO, OOM, długo działający kod ...) mają zastosowanie w przypadku Java i jak sobie z nimi radzisz? - Alexei Levenkov
SO i OOM mogą zostać przechwycone w bloku catch all, który opuszcza wątek z obcym kodem i zwalnia zasoby. Długie działanie kodu może być nieco bardziej problematyczne, jeśli uruchomimy go w innym wątku w obrębie tej samej maszyny JVM (Java tak naprawdę nie zapewnia mechanizmu "zabicia" wątku) - ale jeśli jest to ryzyko, kod może być uruchamiany w innym procesie (tj. inna JVM), w którym to przypadku proste wywołanie systemu operacyjnego może zabić ten inny proces. - assylias


Jeśli chcesz uruchomić kod dostarczony przez użytkowników końcowych i chcesz, aby używał języka, który prawdopodobnie już znają, dlaczego nie JavaScript?

Możliwe jest piaskowanie JavaScriptu w WebWorker (wątek równoczesny, który jest odizolowany od głównej aplikacji JavaScript i nie ma dostępu do pamięci współużytkowanej lub globalnych, takich jak obiekt Window i DOM, i tylko jedna droga do komunikacji z głównym wątkiem).

Jedyny problem z bezpieczeństwem, jaki mogę sobie wyobrazić, to ograniczenie zasobów sprzętowych zużywanych przez jeden, ale nie przyjrzałem się temu - może być to bardzo możliwe z jednym z programów wykonawczych JavaScript. Chciałbyś także znaleźć sposób, aby uniemożliwić jednemu z Webworkerów tworzenie dodatkowych. Będziesz musiał dodać dodatkowy kod, aby upewnić się, że czyjś program WebWorker zostanie automatycznie wyłączony po pewnym czasie.

Jeszcze nie próbowałem serwerów WebWorkers, ale z jego wyglądu NodeJS, Rhino i PhantomJS wszystkie go obsługują. Node i Rhino zapewniają różne środowiska niż typowa przeglądarka internetowa, podczas gdy PhantomJS jest pełnym silnikiem przeglądarki (WebKit) działającym bezgłosu. Z perspektywy WebWorkera prawdopodobnie wszystkie wyglądałyby tak samo.


1
2018-01-31 17:59



Ponadto, jeśli chcesz mieć dodatkowe piaskownice na samych WebWorkers, Rhino uruchamia cały silnik JavaScript w piaskownicy JVM. - Richard Connamacher
W rzeczy samej. Takie rzeczy, jak program SecurityManager, mogą być używane do dodawania dodatkowego poziomu izolacji wokół skryptowanego kodu. Dużą zaletą jest to, że oprócz samych skryptów większość kodu można napisać w języku mocno napisanym, co jest prawdziwym plusem dla większych projektów, takich jak gry z niestandardową sztuczną sztuczną inteligencją. +1 - Stijn de Witt


Jeśli naprawdę chcesz "dobrze znany", ADsafe jest podzbiorem JavaScript, który jest efektywnie piaskowany, choć ma kilka dziwactw (np. unikanie) this).

Java ma "ładowniki klas", które mogą ograniczać klasy, do których klasa ma dostęp (zob SecureClassLoader). Jestem trochę niejasny w szczegółach, ale zasadniczo to, co jest używane do zapewnienia bezpieczeństwa apletów Java. Nie wiem, czy może ograniczyć wykorzystanie pamięci, ale ograniczenie czasu procesora nie jest zbyt trudne (nie pozwól, aby odrodziło się wątki i zabił wątek z niezaufanym kodem po przekroczeniu limitu czasu).

(Czuję, jak mi się podobało Robocode który uruchamia niezaufaną sztuczną inteligencję próbującą zabić inną niezaufaną sztuczną inteligencję w ramach ograniczeń gry. Główną różnicą jest to, że miała ona działać na komputerach użytkowników końcowych, chociaż witryny były zautomatyzowane. To było moje wprowadzenie do Javy, choć zauważam, że obsługuje teraz .NET, prawdopodobnie ze względu na podobieństwo dwóch języków.)


0
2018-01-27 01:57



Robocode rzeczywiście wygląda bardzo podobnie do tego, co próbuję zrobić, ale jest już nieco bardziej zaawansowany. Wątpię, czy mogę wyłączyć konstrukcje takie jak "while", "foreach" itp. W Java Java, prawda? ADsafe jest interesujący, ale wydaje mi się, że jest bardziej odpowiedni do przetwarzania DOM, a nie do interakcji z niestandardowymi interfejsami, które zdefiniowałem. Ale mogę się mylić. - Antiz