Tôi hiện đang xây dựng một ứng dụng trang duy nhất bằng Reacjs. Tôi đọc được rằng nhiều lý do không sử dụng localStorage là do các lỗ hổng XSS. Vì React thoát khỏi tất cả đầu vào của người dùng, giờ đây nó có an toàn khi sử dụng localStorage không?
Tôi hiện đang xây dựng một ứng dụng trang duy nhất bằng Reacjs. Tôi đọc được rằng nhiều lý do không sử dụng localStorage là do các lỗ hổng XSS. Vì React thoát khỏi tất cả đầu vào của người dùng, giờ đây nó có an toàn khi sử dụng localStorage không?
Câu trả lời:
Trong hầu hết các ứng dụng trang đơn hiện đại, chúng tôi thực sự phải lưu trữ mã thông báo ở đâu đó ở phía máy khách (trường hợp sử dụng phổ biến nhất - để giữ cho người dùng đăng nhập sau khi làm mới trang).
Có tổng cộng 2 tùy chọn có sẵn: Lưu trữ web (lưu trữ phiên, lưu trữ cục bộ) và cookie phía máy khách. Cả hai tùy chọn đều được sử dụng rộng rãi, nhưng điều này không có nghĩa là chúng rất an toàn.
Tom Abbott tóm tắt tốt bảo mật phiên JWTStorage và localStorage :
Lưu trữ web (localStorage / sessionStorage) có thể truy cập thông qua JavaScript trên cùng một tên miền. Điều này có nghĩa là bất kỳ JavaScript nào chạy trên trang web của bạn đều có quyền truy cập vào bộ lưu trữ web và do điều này có thể dễ bị tấn công bởi kịch bản chéo trang (XSS) . XSS, tóm lại, là một loại lỗ hổng trong đó kẻ tấn công có thể tiêm JavaScript sẽ chạy trên trang của bạn. Các cuộc tấn công XSS cơ bản cố gắng tiêm JavaScript thông qua các đầu vào của biểu mẫu, trong đó kẻ tấn công đưa
<script>alert('You are Hacked');</script>
vào một biểu mẫu để xem nó có được trình duyệt chạy hay không và có thể được xem bởi những người dùng khác.
Để ngăn XSS, phản ứng phổ biến là thoát và mã hóa tất cả dữ liệu không đáng tin cậy. React (chủ yếu) làm điều đó cho bạn! Đây là một cuộc thảo luận tuyệt vời về mức độ bảo vệ lỗ hổng XSS mà React chịu trách nhiệm .
Nhưng điều đó không bao gồm tất cả các lỗ hổng có thể! Một mối đe dọa tiềm năng khác là việc sử dụng JavaScript được lưu trữ trên CDN hoặc cơ sở hạ tầng bên ngoài .
Lại là Tom:
Các ứng dụng web hiện đại bao gồm các thư viện JavaScript của bên thứ 3 để thử nghiệm A / B, phân tích kênh / thị trường và quảng cáo. Chúng tôi sử dụng các trình quản lý gói như Bower để nhập mã của người khác vào ứng dụng của mình.
Điều gì nếu chỉ một trong các tập lệnh bạn sử dụng bị xâm phạm? JavaScript độc hại có thể được nhúng trên trang và Lưu trữ web bị xâm phạm. Các loại tấn công XSS này có thể khiến Web Storage của mọi người truy cập trang web của bạn mà không cần biết. Đây có lẽ là lý do tại sao một loạt các tổ chức khuyên không nên lưu trữ bất cứ thứ gì có giá trị hoặc tin tưởng bất kỳ thông tin nào trong lưu trữ web. Điều này bao gồm định danh phiên và mã thông báo.
Do đó, kết luận của tôi là với tư cách là một cơ chế lưu trữ, Web Storage không thực thi bất kỳ tiêu chuẩn bảo mật nào trong quá trình chuyển . Bất cứ ai đọc Lưu trữ web và sử dụng nó đều phải thực hiện trách nhiệm của mình để đảm bảo họ luôn gửi JWT qua HTTPS và không bao giờ HTTP.
Tôi biết đây là một câu hỏi cũ nhưng theo những gì @ mikejones1477 đã nói, các thư viện và khung công tác hiện đại thoát khỏi văn bản giúp bạn bảo vệ chống lại XSS. Lý do tại sao cookie không phải là một phương pháp an toàn khi sử dụng thông tin đăng nhập là vì cookie không ngăn CSRF khi localStorage thực hiện (cũng nhớ rằng cookie cũng có thể truy cập bằng javascript, vì vậy XSS không phải là vấn đề lớn ở đây), câu trả lời này tiếp tục tại sao .
Lý do lưu trữ mã thông báo xác thực trong bộ nhớ cục bộ và thêm thủ công vào từng yêu cầu bảo vệ chống lại CSRF là từ khóa đó: thủ công. Vì trình duyệt không tự động gửi mã thông báo xác thực đó, nếu tôi truy cập evil.com và nó quản lý để gửi POST http://example.com/delete-my-account , vì vậy nó sẽ không thể gửi mã thông báo authn của tôi, vì vậy yêu cầu bị bỏ qua.
Tất nhiên httpOnly là chén thánh nhưng bạn không thể truy cập từ Reacjs hoặc bất kỳ khung js nào bên cạnh bạn vẫn có lỗ hổng CSRF. Đề xuất của tôi sẽ là lưu trữ cục bộ hoặc nếu bạn muốn sử dụng cookie, hãy đảm bảo thực hiện một số giải pháp cho vấn đề CSRF của bạn như django .
Liên quan đến CDN, đảm bảo bạn không sử dụng một số CDN kỳ lạ, ví dụ CDN như google hoặc bootstrap cung cấp, được cộng đồng duy trì và không chứa mã độc, nếu bạn không chắc chắn, bạn có thể xem xét miễn phí.
HttpOnly
SameSite=strict
và secure
, sẽ giữ thông tin bạn đặt trong cookie an toàn. Sau đó, chống lại XSS, bạn chỉ cần đảm bảo rằng JavaScript của bạn không biết về bất kỳ dữ liệu liên quan đến xác thực nào, như mã thông báo và mật khẩu (nghĩa là không lưu trữ chúng trong Bộ lưu trữ web) - nếu bạn nhập tập lệnh độc hại, tập lệnh đó sẽ không có quyền truy cập dữ liệu nhạy cảm. Có, bạn cũng sẽ không có quyền truy cập vào mã thông báo thông qua JS, nhưng đó thực sự không phải là vấn đề.
Về cơ bản, bạn có thể lưu trữ JWT của mình trong LocalStorage.
Và tôi nghĩ rằng đây là một cách tốt. Nếu chúng ta đang nói về XSS, XSS bằng CDN, thì đó cũng có nguy cơ tiềm ẩn trong việc đăng nhập / vượt qua của khách hàng của bạn. Lưu trữ dữ liệu trong bộ nhớ cục bộ sẽ ngăn chặn các cuộc tấn công CSRF ít nhất.
Bạn cần nhận thức được cả hai và chọn những gì bạn muốn. Cả hai cuộc tấn công không phải là tất cả những gì bạn cần phải biết, chỉ cần nhớ: ỨNG DỤNG ENTIRE CỦA BẠN CHỈ ĐƯỢC BẢO ĐẢM LÀ ĐIỂM BẢO MẬT MỚI NHẤT CỦA ỨNG DỤNG CỦA BẠN.
Một lần nữa lưu trữ là OK, dễ bị XSS, CSRF, ... không
Sẽ không an toàn nếu bạn sử dụng CDN:
JavaScript độc hại có thể được nhúng trên trang và Lưu trữ web bị xâm phạm. Các loại tấn công XSS này có thể khiến Web Storage của mọi người truy cập trang web của bạn mà không cần biết. Đây có lẽ là lý do tại sao một loạt các tổ chức khuyên không nên lưu trữ bất cứ thứ gì có giá trị hoặc tin tưởng bất kỳ thông tin nào trong lưu trữ web. Điều này bao gồm định danh phiên và mã thông báo.
thông qua cơn bão
Bất kỳ tập lệnh nào bạn yêu cầu từ bên ngoài đều có khả năng bị xâm phạm và có thể lấy bất kỳ JWTS nào từ bộ lưu trữ của khách hàng của bạn và gửi dữ liệu cá nhân trở lại máy chủ của kẻ tấn công.
Localst Storage được thiết kế để có thể truy cập bằng javascript, do đó nó không cung cấp bất kỳ sự bảo vệ XSS nào. Như đã đề cập trong các câu trả lời khác, có một loạt các cách có thể để thực hiện một cuộc tấn công XSS, từ đó lưu trữ cục bộ không được bảo vệ theo mặc định.
Tuy nhiên, cookie có cờ bảo mật bảo vệ khỏi các cuộc tấn công XSS và CSRF. Cờ httpOnly ngăn javascript phía máy khách truy cập cookie, Cờ bảo mật chỉ cho phép trình duyệt chuyển cookie qua ssl và cờ SameSite đảm bảo rằng cookie chỉ được gửi đến nguồn gốc. Mặc dù tôi mới kiểm tra và SameSite hiện chỉ được hỗ trợ trong Opera và Chrome, vì vậy để bảo vệ khỏi CSRF, tốt hơn là sử dụng các chiến lược khác. Ví dụ: gửi mã thông báo được mã hóa trong cookie khác với một số dữ liệu người dùng công khai.
Vì vậy, cookie là một lựa chọn an toàn hơn để lưu trữ dữ liệu xác thực.
id_token_hint
máy chủ xác thực OIDC; mã thông báo cung cấp thông tin kẻ tấn công về mật mã được sử dụng để ký tên; v.v.
Một cách để xem xét điều này là xem xét mức độ rủi ro hoặc tác hại.
Bạn đang xây dựng một ứng dụng không có người dùng, POC / MVP? Bạn có phải là một người khởi nghiệp cần tiếp cận và kiểm tra ứng dụng của bạn một cách nhanh chóng? Nếu có, tôi có lẽ sẽ chỉ thực hiện giải pháp đơn giản nhất và duy trì sự tập trung vào việc tìm kiếm sản phẩm phù hợp với thị trường. Sử dụng localStorage vì nó thường dễ thực hiện hơn.
Bạn đang xây dựng một v2 của một ứng dụng có nhiều người dùng hoạt động hàng ngày hay một ứng dụng mà mọi người / doanh nghiệp phụ thuộc rất nhiều vào. Sẽ bị hack có nghĩa là ít hoặc không có chỗ để phục hồi? Nếu vậy, tôi sẽ xem xét kỹ lưỡng các phụ thuộc của bạn và xem xét việc lưu trữ thông tin mã thông báo trong cookie chỉ có http.
Sử dụng cả localStorage và lưu trữ cookie / phiên đều có ưu và nhược điểm riêng.
Như đã nêu trong câu trả lời đầu tiên: Nếu ứng dụng của bạn có lỗ hổng XSS, thì cả hai sẽ không bảo vệ người dùng của bạn. Vì hầu hết các ứng dụng hiện đại có hàng tá phụ thuộc khác nhau, nên ngày càng khó đảm bảo rằng một trong các phụ thuộc của ứng dụng của bạn không dễ bị XSS.
Nếu ứng dụng của bạn có lỗ hổng XSS và tin tặc đã có thể khai thác nó, tin tặc sẽ có thể thực hiện các hành động thay mặt cho người dùng của bạn. Tin tặc có thể thực hiện các yêu cầu GET / POST bằng cách truy xuất mã thông báo từ localStorage hoặc có thể thực hiện các yêu cầu POST nếu mã thông báo được lưu trữ trong cookie chỉ http.
Mặt trái duy nhất của việc lưu trữ mã thông báo của bạn trong bộ nhớ cục bộ là tin tặc sẽ có thể đọc mã thông báo của bạn.
Không phải cookie cục bộ hoặc httpOnly không được chấp nhận? Liên quan đến thư viện bên thứ 3 bị xâm nhập, giải pháp duy nhất tôi biết là sẽ giảm / ngăn chặn thông tin nhạy cảm bị đánh cắp sẽ được thực thi toàn vẹn Subresource .
Subresource Integrity (SRI) là một tính năng bảo mật cho phép các trình duyệt xác minh rằng các tài nguyên mà họ tìm nạp (ví dụ: từ CDN) được phân phối mà không cần thao tác bất ngờ. Nó hoạt động bằng cách cho phép bạn cung cấp hàm băm mật mã mà tài nguyên tìm nạp phải khớp.
Miễn là thư viện bên thứ 3 bị xâm nhập hoạt động trên trang web của bạn, một keylogger có thể bắt đầu thu thập thông tin như tên người dùng, mật khẩu và bất cứ điều gì khác mà bạn nhập vào trang web.
Cookie httpOnly sẽ ngăn truy cập từ một máy tính khác nhưng sẽ không làm gì để ngăn chặn tin tặc thao túng máy tính của người dùng.
Việc lưu trữ mã thông báo của bạn trong localStorage là an toàn miễn là bạn mã hóa nó. Dưới đây là một đoạn mã nén cho thấy một trong nhiều cách bạn có thể làm điều đó.
import SimpleCrypto from 'simple-crypto-js';
const saveToken = (token = '') => {
const encryptInit = new SimpleCrypto('PRIVATE_KEY_STORED_IN_ENV_FILE');
const encryptedToken = encryptInit.encrypt(token);
localStorage.setItem('token', encryptedToken);
}
Sau đó, trước khi sử dụng mã thông báo của bạn giải mã nó bằng cách sử dụng PRIVATE_KEY_STORED_IN_ENV_FILE