Czy lokalną pamięć masową można kiedykolwiek uznać za bezpieczną? [Zamknięte]

161

Jestem zobowiązany do stworzenia aplikacji internetowej, która będzie działać w trybie offline przez długi czas. Aby było to możliwe, nie mogę uniknąć zapisywania poufnych danych (danych osobowych, ale nie tych, które byłyby tylko zaszyfrowane) w pamięci lokalnej.

Akceptuję, że nie jest to zalecana praktyka, ale mając niewielki wybór, wykonuję następujące czynności, aby zabezpieczyć dane:

  • szyfrowanie wszystkiego, co trafia do lokalnej pamięci, przy użyciu biblioteki kryptograficznej Stanford javascript i AES-256
  • hasło użytkownika jest kluczem szyfrowania i nie jest przechowywane na urządzeniu
  • obsługa wszystkich treści (w trybie online) z jednego zaufanego serwera za pośrednictwem protokołu SSL
  • walidacja wszystkich danych przychodzących do iz lokalnej pamięci na serwerze przy użyciu projektu owasp antisamy
  • w sekcji sieci pamięci podręcznej aplikacji, nie używa *, a zamiast tego podaje tylko identyfikatory URI wymagane do połączenia z zaufanym serwerem
  • generalnie staram się stosować wskazówki sugerowane w ściągawce OWASP XSS

Doceniam, że diabeł często tkwi w szczegółach i wiem, że istnieje wiele sceptycyzmu co do lokalnego przechowywania i ogólnie bezpieczeństwa opartego na javascript. Czy ktoś może skomentować, czy są:

  • podstawowe wady powyższego podejścia?
  • jakieś możliwe rozwiązania takich wad?
  • jakikolwiek lepszy sposób na zabezpieczenie lokalnej pamięci masowej, gdy aplikacja HTML 5 musi działać w trybie offline przez długi czas?

Dzięki za wszelką pomoc.

user1173706
źródło
„Akceptuję, że to nie jest zalecana praktyka” - czy tak jest? Czy nie jest odwrotnie, że został stworzony właśnie do tego?
hakre
2
Aby wyjaśnić, miałem na myśli niezalecane praktyki przechowywania poufnych danych w lokalnej pamięci.
user1173706
W ten sposób nie powinieneś przesyłać wrażliwych danych przez duże sieci?
hakre
@ user1173706 Dlaczego aplikacja musi działać przez dłuższy czas w trybie offline? Jacy są użytkownicy? Jakie przeglądarki musisz obsługiwać? Myślę, że jest to możliwe, ale muszę poznać szczegóły dotyczące twojego scenariusza.
Benjamin Gruenbaum
@Benjamin Zaktualizowałem pytanie. Dzięki.
user1173706,

Odpowiedzi:

74

WebCrypto

Obawy związane z kryptografią w javascript po stronie klienta (przeglądarki) są szczegółowo opisane poniżej. Wszystkie te obawy oprócz jednego nie dotyczą interfejsu API WebCrypto , który jest teraz dość dobrze obsługiwany .

W przypadku aplikacji offline nadal musisz zaprojektować i wdrożyć bezpieczny magazyn kluczy.

Poza tym: jeśli używasz Node.js, użyj wbudowanego Crypto API.

Kryptografia natywna-Javascript (przed WebCrypto)

Zakładam, że głównym problemem jest ktoś, kto ma fizyczny dostęp do komputera czytającego localStorageTwoją witrynę, a chcesz, aby kryptografia zapobiegała temu dostępowi.

Jeśli ktoś ma fizyczny dostęp, jesteś również narażony na ataki inne i gorsze niż czytanie. Są to między innymi: keyloggery, modyfikacja skryptów offline, wstrzykiwanie skryptów lokalnych, zatruwanie pamięci podręcznej przeglądarki i przekierowania DNS. Te ataki działają tylko wtedy, gdy użytkownik korzysta z maszyny po tym, jak została ona przejęta. Niemniej jednak fizyczny dostęp w takim scenariuszu oznacza większe problemy.

Należy więc pamiętać, że ograniczony scenariusz, w którym lokalne kryptowaluty są cenne, to kradzież maszyny.

