Lưu trữ cục bộ bao giờ có thể được coi là an toàn? [đóng cửa]


160

Tôi được yêu cầu phát triển một ứng dụng web sẽ hoạt động ngoại tuyến trong thời gian dài. Để điều này khả thi, tôi không thể tránh lưu dữ liệu nhạy cảm (dữ liệu cá nhân nhưng không phải là loại dữ liệu bạn sẽ chỉ lưu trữ băm) trong bộ nhớ cục bộ.

Tôi chấp nhận rằng đây không phải là khuyến cáo thực hành, nhưng được đưa ra ít lựa chọn Tôi đang làm như sau để bảo mật dữ liệu:

  • mã hóa mọi thứ đi vào bộ nhớ cục bộ bằng thư viện tiền điện tử javascript và AES-256
  • mật khẩu người dùng là khóa mã hóa và không được lưu trữ trên thiết bị
  • phục vụ tất cả nội dung (khi trực tuyến) từ một máy chủ đáng tin cậy qua ssl
  • xác thực tất cả dữ liệu đi đến và từ bộ nhớ cục bộ trên máy chủ bằng dự án antisamy owasp
  • trong phần mạng của appcache, không sử dụng * và thay vào đó chỉ liệt kê các URI cần thiết để kết nối với máy chủ đáng tin cậy
  • nói chung cố gắng áp dụng các hướng dẫn được đề xuất trong bảng cheat OWASP XSS

Tôi đánh giá cao rằng ma quỷ thường ở chi tiết và biết rằng có rất nhiều sự hoài nghi về lưu trữ cục bộ và bảo mật dựa trên javascript nói chung. Bất cứ ai có thể nhận xét về việc có:

  • sai sót cơ bản trong cách tiếp cận trên?
  • bất kỳ giải pháp có thể cho các sai sót như vậy?
  • có cách nào tốt hơn để bảo mật bộ nhớ cục bộ khi ứng dụng html 5 phải hoạt động ngoại tuyến trong thời gian dài không?

Cảm ơn vì bất kì sự giúp đỡ.


"Tôi chấp nhận rằng đây không phải là thực hành được khuyến nghị" - Có phải vậy không? Không phải nó ngược lại mà nó đã được tạo ra thực sự cho điều đó sao?
hakre

2
Để làm rõ, tôi có nghĩa là không nên thực hành để lưu trữ dữ liệu nhạy cảm trong bộ nhớ cục bộ.
dùng1173706

Như thế bạn không nên truyền dữ liệu nhạy cảm qua các mạng lớn?
hakre

@ user1173706 Tại sao ứng dụng phải hoạt động phải chạy trong thời gian dài ngoại tuyến? Người dùng như thế nào? Những trình duyệt nào bạn phải hỗ trợ? Tôi nghĩ rằng điều đó là có thể nhưng tôi cần biết chi tiết cụ thể về kịch bản của bạn .
Benjamin Gruenbaum

@Benjamin tôi đã cập nhật câu hỏi. Cảm ơn.
dùng1173706

Câu trả lời:


74

Tiền điện tử

Các mối quan tâm với mật mã trong javascript phía máy khách (trình duyệt) được trình bày chi tiết bên dưới. Tất cả trừ một trong những mối quan tâm này không áp dụng cho API WebCrypto , hiện được hỗ trợ khá tốt .

Đối với một ứng dụng ngoại tuyến, bạn vẫn phải thiết kế và triển khai kho khóa an toàn.

Ngoài ra: Nếu bạn đang sử dụng Node.js, hãy sử dụng API mã hóa dựng sẵn .

Mật mã gốc Javascript (tiền WebCrypto)

Tôi cho rằng mối quan tâm chính là ai đó có quyền truy cập vật lý vào máy tính đang đọc localStoragetrang web của bạn và bạn muốn mật mã để giúp ngăn chặn truy cập đó.

Nếu ai đó có quyền truy cập vật lý, bạn cũng sẵn sàng tấn công người khác và tệ hơn là đọc. Chúng bao gồm (nhưng không giới hạn): keylogger, sửa đổi tập lệnh ngoại tuyến, tiêm tập lệnh cục bộ, nhiễm độc bộ đệm của trình duyệt và chuyển hướng DNS. Những cuộc tấn công đó chỉ hoạt động nếu người dùng sử dụng máy sau khi nó bị xâm nhập. Tuy nhiên, truy cập vật lý trong một kịch bản như vậy có nghĩa là bạn có vấn đề lớn hơn.

Vì vậy, hãy nhớ rằng kịch bản giới hạn trong đó tiền điện tử cục bộ có giá trị sẽ là nếu máy bị đánh cắp.

