Kodowanie po stronie klienta: jak zapobiec złośliwemu użyciu?

60

W ostatnich latach trend aplikacji po stronie klienta (przeglądarki) naprawdę się rozwinął.

W moim najnowszym projekcie postanowiłem iść z duchem czasu i napisać aplikację po stronie klienta.

Część tej aplikacji obejmuje wysyłanie wiadomości e-mail dotyczących transakcji do użytkowników (na przykład sprawdzanie poprawności rejestracji, wiadomości e-mail dotyczące resetowania hasła itp.). Korzystam z interfejsu API innej firmy do wysyłania wiadomości e-mail.

Zwykle moja aplikacja działałaby na serwerze. Dzwonię do interfejsu API innej firmy z kodu na moim serwerze.

Uruchomienie aplikacji po stronie klienta oznacza, że ​​teraz musi to nastąpić w przeglądarce użytkownika. Interfejs API innej firmy zapewnia niezbędne pliki JavaScript do osiągnięcia tego celu.

Pierwszym rażącym problemem, jaki widzę, jest konieczność użycia klucza API. Zwykle byłoby to bezpiecznie przechowywane na moim serwerze, ale teraz prawdopodobnie będę musiał dostarczyć ten klucz do przeglądarki klienta.

Zakładając, że mogę obejść ten problem, następnym problemem jest to, co powstrzymuje doświadczonego technicznie użytkownika ładującego narzędzie programistyczne JavaScript w przeglądarce i używającego interfejsu API poczty e-mail, tak czy inaczej, zamiast mówić o przestrzeganiu reguł, które ustawiłem w aplikacji .

Wydaje mi się, że moim ogólnym pytaniem jest - w jaki sposób możemy zapobiec złośliwemu użyciu aplikacji po stronie klienta?

Gaz_Edge
źródło
24
Czy jest jakiś powód, dla którego ta aplikacja nie komunikuje się z własnym serwerem, a następnie serwer przesyła te żądania do dowolnej usługi zewnętrznej, z której chcesz skorzystać? (Wiele takich usług i tak zabroniłoby korzystania z nich w ten sposób)
Thorsten Müller
11
Dlatego klucze API są ostatecznie bezcelowe. Serwer nie powinien ufać aplikacji, która wysyła mu polecenia; powinien ufać tylko użytkownikowi.
Kevin Panko
42
Nie widziałem, żeby jakikolwiek rozsądny człowiek zdefiniował „aplikację po stronie klienta” jako „pod żadnym pozorem nigdy nie komunikuje się z serwerem” - wydaje się to bardziej słaby niż rozsądny argument. Oczywiście po stronie serwera trzeba poradzić sobie z pewnymi sprawami, ale zdecydowana większość działań może być wykonywana lokalnie bez problemów, co z kolei znacznie poprawi czas reakcji i skalowalność.
Voo
4
Gdzie widzisz nacisk na „Aplikacje tylko do przeglądania?” Nigdy nie widziałem czegoś takiego, co opisujesz, trzymania tajemnic w kodzie klienta w szalenie złym pomyśle, nawet najbardziej zagorzali faceci z frontonu, których znam, nigdy by tego nie zrobili.
Wheeyls,
2
Każda próba ochrony bezpiecznych zasobów po stronie klienta jest skazana na niepowodzenie, ponieważ narusza kilka niezmiennych praw bezpieczeństwa. # 2/3 - jeśli twoje oprogramowanie działa na twoim komputerze przeciwnika, z definicji nie jest to twój komputer i już go zgubiłeś. # 7 próba ochrony zasobu przez szyfrowanie jest skazana na niepowodzenie, ponieważ musisz także dostarczyć klientowi klucz deszyfrujący. # 10 żadna technologia nie może naprawić powyższego. blogs.technet.com/b/rhalbheer/archive/2011/06/16/…
Dan Neely

Odpowiedzi:

200

Nie możesz, a im więcej ludzie to rozumieją, i im głębiej rozumieją, tym lepiej dla świata.

Kod działający na urządzeniu kontrolowanym przez użytkownika nie może być kontrolowany. Smartfony mogą mieć jailbreak. Dekodery mogą być popękane. Zwykłe przeglądarki nawet nie próbują uniemożliwiać dostępu do kodu JavaScript. Jeśli masz coś, co warto ukraść lub nadużyć, zdeterminowany atakujący będzie mógł to zrobić, chyba że zweryfikujesz wszystko, co cenisz po stronie serwera.