Istnieją biblioteki, które implementują pożądaną funkcjonalność, np. Stanford Javascript Crypto Library . Istnieją jednak nieodłączne słabości (o których mowa w linku z odpowiedzi @ ircmaxell):

  1. Brak entropii / generowania liczb losowych;
  2. Brak bezpiecznego magazynu kluczy, tj. Klucz prywatny musi być chroniony hasłem, jeśli jest przechowywany lokalnie lub na serwerze (co blokuje dostęp offline);
  3. Brak bezpiecznego wymazywania;
  4. Brak charakterystyk czasowych.

Każda z tych słabości odpowiada kategorii kompromisów kryptograficznych. Innymi słowy, chociaż możesz mieć „krypto” z nazwy, będzie ono znacznie poniżej rygoru, do którego aspiruje się w praktyce.

Mimo wszystko ocena aktuarialna nie jest tak banalna, jak „Kryptowaluta w Javascript jest słaba, nie używaj jej”. To nie jest aprobata, ściśle zastrzeżenie i wymaga pełnego zrozumienia ujawnienia powyższych słabości, częstotliwości i kosztu wektorów, z którymi się spotykasz, oraz zdolności do łagodzenia lub ubezpieczenia w przypadku awarii: krypto JavaScript, w pomimo swoich słabości może zmniejszyć Twoje narażenie, ale tylko przeciwko złodziejom o ograniczonych możliwościach technicznych. Należy jednak założyć, że krypto JavaScript nie ma wartości w stosunku do zdeterminowanego i zdolnego napastnika, który atakuje te informacje. Niektórzy uznaliby za mylące nazywanie danych „zaszyfrowanymi”, skoro wiadomo, że tak wiele słabych punktów jest nieodłącznych dla implementacji. Innymi słowy, możesz nieznacznie zmniejszyć swoją ekspozycję techniczną, ale zwiększysz swoją ekspozycję finansową w wyniku ujawnienia. Oczywiście każda sytuacja jest inna - a analiza redukcji technicznej ekspozycji na ekspozycję finansową jest nietrywialna. Oto przykładowa analogia:Niektóre banki wymagają słabych haseł , pomimo nieodłącznego ryzyka, ponieważ ich narażenie na straty wynikające ze słabych haseł jest mniejsze niż koszty obsługi silnych haseł dla użytkownika końcowego.

🔥 Jeśli przeczytałeś ostatni akapit i pomyślałeś: „Jakiś facet w Internecie imieniem Brian mówi, że mogę używać kryptografii Javascript”, nie używaj kryptografii Javascript.

W przypadku użycia opisanym w pytaniu wydaje się, że bardziej sensowne byłoby zaszyfrowanie lokalnej partycji lub katalogu domowego przez użytkowników i użycie silnego hasła. Ten rodzaj zabezpieczeń jest ogólnie dobrze przetestowany, powszechnie zaufany i powszechnie dostępny.

Brian M. Hunt
źródło
Dostępna jest dodatkowa dokumentacja (cytaty) przedstawiająca ogólne stanowisko „nie używaj kryptografii JavaScript”, dostarczona przez NCC Group od 2011 r .: Kryptografia JavaScript uznana za szkodliwą (w szczególności ze względu na chwyt-22 pobierania narzędzia do weryfikacji plików do pobrania… Jakość PRNG … Itd.)
amcgregor
58

Cóż, podstawowe założenie jest takie: nie, nie jest jeszcze bezpieczne.

Zasadniczo nie możesz uruchomić kryptografii w JavaScript: JavaScript Crypto uważany za szkodliwy .

Problem polega na tym, że nie możesz niezawodnie pobrać kodu kryptograficznego do przeglądarki, a nawet gdybyś mógł, JS nie jest zaprojektowany, aby umożliwić Ci bezpieczne uruchamianie. Tak więc dopóki przeglądarki nie będą miały kontenera kryptograficznego (który zapewniają rozszerzenia Encrypted Media Extensions, ale są wykorzystywane do celów DRM), nie będzie można tego zrobić bezpiecznie.

Jeśli chodzi o „Lepszy sposób”, nie ma go teraz. Jedyną alternatywą jest przechowywanie danych w postaci zwykłego tekstu i nadzieja na najlepsze. Lub w ogóle nie przechowuj informacji. Tak czy inaczej.

Albo to, albo jeśli potrzebujesz tego rodzaju zabezpieczeń i potrzebujesz lokalnej pamięci, utwórz niestandardową aplikację ...