Có những thư viện thực hiện chức năng mong muốn, ví dụ Thư viện tiền điện tử Javascript Javascript . Tuy nhiên, có những điểm yếu cố hữu (như được đề cập trong liên kết từ câu trả lời của @ ircmaxell):

  1. Thiếu entropy / tạo số ngẫu nhiên;
  2. Thiếu kho lưu trữ khóa an toàn tức là khóa riêng phải được bảo vệ bằng mật khẩu nếu được lưu trữ cục bộ hoặc được lưu trữ trên máy chủ (có chức năng truy cập ngoại tuyến);
  3. Thiếu xóa an toàn;
  4. Thiếu đặc điểm thời gian.

Mỗi điểm yếu này tương ứng với một loại thỏa hiệp về mật mã. Nói cách khác, trong khi bạn có thể có "tiền điện tử" theo tên, nó sẽ nằm dưới mức nghiêm ngặt mà người ta khao khát trong thực tế.

Tất cả những gì đang được nói, việc đánh giá chuyên gia tính toán không tầm thường như "tiền điện tử Javascript yếu, không sử dụng nó". Đây không phải là một sự chứng thực, hoàn toàn là một lời cảnh báo và nó đòi hỏi bạn phải hoàn toàn hiểu được sự phơi bày của các điểm yếu trên, tần suất và chi phí của các vectơ mà bạn gặp phải và khả năng giảm thiểu hoặc bảo hiểm trong trường hợp thất bại: Javascript crypto, trong mặc dù điểm yếu của nó, có thể làm giảm sự tiếp xúc của bạn nhưng chỉ chống lại kẻ trộm với năng lực kỹ thuật hạn chế. Tuy nhiên, bạn nên cho rằng tiền điện tử Javascript không có giá trị chống lại kẻ tấn công xác định và có khả năng đang nhắm mục tiêu thông tin đó. Một số người sẽ coi đó là sai lầm khi gọi dữ liệu là "được mã hóa" khi có rất nhiều điểm yếu được biết là vốn có khi thực hiện. Nói cách khác, bạn có thể giảm nhẹ mức độ tiếp xúc kỹ thuật của mình nhưng bạn tăng mức độ tiếp xúc tài chính từ việc tiết lộ thông tin. Mỗi tình huống là khác nhau, tất nhiên - và phân tích giảm tiếp xúc kỹ thuật đối với tiếp xúc tài chính là không tầm thường. Đây là một tương tự minh họa:Một số ngân hàng yêu cầu mật khẩu yếu , bất chấp rủi ro vốn có, bởi vì mức độ mất mát từ mật khẩu yếu của họ thấp hơn chi phí của người dùng cuối khi hỗ trợ mật khẩu mạnh.

Nếu bạn đọc đoạn cuối và nghĩ rằng "Một số người trên Internet tên là Brian nói rằng tôi có thể sử dụng tiền điện tử Javascript", đừng sử dụng tiền điện tử Javascript.

Đối với trường hợp sử dụng được mô tả trong câu hỏi, dường như sẽ có ý nghĩa hơn đối với người dùng để mã hóa phân vùng cục bộ hoặc thư mục chính của họ và sử dụng mật khẩu mạnh. Loại bảo mật đó thường được thử nghiệm tốt, được tin cậy rộng rãi và thường có sẵn.


Có tài liệu bổ sung (trích dẫn) có sẵn cho lập trường chung về "không sử dụng tiền điện tử JavaScript" do NCC Group cung cấp từ năm 2011: Mã hóa JavaScript được coi là có hại (đáng chú ý là do việc tải xuống 22 công cụ để xác minh chất lượng tải xuống PRNG Vv v.v.)
amcgregor

58

Vâng, tiền đề cơ bản ở đây là: không, nó chưa an toàn.

Về cơ bản, bạn không thể chạy tiền điện tử trong JavaScript: JavaScript Crypto được coi là có hại .

Vấn đề là bạn không thể lấy mã mật mã một cách đáng tin cậy vào trình duyệt và ngay cả khi bạn có thể, thì JS không được thiết kế để cho phép bạn chạy nó một cách an toàn. Vì vậy, cho đến khi các trình duyệt có một thùng chứa mật mã (mà Phần mở rộng đa phương tiện được mã hóa cung cấp, nhưng đang được sử dụng cho mục đích DRM của họ), thì sẽ không thể thực hiện một cách an toàn.

Theo như một "cách tốt hơn", không có ngay bây giờ. Thay thế duy nhất của bạn là lưu trữ dữ liệu trong văn bản đơn giản và hy vọng điều tốt nhất. Hoặc không lưu trữ thông tin nào cả. Dù bằng cách nào.

Hoặc, hoặc nếu bạn cần loại bảo mật đó và bạn cần bộ nhớ cục bộ, hãy tạo một ứng dụng tùy chỉnh ...