Zaciemnianie jest bardzo mało pomocne; rodzaj przeciwnika, którego przyciągniesz, gdy tylko zdalnie zajmie się to finansowo, czyta język asemblera, jak ogłoszenia drobne. Szyfrowanie nie może ci pomóc, ponieważ urządzenie, które będzie pilnowało klucza, jest tym samym urządzeniem, co do którego musisz założyć, że jest pęknięte. Istnieje wiele innych, pozornie oczywistych środków zaradczych, które nie działają z podobnych powodów.

Niestety jest to bardzo niewygodna prawda. Świat jest pełen małych i dużych operatorów, którzy myślą, że mogą w jakiś sposób obejść fundamentalne zerwanie zdalnego zaufania, po prostu dlatego, że byłoby tak miło , gdybyśmy mogli założyć, że nasz kod będzie działał tak, jak zakładaliśmy. I tak, wszystko to byłoby o wiele łatwiejsze, że nawet nie jest śmieszne. Ale pragnienie tego nie czyni, a nadzieja wbrew nadziei, że jesteś jedynym inteligentnym ciasteczkiem, który może uniknąć nieprzyjemności, spali tylko ciebie i twoich klientów. Dlatego wejdź do sposobu myślenia, że ​​Internet jest terytorium wroga, uwzględnij ten dodatkowy koszt w swoich szacunkach, a wszystko będzie dobrze.

To powiedziawszy, oczywiście istnieje coś takiego jak głęboka obrona. Ukrywanie kodu JavaScript nie zniechęca zdecydowanego napastnika, ale może zniechęcić niektórych mniej zdeterminowanych atakujących. Jeśli twoje aktywa są wystarczające do ochrony, ale nie za wszelką cenę, którykolwiek z tych środków może zwiększyć wartość biznesową twojego systemu; to po prostu nie może być idealne. Tak długo, jak masz pełną świadomość kompromisów, może to być rozsądna strategia.

