Zastanawiam się, czy możliwe jest piaskownica JavaScript działająca w przeglądarce, aby uniemożliwić dostęp do funkcji, które są normalnie dostępne dla kodu JavaScript działającego na stronie HTML.
Na przykład, powiedzmy, że chcę zapewnić użytkownikom końcowym JavaScript API, aby umożliwić im zdefiniowanie programów obsługi zdarzeń, które mają być uruchamiane, gdy wystąpią „interesujące zdarzenia”, ale nie chcę, aby ci użytkownicy mieli dostęp do właściwości i funkcji window
obiektu. Czy jestem w stanie to zrobić?
W najprostszym przypadku powiedzmy, że chcę uniemożliwić użytkownikom dzwonienie alert
. Oto kilka podejść, które przychodzą mi do głowy:
window.alert
Globalnie przedefiniuj . Nie sądzę, żeby to było właściwe podejście, ponieważ inny kod działający na stronie (tj. Rzeczy, które nie zostały utworzone przez użytkowników w ich programach obsługi zdarzeń) mogą chcieć użyćalert
.- Wyślij kod obsługi zdarzeń do serwera w celu przetworzenia. Nie jestem pewien, czy wysłanie kodu do serwera w celu przetworzenia jest właściwym podejściem, ponieważ programy obsługi zdarzeń muszą działać w kontekście strony.
Być może rozwiązanie, w którym serwer przetwarza funkcję zdefiniowaną przez użytkownika, a następnie generuje wywołanie zwrotne do wykonania na kliencie, zadziała? Nawet jeśli to podejście działa, czy istnieją lepsze sposoby rozwiązania tego problemu?
źródło
while (1) {}
--- po prostu się zawiesza. Podobniea=[]; while (1) { a=[a,a]; }
.Spójrz na ADsafe Douglasa Crockforda :
Możesz zobaczyć przykład korzystania z ADsafe, przeglądając pliki
template.html
itemplate.js
w repozytorium GitHub projektu .źródło
this
, który jest całkowicie nie do przyjęcia. Nie możesz napisać dobrego javascript bez użyciathis
.this
. Nie jest trudno uniknąć źle nazwanego parametru.this
istnieje równy, równoważnythis
sposób, aby to zrobić (w końcu jest to tylko parametr).Stworzyłem bibliotekę piaskownicy o nazwie jsandbox, która wykorzystuje pracowników sieci do oceny kodu w piaskownicy. Posiada również metodę wejściową do jawnego podawania danych kodu w trybie piaskownicy, których w innym przypadku nie byłby w stanie uzyskać.
Poniżej znajduje się przykład interfejsu API:
źródło
Myślę, że warto tu wspomnieć o js.js. To interpreter JavaScript napisany w JavaScript.
Jest około 200 razy wolniejszy niż natywny JS, ale jego natura sprawia, że jest idealnym środowiskiem piaskownicy. Inną wadą jest jego rozmiar - prawie 600 kb, co w niektórych przypadkach może być akceptowalne dla komputerów stacjonarnych, ale nie dla urządzeń mobilnych.
źródło
Jak wspomniano w innych odpowiedziach, wystarczy uwięzić kod w piaskownicy iframe (bez wysyłania go na serwer) i komunikować się z wiadomościami. Proponuję przyjrzeć się małej bibliotece, którą stworzyłem głównie ze względu na potrzebę udostępnienia jakiegoś API do niezaufanego kodu, tak jak opisano w pytaniu: istnieje możliwość wyeksportowania określonego zestawu funkcji bezpośrednio do piaskownicy, gdzie niezaufany kod zostanie uruchomiony. Jest też demo, które wykonuje kod przesłany przez użytkownika w piaskownicy:
http://asvd.github.io/jailed/demos/web/console/
źródło
Wszyscy dostawcy przeglądarek i specyfikacja HTML5 pracują nad rzeczywistą właściwością piaskownicy, aby umożliwić korzystanie z elementów iframe w piaskownicy - ale nadal jest to ograniczone do szczegółowości elementów iframe.
Ogólnie rzecz biorąc, żaden poziom wyrażeń regularnych itp. Nie może bezpiecznie oczyścić dowolnego JavaScript dostarczonego przez użytkownika, ponieważ degeneruje się on do problemu zatrzymania: - /
źródło
Ulepszona wersja kodu piaskownicy dla pracowników sieci @ RyanOHara, w jednym pliku (nie
eval.js
jest potrzebny żaden dodatkowy plik).Sprawdź to:
https://jsfiddle.net/kp0cq6yw/
Powinien się wyświetlać
6
(testowane w Chrome i Firefox).źródło
Brzydki sposób, ale może to działa dla ciebie, wziąłem wszystkie globale i przedefiniowałem je w zakresie piaskownicy, a także dodałem tryb ścisły, aby nie mogli uzyskać obiektu globalnego za pomocą funkcji anonimowej.
https://gist.github.com/alejandrolechuga/9381781
źródło
window
z tego wrócić.sandboxcode('console.log((0,eval)("this"))')
function sbx(s,p) {e = eval; eval = function(t){console.log("GOT GOOD")}; sandboxcode(s,p); eval =e}
(_=>_).constructor('return this')()
Niezależny interpreter JavaScript z większym prawdopodobieństwem zapewni solidną piaskownicę niż wersję implementacji wbudowanej przeglądarki w klatce. Ryan już wspomniał o js.js , ale bardziej aktualnym projektem jest JS-Interpreter . W docs pokrycie jak wystawiać różne funkcje do tłumacza, ale jego zakres jest inaczej bardzo ograniczony.
źródło
Od 2019 roku vm2 wygląda na najpopularniejsze i najczęściej aktualizowane rozwiązanie tego problemu.
źródło
Dzięki NISP będziesz mógł przeprowadzić ocenę w piaskownicy. Chociaż napisane wyrażenie nie jest dokładnie JS, zamiast tego napiszesz s-wyrażenia. Idealny do prostych DSL, które nie wymagają rozbudowanego programowania.
źródło
1) Załóżmy, że masz kod do wykonania:
Teraz przypuśćmy, że chcesz wykonać to w piaskownicy:
Te dwa wiersze po wykonaniu zakończą się niepowodzeniem, ponieważ funkcja „alert” nie jest dostępna z poziomu „piaskownicy”
2) A teraz chcesz udostępnić element członkowski obiektu window ze swoją funkcjonalnością:
Rzeczywiście, możesz dodać cudzysłowy i zrobić inne polerowanie, ale myślę, że pomysł jest jasny.
źródło
Skąd pochodzi JavaScript użytkownika?
Niewiele można zrobić, aby użytkownik osadził kod na swojej stronie, a następnie wywołał go z przeglądarki (patrz Greasemonkey, http://www.greasespot.net/ ). Robią to tylko przeglądarki.
Jeśli jednak przechowujesz skrypt w bazie danych, a następnie pobierzesz go i przeprowadzisz eval (), możesz wyczyścić skrypt przed jego uruchomieniem.
Przykłady kodu, który usuwa wszystkie okna. i dokument. Bibliografia:
Ma to na celu zapobieżenie wykonaniu następujących czynności (nie przetestowano):
Istnieje wiele ograniczeń, które musiałbyś zastosować do niebezpiecznego skryptu użytkownika. Niestety dla JavaScript nie jest dostępny żaden „kontener piaskownicy”.
źródło
Pracowałem nad uproszczoną piaskownicą js, aby umożliwić użytkownikom tworzenie apletów dla mojej witryny. Chociaż nadal napotykam pewne wyzwania związane z zezwoleniem na dostęp do DOM (parentNode po prostu nie pozwala mi zachować bezpieczeństwa = /), moim podejściem było po prostu przedefiniowanie obiektu okna z niektórymi jego użytecznymi / nieszkodliwymi składnikami, a następnie eval () użytkownika kod z tym ponownie zdefiniowanym oknem jako domyślnym zakresem.
Mój „podstawowy” kod wygląda tak ... (nie pokazuję go całkowicie;)
Mogę więc utworzyć instancję Sandbox i użyć jej funkcji execute (), aby uruchomić kod. Ponadto wszystkie nowe zadeklarowane zmienne w kodzie eval'd ostatecznie będą powiązane z zakresem execute (), więc nie będzie kolidujących nazw ani bałaganu z istniejącym kodem.
Chociaż obiekty globalne będą nadal dostępne, te, które powinny pozostać nieznane w kodzie piaskownicy, muszą być zdefiniowane jako proxy w obiekcie Sandbox :: scope.
Mam nadzieję, że to działa dla Ciebie.
źródło
Możesz opakować kod użytkownika w funkcję, która na nowo definiuje zabronione obiekty jako parametry - byłyby wtedy
undefined
wywołane:Oczywiście sprytni napastnicy mogą obejść ten problem, sprawdzając Javascript DOM i znajdując niezamknięty obiekt, który zawiera odniesienie do okna.
Innym pomysłem jest skanowanie kodu użytkownika za pomocą narzędzia takiego jak jslint . Upewnij się, że nie ma predefiniowanych zmiennych (lub: tylko zmienne, które chcesz), a następnie, jeśli są ustawione lub dostępne jakiekolwiek zmienne globalne, nie pozwól na użycie skryptu użytkownika. Ponownie, może być podatny na chodzenie po DOM - obiekty, które użytkownik może skonstruować za pomocą literałów, mogą mieć niejawne odniesienia do obiektu okna, do którego można uzyskać dostęp, aby uciec z piaskownicy.
źródło