2013-06-04 16 views
5

Piszę aplikację i chcę, aby użytkownicy mogli wprowadzać pliki Pythona dla przypadków narożnych. W mojej głowie najlepszym sposobem na zrobienie tego jest zapisanie ich pliku na dysku i zapisanie lokalizacji w DB, a następnie dynamiczne zaimportowanie go za pomocą __import__(), a następnie wykonanie go. Pierwsza część mojego pytania brzmi: czy to najlepszy sposób na zrobienie tego?Dynamiczne odczytywanie w pliku Pythona i wykonywanie go bezpiecznie

Podnosi to również poważne obawy związane z bezpieczeństwem. Czy istnieje sposób, aby uruchomić swój moduł pod ograniczeniem? Aby nie pozwolić mu zobaczyć systemu plików czy czegokolwiek?

Edit:

Realizacja pytona byłoby pobierać dane z usług zaplecza, która jest poza zakresem „normalne”, więc nie byłoby pełne zastosowanie. Może to być definicja niestandardowego protokołu.

+2

http://wiki.python.org/moin/SandboxedPython ... Postawiłem to jako odpowiedź ... ale naprawdę po prostu przeczytaj ten artykuł ... –

Odpowiedz

3

Możesz użyć kombinacji wbudowanych compile i exec do wykonywania w pamięci. Minusem jest to, że nie otrzymujesz linii źródłowych w tracebacku.

Nie ma zbyt wiele nadziei na bezpieczeństwo. Nawet jeśli umieścisz absurdalnie restrykcyjne filtry, np. Ograniczając wszystko do pojedynczego wyrażenia i usuwając większość wbudowanych funkcji, arbitrary code can be executed. Zakaz dostępu do systemu plików lub dostępu do innych zasobów systemu operacyjnego również jest trudny w Pythonie, ponieważ kod byłby uruchamiany w tym samym procesie. Proces potomny z surowymi ograniczeniami (chroot więzienie, ulimit, itp.) Jest możliwe, ale to nie tylko dużo pracy, ale także wyklucza większość środków interakcji z aplikacją hosta.

Jeśli aplikacja działa lokalnie i ma takie same uprawnienia, jak konto użytkownika, najlepiej jest nie martwić się i dać im więcej mocy, ponieważ nie mogą zrobić niczego/wiele, czego i tak nie mogliby zrobić, i większość ograniczeń sprawiłoby, że zadanie (cokolwiek by to nie było) stało się trudniejsze/bardziej irytujące. Jeśli, z drugiej strony, kod zostałby wykonany na serwerze lub czymś, zapomnij o uruchomieniu go w tym samym procesie.

+0

Jestem myślę, że może odradzać piaskownicę instancję jvm i uruchamiać jython. W ten sposób mogę wziąć kod użytkownika w coś więcej niż tylko python. Czy to ma sens? Natknąłem się również na [pysandbox] (https://github.com/haypo/pysandbox), ale nie jestem pewien, jak jest to uzasadnione. –

+0

@ sir_charles804 Dźwięki są możliwe. Byłbym jednak zmęczony toczeniem czegoś takiego, co jest wielką szansą na zepsucie. Powiedział, że również dokładnie sprawdziłbym, czy jakikolwiek projekt strony trzeciej to robi (np. 'Pysandbox'). – delnan

+0

Zgadzam się. Myślę, że jeśli to zrobię, będzie to z VM. W ten sposób ufam kontenerem.Nie zdecydowałem, że w ten sposób pozwolę użytkownikom określać połączenia w przypadku narożników lub jeszcze nie, ale Twój wkład był bardzo pomocny. Dzięki! –

0

Można rozważyć następujące metody

class _DynamicModule(object): 
    def __init__(self, name): 
     self._name = name 

    def load(self, code): 
     execdict = {'__builtins__': __builtins__} 
     exec compile(code, '<string>', 'exec') in execdict 
     for key in execdict: 
      if not key.startswith('_'): 
       if not isinstance(execdict[key], str): 
        execdict[key].__module__ = self._name 
       setattr(self, key, execdict[key]) 
     return self 

import sys 
sys.modules['dummy_modules'] = _DynamicModule('dummy_modules').load('print ("!")') 

ten wciąż ma bardzo duże obawy związane z bezpieczeństwem.

1

można zrobić kilka rzeczy, aby ograniczyć uprawnienia (patrz mój komentarz na OP)

ale naprawdę moje dwa centy ... po prostu dać każdemu użytkownikowi własnych VM (może AWS?) ... w ten sposób nie potrafią Zepsuć wiele ... i zawsze możesz po prostu ponownie go uruchomić ...

bardziej skomplikowanym podejściem (ale zapewne fajniejszym) byłoby użycie lex/yacc (w pythonie jego PLY) i zdefiniowanie własnego języka (który mógłby być ograniczony podzbiór python)

Powiązane problemy