8
Downvoter: bạn có thể cung cấp một câu trả lời tốt hơn? Tôi nhận ra rằng đây là một vấn đề gây tranh cãi khi có sự bất đồng quan trọng giữa các chuyên gia bảo mật (và cả những người không chuyên nghiệp), vì vậy quan điểm thay thế sẽ rất đáng để chia sẻ. Trừ khi bạn hạ thấp vì một lý do khác, trong trường hợp nào tôi có thể cải thiện câu trả lời này?
ircmaxell

9
@ircmaxell không phải tôi, nhưng tôi không đồng ý với câu trả lời này. "Vấn đề là bạn không thể lấy mã mật mã một cách đáng tin cậy vào trình duyệt và ngay cả khi bạn có thể, thì JS không được thiết kế để cho phép bạn chạy nó một cách an toàn." - Tại sao? Là gì vốn có vấn đề? Bạn có thể sử dụng thư viện mã hóa JavaScript Stanford và mã hóa / giải mã trong đó. Bạn có thể băm, và bạn có thể làm mọi thứ một cách an toàn. Tôi không thấy vấn đề cố hữu ở đây trong một ứng dụng ngoại tuyến trong JS đang thực hiện crpyto tiêu chuẩn, giống như một ứng dụng được xây dựng bằng bất kỳ ngôn ngữ nào khác.
Benjamin Gruenbaum

11
@BenjaminGruenbaum: vấn đề là có nhiều nơi mà mã hóa sẽ cần phải tương tác với mã của bên thứ ba. Toàn bộ điểm của bài viết mà tôi liên kết là bạn không thể kiểm soát môi trường thực thi. Vì vậy, bạn cài đặt lib Crypto Stanford. Vậy thì chuyện gì sẽ xảy ra nếu một số plugin trình duyệt ghi đè lên sjcl.encryptemail cho kẻ tấn công? Trong JS đó là 100% có thể và bạn không thể làm gì để ngăn chặn nó. Và đó là điểm cơ bản. Không có cơ chế "bảo mật" nào để ngăn chặn các JS khác làm những điều khó chịu với dữ liệu của bạn. Và đó là một vấn đề .
ircmaxell

13
@ircmaxell Nếu bạn ngủ với chó, bạn không thể không thức dậy với bọ chét. Nếu người dùng cài đặt một phần mềm độc hại bổ sung vào đó giống như người dùng cài đặt vi-rút trên PC của họ, thì nó không khác gì nó. Chương trình Java hoặc C của bạn có thể an toàn như được nhận nhưng ngay khi kẻ tấn công có khả năng chạy mã bạn bị lừa. Điều đó không khác biệt đối với JS. Addons không chỉ xuất hiện một cách kỳ diệu trong trình duyệt. Hơn nữa, việc không lưu thông tin được mã hóa sẽ không giúp ích được gì nếu người dùng có phần mềm độc hại, vì nó chỉ có thể chiếm đoạt dữ liệu trực tiếp.
Benjamin Gruenbaum

9
@BenjaminGruenbaum: không đồng ý. Trong một ứng dụng bình thường, bạn sẽ cần một trong hai thỏa hiệp chính ứng dụng đó (để đọc vị trí bộ nhớ), hoặc tiếp cận được rễ vào hộp (thỏa hiệp hệ điều hành). Dù bằng cách nào, bạn cần phải thỏa hiệp một cái gì đó sâu sắc hơn là chỉ thực hiện hành vi bình thường. JS cho phép điều này trong hành vi bình thường. Đó là vấn đề ...
ircmaxell

12

Khi khám phá chủ đề này, tôi có một bài thuyết trình có tiêu đề "Bảo mật TodoMVC bằng API mã hóa web" ( video , ).

Nó sử dụng API mã hóa web để lưu trữ danh sách việc cần mã hóa trong localStorage bằng mật khẩu bảo vệ ứng dụng và sử dụng khóa dẫn xuất mật khẩu để mã hóa. Nếu bạn quên hoặc mất mật khẩu, không có phục hồi. ( Tuyên bố miễn trừ trách nhiệm - đó là POC và không dành cho sử dụng sản xuất. )

Như các câu trả lời khác, điều này vẫn dễ bị XSS hoặc phần mềm độc hại được cài đặt trên máy khách. Tuy nhiên, bất kỳ dữ liệu nhạy cảm nào cũng sẽ nằm trong bộ nhớ khi dữ liệu được lưu trữ trên máy chủ và ứng dụng đang được sử dụng. Tôi đề nghị hỗ trợ ngoại tuyến có thể là trường hợp sử dụng hấp dẫn.