ircmaxell
źródło
8
Downvoter: czy możesz podać lepszą odpowiedź? Zdaję sobie sprawę, że jest to nieco kontrowersyjna kwestia, w której istnieje znaczny spór między specjalistami ds. Bezpieczeństwa (i nieprofesjonalistami również), więc warto podzielić się innym punktem widzenia. O ile nie głosujesz w dół z innego powodu, w takim przypadku jak mogę poprawić tę odpowiedź?
ircmaxell,
9
@ircmaxell nie ja, ale nie zgadzam się z tą odpowiedzią. „Problem polega na tym, że nie możesz niezawodnie pobrać kodu kryptograficznego do przeglądarki, a nawet gdybyś mógł, JS nie jest zaprojektowany tak, aby umożliwić Ci bezpieczne uruchamianie”. - Czemu? Jaki jest nieodłączny problem? Możesz użyć biblioteki szyfrowania JavaScript Stanforda i zaszyfrować / odszyfrować w niej. Możesz haszować i robić wszystko bezpiecznie. Nie widzę tutaj nieodłącznego problemu w aplikacji offline w JS wykonującej standardowe crpyto, podobnie jak aplikacja zbudowana w jakimkolwiek innym języku.
Benjamin Gruenbaum
11
@BenjaminGruenbaum: problem polega na tym, że istnieje wiele miejsc, w których ten kod kryptograficzny musiałby wchodzić w interakcję z kodem strony trzeciej. Cały punkt tego artykułu, do którego nawiązałem, jest taki, że nie możesz kontrolować środowiska wykonawczego. Więc instalujesz bibliotekę Stanford Crypto. Co się stanie, jeśli jakaś wtyczka przeglądarki zastąpi sjcl.encryptwysłanie klucza e-mailem do atakującego? W JS jest to w 100% możliwe i nic nie możesz zrobić, aby to zatrzymać. I to jest podstawowa kwestia. Nie istnieją żadne mechanizmy „bezpieczeństwa”, które uniemożliwiłyby innym JS wykonanie nieprzyjemnych czynności z danymi. I to jest problem .
ircmaxell
13
@ircmaxell Jeśli śpisz z psami, nie możesz oczekiwać, że nie obudzisz się z pchłami. Jeśli użytkownik zainstaluje dodatek złośliwego oprogramowania, który jest taki sam, jak użytkownik instalujący wirusa na swoim komputerze, nie różni się od niego. Twój program w języku Java lub C może być tak bezpieczny, jak to tylko możliwe, ale gdy tylko osoba atakująca będzie mogła uruchomić kod, jesteś oszukany. Nie inaczej jest w przypadku JS. Dodatki nie tylko magicznie pojawiają się w przeglądarce. Co więcej, nie zapisywanie zaszyfrowanych informacji nie pomogłoby w żaden sposób, jeśli użytkownik ma złośliwe oprogramowanie, ponieważ może po prostu przejąć dane na żywo.
Benjamin Gruenbaum
9
@BenjaminGruenbaum: nie zgadzam się. W normalnym zastosowaniu, to trzeba albo iść na kompromis samą aplikację (do odczytu komórki pamięci) lub dostęp korzeń zysk do skrzynki (zagrozić OS). Tak czy inaczej, musisz pogodzić się z czymś głębszym niż zwykłe zachowanie. JS pozwala na to w normalnym zachowaniu. Jaki jest problem ...
ircmaxell
12

Aby zgłębić ten temat, mam prezentację zatytułowaną „Zabezpieczanie TodoMVC przy użyciu interfejsu Web Cryptography API” ( wideo , kod ).

Wykorzystuje interfejs API kryptografii sieci Web do przechowywania listy zadań do wykonania zaszyfrowanej w localStorage za pomocą hasła chroniącego aplikację i używającego klucza uzyskanego z hasła do szyfrowania. Jeśli zapomnisz lub zgubisz hasło, nie ma możliwości odzyskania. ( Zastrzeżenie - był to POC i nie jest przeznaczony do użytku produkcyjnego ).

Jak podano w innych odpowiedziach, nadal jest podatny na XSS lub złośliwe oprogramowanie zainstalowane na komputerze klienckim. Jednak wszelkie wrażliwe dane byłyby również w pamięci, gdy są przechowywane na serwerze, a aplikacja jest używana. Sugeruję, że wsparcie offline może być przekonującym przypadkiem użycia.