Kilian Foth
źródło
6
Ale z perspektywy czasu: dotyczy to KAŻDEGO oprogramowania, czy to systemu operacyjnego, czy transakcji. W końcu istnieje kilka bardzo dobrych zaciemniaczy kodu i możesz podnieść poprzeczkę najprawdopodobniej wystarczająco wysoko, jeśli nie ma natychmiastowej zachęty finansowej do włamania się do twojego oprogramowania!
Falco
5
W dzisiejszych czasach firmy podjęły groźbę działań prawnych przeciwko osobom, które włamują się do treści otrzymanych od nich przed przetwarzaniem (np. Za pomocą blokerów reklam). To tylko pokazuje, jak niemożliwe jest działanie techniczne .
Kilian Foth,
62
Jeśli mogę rozwinąć pierwsze dwa zdania, subtelność, której często brakuje ludziom, polega na tym, że aplikacje przeglądarki po stronie klienta mają na celu odciążenie. Twój serwer jest nadal odpowiedzialny za zaufane operacje, takie jak wysyłanie wiadomości e-mail lub dostęp do danych. Zlecenie klientowi renderowania wykresu z tych danych pozwala jednak zaoszczędzić czas procesora (i pieniądze) bez zmiany modelu bezpieczeństwa.
ssube
11
@Gaz_Edge Należy zauważyć, że problemem nie jest to, że aplikacje po stronie klienta są z natury niepewne. Problem polega na pisaniu tych aplikacji po stronie klienta w sposób wymagający zaufania klientowi informacji, których nie chcesz upubliczniać. Zupełnie możliwe jest napisanie aplikacji obciążającej klienta, która jest równie bezpieczna jak aplikacja, w której większość przetwarzania odbywa się na serwerze. (Więcej informacji na ten temat znajduje się w odpowiedzi
jhockinga
7
@ Ajedi32 Aplikacje po stronie klienta niepewne. Nie można zaprojektować bezpiecznej aplikacji, jeśli jakakolwiek logika wykonana po stronie klienta nie jest sprawdzona po stronie serwera. W tym momencie logika po stronie klienta zmienia się w interfejs użytkownika lub sposób na odciążenie podstawowych kontroli, ale wszystko musi zawsze zostać sprawdzone na serwerze !! .
69

Zasada jest następująca:

Rób wszystko, co po stronie klienta, co nie wpływa na nikogo innego, jeśli użytkownik manipuluje nim. W szczególności oznacza to efekty graficzne.

Zrób wszystko, co wymaga bezpieczeństwa po stronie serwera, i po prostu wyślij zdarzenia interfejsu użytkownika od klienta (np. Wtedy klient mówi „użytkownik nacisnął przycisk Kup”, podczas gdy serwer faktycznie przeprowadza transakcję). W szczególności oznacza to transakcje finansowe.

jhocking
źródło
28

Dokładnie tak jest, gdy uczynienie go całkowicie aplikacją po stronie klienta nie jest właściwe.

Możesz dokonać logiki i podstawowej weryfikacji formularzy po stronie klienta (nadal musisz dokonać ponownej walidacji na serwerze, ponieważ ktoś może próbować sfałszować żądanie), aby poprawić czas reakcji, możesz wykonywać żądania HTTP z JavaScript przekazujące dane tam iz powrotem w JSON do unikaj ponownego wysyłania ozdób stron i tym podobnych, ale jeśli sama transakcja wymaga uwierzytelnienia i autoryzacji, powinna ona nadal odbywać się na serwerze.

Jan Hudec
źródło
11
Uwaga: Chociaż sprawdzanie poprawności formularzy po stronie klienta jest świetne, nigdy nie zapomnij o sprawdzeniu ich także po stronie serwera! Do czasu wysłania kodu klienta do przeglądarki przestaje on być Twoim kodem! Musisz zweryfikować każdy bit, który wyśle ​​ponownie!
Josef
17

Twój środkowy akapit jest sednem problemu:

Uruchomienie aplikacji po stronie klienta oznacza, że ​​teraz musi to nastąpić w przeglądarce użytkownika. Interfejs API innej firmy zapewnia niezbędne pliki js, aby to osiągnąć.

Dlaczego aplikacja po stronie klienta oznacza, że ​​nie możesz pracować po stronie serwera? Nacisk na programowanie po stronie klienta nie polega na eliminowaniu serwerów, ale na wykorzystaniu nowszych technologii, które wreszcie obsługują przeglądarki, aby ulepszyć interfejsy użytkownika.

Co do otrzymanego .jspliku, czy jesteś pewien, że jest on przeznaczony do przeglądarki? Czy może to być biblioteka node.js?

Brandon
źródło
4
+1 za naprawdę dobrą sugestię, że plik JS jest przeznaczony dla serwera NodeJS
Machinarius
11

Cofnijmy się od tego i spójrzmy na wyższy poziom ... czy my ... Czy Eudora lub program Outlook (aplikacja po stronie klienta, nawet niepotrzebująca przeglądarki) kiedykolwiek spowodował stratę finansową dla jakiejkolwiek firmy? Nie. Każdy może pisać do API POP / SMTP i być klientem. Ale bez strat na serwerze. Serwer nie ograniczył działań klienta, obliczeń, pamięci, temperatury, rozmiaru dysku, rozmiaru RAM, DPI monitora, GPU, FPU yada yada klienta, ale dokładnie określił, na co odpowie i nic więcej. Czy słyszałeś kiedyś o szybkim użyciu lub o użyciu MS-Money do włamania do banku?

Twoja przeglądarka (tj. Po stronie klienta) może korzystać z tej samej architektury.

  1. Budujesz swój serwer za pomocą interfejsu API (który BTW zawsze sprowadza się do pochodnych GET POST HEAD itp.).
  2. Na serwerze upewnij się, że interfejs API komunikuje się tylko z klientem uwierzytelnionym i zweryfikowanym pod względem tożsamości dla każdego połączenia.
  3. Więc nie obchodzi cię, kim jest klient.
  4. A potem nie obchodzi cię, czy to przeglądarka, zepsute urządzenie, szkło Google, DOS 3.1, czy zupełnie nowy Nexus w rękach pra-pra-pra-pra-pra-dziadka, który podróżował do 2014 roku i przegapił wszystko technologia, która zalała nasze życie w ciągu ostatnich 15 dekad.
  5. Teraz możesz rozpocząć odciążanie wszystkiego po stronie klienta.

SoapBoxBegin

@KilianFoth podnosi ważny punkt świadomości dla naiwnych i lekkomyślnych, głównie tych, którzy cały czas czytają nagłówki, ale nigdy nie myślą, że stanie się to z ich aplikacją, kodem, pracodawcą, klientem, własnym kontem bankowym. Jeszcze bardziej lekkomyślni są ich pracodawcy (zwłaszcza CTO), którzy pozwolą wyjść z aplikacji, które narażą każdy system na niezarządzane / niekontrolowane narażenie. Jednak zawsze zastanawiam się, jak to się wydaje, że „nigdy się nie uczymy”.

SoapBoxEnd

Podsumowując. Stwórz solidny i zwarty API po stronie serwera. Przeładuj wszystko inne na klienta w oparciu o wszystko, co klient może obsłużyć.

LMSingh
źródło
6

Twierdziłbym, że naprawdę nie możesz. Jeśli chcesz wysłać dane do klienta, musisz spodziewać się, że zostaną one wykorzystane - jednak w miarę możliwości. Twój przykład dotyczący klucza API ilustruje tę kwestię, a ja nie uwzględniałbym tego po stronie klienta JS - zostanie skradziony i wykorzystany.

Na pewno będziesz potrzebować pewnej ilości kodu serwera, aby zachować bezpieczeństwo. Nawet coś tak prostego, jak wyszukiwanie tylko danych związanych z zalogowanym użytkownikiem. To uwierzytelnienie nie może być wykonane po stronie klienta, w przeciwnym razie zostaniesz wykorzystany, a Twoje dane nie będą bezpieczne.

Zawsze postrzegałbym środowisko klienta JS jako dodatek do kodu serwera. Sprawdzanie poprawności na kliencie zapewnia przyjemną obsługę, ale jeśli nie zweryfikujesz również danych POST na serwerze odbierającym, narażasz się na atak. Wszystko od klienta należy uznać za podejrzane.

Matt Klinker
źródło
4

To naprawdę proste. Załóżmy, że komputer kliencki i całe działające na nim oprogramowanie jest pod pełną kontrolą sprytnego złośliwego hakera.

Oznacza to, że wszelkie informacje wysyłane z serwera do klienta będą znane złośliwemu hakerowi, dlatego musisz upewnić się, że nie wysłałeś do klienta żadnych informacji, które mogłyby zostać użyte do zaatakowania twojego serwera lub firmy.

Oznacza to również, że wszystko wysyłane z klienta na serwer zostało wyprodukowane przez złośliwego hakera, więc kod serwera musi mieć pewność, że nic, co klient może wysłać, nie będzie w stanie skutecznie zaatakować twojego serwera.

Wprawdzie wdrożenie jest problemem, ale ważne jest podejście mentalne, założenie, że „klient”, z którym myślisz, że twój serwer rozmawia, nie jest klientem, ale aktywnym atakującym.

(Musisz również założyć, że użytkownik jest sprytnym oszustem, który spróbuje zaatakować twoje metody biznesowe, ale nie ma to nic wspólnego z programowaniem po stronie klienta).

gnasher729
źródło
0

Moim zdaniem aplikacja po stronie klienta dotyczy głównie interfejsu użytkownika. Na przykład cały system interfejsu użytkownika zostanie wysłany raz do klienta, a następnie klient zrobi z nim, co chce.

Zwykle moja aplikacja działałaby na serwerze. Dzwonię do interfejsu API innej firmy z kodu na moim serwerze.

Uruchomienie aplikacji po stronie klienta oznacza, że ​​teraz musi to nastąpić w przeglądarce użytkownika. Interfejs API innej firmy zapewnia niezbędne pliki JavaScript do osiągnięcia tego celu.

Jeśli masz klucz API, to nie jest przeznaczony do pracy po stronie klienta. Jeśli podasz klucz API po stronie klienta, każdy ma do niego dostęp, a następnie może go użyć do własnych celów. Zapisz go i użyj po stronie serwera, gdy klient tego potrzebuje, a następnie wyślij wynik za pomocą Ajax / WebSockets.

To tak, jakby twój bank mówił: „Cóż, umieszczę hasło głównej strony bazy danych klienta, aby klient mógł sam o to poprosić, a on nie będzie już niepokoił naszych serwerów”.

Depado
źródło