Cuối cùng, mã hóa localStorage có lẽ chỉ bảo vệ dữ liệu khỏi những kẻ tấn công chỉ đọc quyền truy cập vào hệ thống hoặc các bản sao lưu của nó. Nó bổ sung một lượng nhỏ phòng thủ theo chiều sâu cho 10 mục tiếp xúc dữ liệu nhạy cảm nhất của OWASP và cho phép bạn trả lời "Có bất kỳ dữ liệu nào trong số này được lưu trữ trong văn bản rõ ràng lâu dài không?" chính xác


3

Đây là một bài viết thực sự thú vị ở đây. Tôi đang xem xét triển khai mã hóa JS để cung cấp bảo mật khi sử dụng bộ nhớ cục bộ. Hoàn toàn rõ ràng rằng điều này sẽ chỉ bảo vệ nếu thiết bị bị đánh cắp (và được triển khai chính xác). Nó sẽ không cung cấp sự bảo vệ chống lại keylogger, v.v. Tuy nhiên, đây không phải là vấn đề về JS vì mối đe dọa keylogger là vấn đề của tất cả các ứng dụng, bất kể nền tảng thực thi của chúng (trình duyệt, bản địa). Đối với bài viết "JavaScript Crypto được coi là có hại" được tham chiếu trong câu trả lời đầu tiên, tôi có một lời chỉ trích; nó ghi "Bạn có thể sử dụng SSL / TLS để giải quyết vấn đề này, nhưng điều đó rất tốn kém và phức tạp". Tôi nghĩ rằng đây là một yêu sách rất tham vọng (và có thể khá thiên vị). Có, SSL có chi phí,

Kết luận của tôi - Có một nơi dành cho mã hóa phía máy khách, tuy nhiên, với tất cả các ứng dụng, các nhà phát triển phải nhận ra những hạn chế của nó và thực hiện nếu phù hợp với nhu cầu của họ và đảm bảo có những cách để giảm thiểu rủi ro.


Trong lịch sử đã có những chi phí phi thường (cơ học, không phải tài chính) liên quan đến đàm phán kết nối ban đầu. Đến mức các tập đoàn sẽ sử dụng các thiết bị chấm dứt SSL chuyên dụng, có thể trở nên tốn kém về mặt tài chính ngoài chi phí cấp giấy chứng nhận và đảm bảo. Ngày nay, nhiều vấn đề trong số đó đã được giải quyết, chẳng hạn như việc duy trì phiên kéo dài để tránh bắt tay ban đầu đối với các yêu cầu tiếp theo.
amcgregor

2

Không thể truy cập vào bất kỳ trang web nào (đúng) nhưng có thể dễ dàng truy cập và dễ dàng chỉnh sửa thông qua các công cụ dev, chẳng hạn như chrome (ctl-shift-J). Do đó, tiền điện tử tùy chỉnh cần thiết trước khi lưu trữ giá trị.

Nhưng, nếu javascript cần giải mã (để xác thực) thì thuật toán giải mã bị lộ và có thể bị thao túng.

Javascript cần một bộ chứa hoàn toàn an toàn và khả năng thực hiện đúng các biến và hàm riêng chỉ có sẵn cho trình thông dịch js. Nhưng, điều này vi phạm bảo mật người dùng - vì dữ liệu theo dõi có thể được sử dụng mà không bị trừng phạt.

Do đó, javascript sẽ không bao giờ được bảo mật hoàn toàn.


-29

Không.

Có thể truy cập localStorage bởi bất kỳ trang web nào và nếu bạn có khóa, bạn có thể thay đổi bất kỳ dữ liệu nào bạn muốn.

Điều đó đang được nói, nếu bạn có thể nghĩ ra cách mã hóa các khóa một cách an toàn, thì việc bạn chuyển dữ liệu không thành vấn đề, nếu bạn có thể chứa dữ liệu trong một lần đóng, thì dữ liệu đó (phần nào) an toàn.


19
Nó không thể truy cập vào "bất kỳ trang web". Nó chỉ có thể truy cập vào các trang trong miền hiện tại.
dtabuenc

@dtabuenc ngược lại, tôi đã tạo một cây bút một lúc trước cho bạn thấy mỗi cặp khóa / giá trị duy nhất trong localStorage của bạn , mà không có bất kỳ hack nào.
hellol11

3
Không! Lấy làm tiếc. Lưu trữ cục bộ được phân lập trên mỗi miền. Mã chạy trong một tên miền không thể truy cập các giá trị được lưu trữ vào bộ nhớ cục bộ bởi một tên miền khác. Ví dụ: google.com lưu trữ một loạt các công cụ trong bộ nhớ cục bộ. Bạn sẽ không thể liệt kê bất kỳ khóa nào từ google.com trong ví dụ về bút của bạn.
dtabuenc

@dtabuenc đã thử nó, bạn nói đúng.
hellol11
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.