Ostatecznie szyfrowanie localStorage prawdopodobnie chroni dane tylko przed atakującymi, którzy mają dostęp tylko do odczytu do systemu lub jego kopii zapasowych. Dodaje niewielką ilość dogłębnej obrony dla 10 pozycji OWASP Top 10 A6-Sensitive Data Exposure i pozwala odpowiedzieć „Czy któreś z tych danych są przechowywane w postaci zwykłego tekstu przez długi czas?” prawidłowo.

Kevin Hakanson
źródło
3

To jest naprawdę interesujący artykuł. Rozważam wdrożenie szyfrowania JS w celu zapewnienia bezpieczeństwa podczas korzystania z lokalnego magazynu. Jest absolutnie jasne, że zapewni to ochronę tylko wtedy, gdy urządzenie zostanie skradzione (i zostanie prawidłowo wdrożone). Nie zapewni ochrony przed keyloggerami itp. Nie jest to jednak problem JS, ponieważ zagrożenie keyloggerem jest problemem wszystkich aplikacji, niezależnie od platformy ich wykonywania (przeglądarka, natywna). Jeśli chodzi o artykuł „JavaScript Crypto uważany za szkodliwy”, o którym mowa w pierwszej odpowiedzi, mam jedną krytykę; stwierdza: „Możesz użyć SSL / TLS, aby rozwiązać ten problem, ale jest to kosztowne i skomplikowane”. Myślę, że jest to bardzo ambitne twierdzenie (i być może raczej stronnicze). Tak, SSL kosztuje,

Mój wniosek - jest miejsce na kod szyfrujący po stronie klienta, jednak tak jak w przypadku wszystkich aplikacji programiści muszą rozpoznać jego ograniczenia i zaimplementować je, jeśli jest to odpowiednie dla ich potrzeb, oraz upewnić się, że istnieją sposoby na ograniczenie tego ryzyka.

Paul S.
źródło
Historycznie rzecz biorąc, początkowe negocjacje połączeń wiązały się z nadzwyczajnymi kosztami (mechanicznymi, a nie finansowymi). Do tego stopnia, że ​​korporacje używałyby dedykowanych urządzeń kończących SSL, co mogłoby stać się kosztowne finansowo, wykraczając poza koszty wydania certyfikatu i zabezpieczenia. Obecnie wiele z tych problemów zostało rozwiązanych, na przykład wydłużenie czasu trwania sesji w celu uniknięcia wstępnego uzgadniania kolejnych żądań.
amcgregor
2

Niedostępny dla żadnej strony internetowej (prawda), ale jest łatwo dostępny i łatwo edytowalny za pomocą narzędzi programistycznych, takich jak chrome (ctl-shift-J). W związku z tym przed zapisaniem wartości wymagane jest niestandardowe szyfrowanie.

Ale jeśli javascript musi odszyfrować (sprawdzić poprawność), algorytm deszyfrujący jest ujawniony i można nim manipulować.

Javascript potrzebuje w pełni bezpiecznego kontenera oraz możliwości prawidłowego implementowania prywatnych zmiennych i funkcji, które są dostępne tylko dla interpretera js. Narusza to jednak bezpieczeństwo użytkownika - ponieważ dane śledzenia mogą być używane bezkarnie.

W rezultacie javascript nigdy nie będzie w pełni bezpieczny.

rockmo
źródło
-29

Nie.

localStorage jest dostępny z dowolnej strony internetowej, a jeśli masz klucz, możesz zmienić dowolne dane.

Biorąc to pod uwagę, jeśli potrafisz wymyślić sposób bezpiecznego szyfrowania kluczy, nie ma znaczenia, w jaki sposób przesyłasz dane, jeśli możesz zawrzeć dane w zamknięciu, dane są (w pewnym stopniu) bezpieczne.

hellol11
źródło
19
Nie jest dostępny dla „żadnej strony internetowej”. Jest dostępny tylko dla stron w bieżącej domenie.
dtabuenc
@dtabuenc wręcz przeciwnie, jakiś czas temu stworzyłem pióro, które pokazuje każdą parę klucz / wartość w lokalnym magazynie , bez żadnych hacków.
hellol11
3
Nie! Przepraszam. Lokalna pamięć masowa jest izolowana dla każdej domeny. Kod działający w jednej domenie nie może uzyskać dostępu do wartości przechowywanych w pamięci lokalnej przez inną domenę. Na przykład google.com przechowuje wiele rzeczy w pamięci lokalnej. W przykładzie z piórem nie będzie można podać żadnego klucza z witryny google.com.
dtabuenc,
@dtabuenc przetestował to, masz rację.
hellol11