Piaskownica w Pythonie jest trudna . Python jest z natury introspektywny na wielu poziomach.
Oznacza to również, że możesz znaleźć metody fabryczne dla konkretnych typów z tych samych typów i zbudować nowe obiekty niskiego poziomu, które będą uruchamiane bezpośrednio przez interpretera bez ograniczeń.
Oto kilka przykładów znalezienia kreatywnych sposobów na wyjście z piaskownicy Python:
Podstawową ideą jest zawsze znalezienie sposobu na stworzenie podstawowych typów Pythona; funkcje i klasy oraz wyrwać się z powłoki, zmuszając interpreter języka Python do wykonania dowolnego (niezaznaczonego!) kodu bajtowego.
To samo i więcej dotyczy exec
instrukcji ( exec()
funkcja w Pythonie 3).
Więc chcesz:
Ściśle kontrolować kompilację bajtów kodu Pythona lub przynajmniej przetworzyć kod bajtowy, aby usunąć dostęp do nazw zaczynających się od podkreślników.
Wymaga to dokładnej wiedzy na temat działania interpretera języka Python i struktury kodu bajtowego Pythona. Obiekty kodu są zagnieżdżone; kod bajtowy modułu obejmuje tylko najwyższy poziom instrukcji, każda funkcja i klasa składa się z własnej sekwencji kodu bajtowego oraz metadanych, zawierających na przykład inne obiekty kodu bajtowego dla zagnieżdżonych funkcji i klas.
Musisz dodać do białej listy moduły, których można użyć. Ostrożnie.
Moduł python zawiera odniesienia do innych modułów. Po zaimportowaniu w przestrzeni nazw modułu os
znajduje się nazwa lokalna, os
która odnosi się do os
modułu. Może to doprowadzić zdeterminowanego napastnika do modułów, które pomogą im wydostać się z piaskownicy. Na pickle
przykład moduł pozwala na przykład ładować dowolne obiekty kodu, więc jeśli jakakolwiek ścieżka prowadząca do modułów z białej listy prowadzi do pickle
modułu, problem nadal występuje.
Musisz ściśle ograniczyć limity czasowe. Nawet najbardziej neutralny kod może nadal próbować działać wiecznie, wiążąc zasoby.
Spójrz na RestrictedPython , który próbuje zapewnić ci ścisłą kontrolę kodu bajtowego. RestrictedPython
przekształca kod Pythona w coś, co pozwala kontrolować, jakie nazwy, moduły i obiekty są dozwolone w Pythonie od 2.3 do 2.7.
Jeśli RestrictedPython
jest wystarczająco bezpieczny dla Twoich celów, zależy od wdrażanych zasad. Niedopuszczenie do dostępu do nazw zaczynających się od podkreślenia i ścisłej białej listy modułów byłoby początkiem.
Moim zdaniem jedyną naprawdę solidną opcją jest użycie oddzielnej maszyny wirtualnej, która nie ma dostępu do sieci do świata zewnętrznego, który niszczysz po każdym uruchomieniu. Zamiast tego każdy nowy skrypt otrzymuje nową maszynę wirtualną. W ten sposób nawet jeśli kodowi uda się wyrwać z piaskownicy Pythona (co nie jest mało prawdopodobne), dostęp do atakującego jest krótkotrwały i bez wartości.