Làm thế nào để gửi mật khẩu một cách an toàn qua HTTP?


115

Nếu trên màn hình đăng nhập, người dùng gửi biểu mẫu có tên người dùng và mật khẩu của mình, mật khẩu sẽ được gửi ở dạng văn bản thuần túy (ngay cả với POST, hãy sửa cho tôi nếu tôi sai).

Vì vậy, câu hỏi đặt ra là đâu là cách phù hợp để bảo vệ người dùng và mật khẩu của mình trước bên thứ ba, những người có thể đang nghe trộm dữ liệu liên lạc?

Tôi biết rằng HTTPS là cách giải quyết vấn đề, nhưng có cách nào để đảm bảo ít nhất một mức độ bảo mật nào đó bằng giao thức HTTP tiêu chuẩn (yêu cầu POST) không? (có thể sử dụng javascript theo một cách nào đó)

CHỈNH SỬA Tôi có thể đã bỏ sót một số điều quan trọng.

Những gì tôi đã nói về một trang - đó là trang đăng nhập do PHP tạo ra, tất nhiên được gửi đến người dùng trong yêu cầu HTTP GET dưới dạng tệp HTML. Không có kết nối (@Jeremy Powel) nào được thiết lập giữa máy chủ và máy khách nên tôi không thể tạo giao thức bắt tay như vậy. Và tôi muốn toàn bộ quá trình minh bạch với người dùng - anh ta muốn gửi mật khẩu chứ không phải xử lý mật mã.

Cảm ơn.


1
Bạn có thể sẽ không thể thực hiện được điều này nếu không có ứng dụng khách sử dụng mật mã, nhưng người dùng không phải xem quá trình như vậy. Anh ấy chỉ cần nhập mật khẩu của mình và mã mà PHP của bạn tạo ra (javascript chẳng hạn) sẽ xử lý tất cả cho bạn.
Jeremy Powell

13
Vấn đề bạn mô tả là lý do HTTPS được phát minh. Nếu bạn gửi một bí mật cho máy khách để mã hóa mật khẩu, kẻ nghe trộm sẽ có thể đánh hơi được và giải mã mật khẩu trong chuyến trở về.
jnoss

1
Vì vậy, S trong đề xuất của bạn chỉ có thể là mật khẩu (hoặc tên người dùng + mật khẩu được kết hợp theo bất kỳ cách nào), vì đây là "bí mật" duy nhất mà người dùng có. Tôi có đúng không? Vì vậy, giải pháp sẽ như sau: - Máy chủ cung cấp cho trang HTML một trường biểu mẫu ẩn R - Người dùng nhập mật khẩu và trước khi mật khẩu được gửi đi, javascript sẽ tính toán H (R, S) và gửi nó đến máy chủ, thậm chí bằng cách sử dụng AJAX - các máy chủ tính toán H (R, S) và so sánh nó với nhận và gửi một phản ứng với ajax yêu cầu liệu xác thực thông qua - các javascript chuyển hướng trình duyệt vào trang web mong muốn
Kornelije Petak

2
@jeremy powell - trong khi những gì bạn mô tả là thông lệ, nó cũng dễ bị kẻ trung gian đánh cắp cookie từ tiêu đề và mạo danh người dùng bằng cách sử dụng lại cookie. Man in the đột phá trung lộ rất khó để bảo vệ chống lại trừ khi bạn đang sử dụng HTTPS
jnoss

1
Đối với những ai có câu hỏi này trong tương lai: SAU KHI đăng nhập, bạn cũng cần bảo mật cookie phiên. (Vì vậy: sử dụng HTTPS thực sự là như vậy dễ dàng hơn nhiều.)
Arjan

Câu trả lời:


66

Sử dụng HTTP với SSL sẽ làm cho cuộc sống của bạn dễ dàng hơn nhiều và bạn có thể yên tâm, những người rất thông minh (ít nhất cũng thông minh hơn tôi!) Đã xem xét kỹ lưỡng phương pháp giao tiếp bí mật này trong nhiều năm.


14
... và "Nhưng tôi phải trả tiền để có chứng chỉ SSL !!" không phải là một khiếu nại hợp lệ, vì bạn có thể nhận được chúng với giá 30 đô la vào những ngày này. Dữ liệu của bạn có thực sự không đáng giá 30 đô để bảo vệ?
caf

3
Điều gì xảy ra nếu máy chủ web bạn đã đăng ký không hỗ trợ thêm chứng chỉ SSL?
Calmarius

89
@Calmarius - sau đó bạn di chuyển đến một webhost thực
BornToCode

3
@BornToCode Về mặt kỹ thuật, điều này có nghĩa là bạn cần có một IP chuyên dụng và bạn cần sở hữu phần cứng máy chủ (hoặc ít nhất là VPS) để sử dụng HTTPS. Máy chủ web được chia sẻ không thể thực hiện HTTPS, trừ khi toàn bộ máy chủ được bảo vệ bằng chứng chỉ của chủ sở hữu máy chủ.
Calmarius

6
webhost chia sẻ chắc chắn có thể làm https, sử dụng en.wikipedia.org/wiki/Server_Name_Indication
Brian Minton

39

Xác thực an toàn là một chủ đề rộng lớn. Tóm lại, như @ jeremy-powell đã đề cập, luôn ưu tiên gửi thông tin đăng nhập qua HTTPS thay vì HTTP. Nó sẽ làm mất đi rất nhiều vấn đề đau đầu liên quan đến bảo mật.

Ngày nay, chứng chỉ TSL / SSL khá rẻ. Trên thực tế, nếu bạn không muốn tốn tiền thì có letsencrypt.org - Cơ quan cấp chứng chỉ tự động miễn phí .

Bạn có thể tiến thêm một bước nữa và sử dụng caddyserver.com gọi letsencrypt trong nền.

Bây giờ, khi chúng ta đã sử dụng được HTTPS ...

Bạn không nên gửi thông tin đăng nhập và mật khẩu qua tải trọng ĐĂNG hoặc tham số GET. Thay vào đó, hãy sử dụng tiêu đề Ủy quyền (Lược đồ xác thực quyền truy cập cơ bản), được xây dựng như sau:

  • Tên người dùng và mật khẩu được kết hợp thành một chuỗi được phân tách bằng dấu hai chấm, ví dụ: tên người dùng: mật khẩu
  • Chuỗi kết quả được mã hóa bằng biến thể RFC2045-MIME của Base64, ngoại trừ không giới hạn ở 76 ký tự / dòng.
  • Sau đó, phương thức ủy quyền và một khoảng trắng tức là "Cơ bản" được đặt trước chuỗi được mã hóa.

nguồn: Wikipedia: Tiêu đề ủy quyền

Nó có vẻ hơi phức tạp, nhưng không phải vậy. Có rất nhiều thư viện tốt sẽ cung cấp chức năng này cho bạn.

Có một vài lý do chính đáng để bạn nên sử dụng tiêu đề Ủy quyền

  1. Đó là một tiêu chuẩn
  2. Nó rất đơn giản (sau khi bạn học cách sử dụng chúng)
  3. Nó sẽ cho phép bạn đăng nhập ở cấp URL, như thế này: https://user:password@your.domain.com/login(Ví dụ : Chrome sẽ tự động chuyển nó thành Authorizationtiêu đề)

QUAN TRỌNG:
Như @zaph đã chỉ ra trong nhận xét của anh ấy bên dưới, việc gửi thông tin nhạy cảm dưới dạng truy vấn GET không phải là ý kiến ​​hay vì rất có thể nó sẽ xuất hiện trong nhật ký máy chủ.

nhập mô tả hình ảnh ở đây


11
Vấn đề với việc gửi thông tin xác thực (mật khẩu) dưới dạng tham số GET là cặp người dùng / mật khẩu có thể sẽ kết thúc trong nhật ký máy chủ, đây không phải là một ý kiến ​​hay. Tốt nhất là gửi thông tin đăng nhập trong một BÀI ĐĂNG.
zaph

Ahh ... không hề. Ảnh chụp màn hình bạn đang xem được sửa đổi để minh họa những gì đang xảy ra trong trình duyệt. Thời điểm bạn nhấn enter, trình duyệt sẽ chuyển đổi url của bạn tạo Authorizationtiêu đề. Cứ thử đi. Nhật ký sẽ nhắc nhở sạch sẽ. Và tất nhiên nếu bạn thực hiện cuộc gọi từ máy chủ (nếu đó là tình huống bạn đang lo lắng), tất nhiên bạn nên tạo tiêu đề theo chương trình.
FullStackForger

Bạn không thể ghi lại những gì bạn không thể nhìn thấy. username:password@urltừ trình duyệt dịch thành: url+ Authorizationtiêu đề yêu cầu. Đối với các truy vấn GET ... như tôi đã nói, hãy sử dụng tiêu đề Authroziation. Tốt hơn là.
FullStackForger

2
Bạn không giải quyết được mấu chốt của câu hỏi: bảo vệ dữ liệu nhạy cảm khỏi sự nghe trộm của kẻ trung gian. Trọng tâm không phải là tìm một cách thay thế và / hoặc cách tiêu chuẩn hóa hơn để vượt qua thông tin đăng nhập mà là bảo vệ chúng qua một kênh không an toàn.
Lord of the Goo,

3
Cần nhấn mạnh rằng giải pháp này chỉ hoạt động nếu bạn đang mã hóa kết nối bằng TLS / SSL. base64 không phải là mã hóa.
Scot

14

Bạn có thể sử dụng sơ đồ phản hồi thách thức. Giả sử cả máy khách và máy chủ đều biết một bí mật S. Sau đó, máy chủ có thể chắc chắn rằng máy khách biết mật khẩu (mà không cho nó đi) bằng cách:

  1. Máy chủ gửi một số ngẫu nhiên, R, cho máy khách.
  2. Máy khách gửi H (R, S) trở lại máy chủ (trong đó H là một hàm băm mật mã, như SHA-256)
  3. Máy chủ tính toán H (R, S) và so sánh nó với phản hồi của máy khách. Nếu chúng khớp, máy chủ biết máy khách biết mật khẩu.

Biên tập:

Có một vấn đề ở đây với sự mới mẻ của R và thực tế là HTTP không trạng thái. Điều này có thể được xử lý bằng cách yêu cầu máy chủ tạo một bí mật, gọi là Q, mà chỉ máy chủ biết . Sau đó, giao thức diễn ra như thế này:

  1. Máy chủ tạo ra một số ngẫu nhiên R. Sau đó nó sẽ gửi đến máy khách H (R, Q) (máy khách không thể giả mạo được).
  2. Máy khách gửi R, H (R, Q) và tính H (R, S) và gửi tất cả chúng trở lại máy chủ (trong đó H là một hàm băm mật mã, như SHA-256)
  3. Máy chủ tính toán H (R, S) và so sánh nó với phản hồi của máy khách. Sau đó, nó nhận R và tính (một lần nữa) H (R, Q). Nếu phiên bản H (R, Q) và H (R, S) của máy khách khớp với tính toán lại của máy chủ, máy chủ coi máy khách đã được xác thực.

Cần lưu ý, vì máy khách không thể giả mạo H (R, Q) nên H (R, Q) hoạt động như một cookie (và do đó có thể được triển khai thực sự như một cookie).

Chỉnh sửa khác:

Chỉnh sửa trước đó đối với giao thức không chính xác vì bất kỳ ai đã quan sát H (R, Q) dường như có thể phát lại nó với hàm băm chính xác. Máy chủ phải nhớ R không còn mới. Tôi đang xem câu trả lời này nên các bạn có thể chỉnh sửa câu trả lời này và tìm ra điều gì đó tốt.


+1 - bạn sẽ cần tính toán phản hồi ở phía máy khách bằng javascript (hoặc Flash / Silverlight / v.v.)
orip

10
Không ngăn chặn người đàn ông ở giữa hoặc các cuộc tấn công mạo danh. Ví dụ: thông qua wifi. Có vẻ như điều này sẽ chỉ mang lại cảm giác an toàn sai lầm, IMO.
Tom Hawtin - tackline 17/10/09

2
Điều đó bảo vệ khỏi các cuộc tấn công bị động, nhưng Người ở giữa vẫn có thể tấn công.
Douglas Leeder

7
Ngoài ra, nó yêu cầu máy chủ biết mật khẩu ban đầu.
Douglas Leeder

3
Đừng phát minh lại tiền điện tử! (đang sản xuất)
bryanph

11

Nếu máy chủ web của bạn cho phép hoặc bạn sẽ cần xử lý dữ liệu nhạy cảm, thì hãy sử dụng HTTPS. (Nó thường được yêu cầu bởi luật pháp afaik).

Ngược lại nếu bạn muốn thực hiện điều gì đó qua HTTP. Tôi sẽ làm một cái gì đó như thế này.

  1. Máy chủ nhúng khóa công khai của nó vào trang đăng nhập.
  2. Khách hàng điền biểu mẫu đăng nhập và bấm gửi.
  3. Một yêu cầu AJAX lấy dấu thời gian hiện tại từ máy chủ.
  4. Tập lệnh phía máy khách nối các thông tin xác thực, dấu thời gian và một muối (được băm từ dữ liệu tương tự, ví dụ: chuyển động chuột, sự kiện nhấn phím), mã hóa nó bằng khóa công khai.
  5. Gửi kết quả băm.
  6. Máy chủ giải mã hàm băm
  7. Kiểm tra xem dấu thời gian có đủ gần đây không (chỉ cho phép cửa sổ ngắn 5-10 giây). Từ chối đăng nhập nếu dấu thời gian quá cũ.
  8. Lưu trữ băm trong 20 giây. Từ chối cùng một băm để đăng nhập trong khoảng thời gian này.
  9. Xác thực người dùng.

Vì vậy, theo cách này, mật khẩu được bảo vệ và không thể phát lại cùng một băm xác thực.

Về tính bảo mật của mã thông báo phiên. Khó hơn một chút. Nhưng có thể khiến việc sử dụng lại mã thông báo phiên bị đánh cắp khó hơn một chút.

  1. Máy chủ đặt một cookie phiên bổ sung chứa một chuỗi ngẫu nhiên.
  2. Trình duyệt sẽ gửi lại cookie này vào yêu cầu tiếp theo.
  3. Máy chủ kiểm tra giá trị trong cookie, nếu nó khác thì nó sẽ hủy phiên, nếu không thì tất cả đều ổn.
  4. Máy chủ đặt lại cookie với văn bản khác.

Vì vậy, nếu mã thông báo phiên bị đánh cắp và một yêu cầu được gửi bởi người khác, thì theo yêu cầu tiếp theo của người dùng ban đầu, phiên sẽ bị hủy. Vì vậy, nếu người dùng tích cực duyệt trang web, nhấp vào các liên kết thường xuyên, thì kẻ trộm sẽ không đi xa với mã thông báo bị đánh cắp. Lược đồ này có thể được củng cố bằng cách yêu cầu một xác thực khác cho các hoạt động nhạy cảm (như xóa tài khoản).

CHỈNH SỬA: Xin lưu ý rằng điều này không ngăn chặn các cuộc tấn công MITM nếu kẻ tấn công thiết lập trang riêng của họ với khóa công khai khác và các yêu cầu proxy đến máy chủ. Để bảo vệ khỏi điều này, khóa công khai phải được ghim trong bộ nhớ cục bộ của trình duyệt hoặc trong ứng dụng để phát hiện các loại thủ thuật này.

Về cách triển khai: RSA có lẽ là thuật toán được biết đến nhiều nhất, nhưng nó khá chậm đối với các khóa dài. Tôi không biết việc triển khai PHP hoặc Javascript sẽ nhanh như thế nào. Nhưng có lẽ có một thuật toán nhanh hơn.


Trong trường hợp này, mật khẩu có thực sự được bảo vệ? Ai đó không thể phát hiện ra những gì được gửi và giải mã nó bằng cách sử dụng khóa công khai và sau đó chỉ cập nhật dấu thời gian khi họ sử dụng nó sau này? Tui bỏ lỡ điều gì vậy?
michaellindahl

@michaellindahl mã hóa không đối xứng có nghĩa là chỉ khóa riêng tư - không bao giờ rời khỏi máy chủ - có thể được sử dụng để giải mã mọi thứ. Khóa công khai chỉ có thể được sử dụng để mã hóa.
Dan Pantry

2
Một máy tính giữa trình duyệt và máy chủ có thể thay đổi khóa công khai trên trang đăng nhập.
Antti

Cảm ơn vì đã chia sẻ phương pháp của bạn, tôi thấy rất thú vị. Dấu thời gian được thêm vào khi gửi thông tin xác thực là một cách tốt! Một câu hỏi về vấn đề sử dụng cookie phiên bổ sung có giá trị là một chuỗi ngẫu nhiên: giống như một mã thông báo chỉ cho yêu cầu tiếp theo?
Victor

4

Tôi sẽ sử dụng hệ thống trao đổi khóa Diffie-Hellman phía máy chủ và phía máy khách với AJAX hoặc gửi nhiều biểu mẫu (tôi khuyên bạn nên gửi trước), mặc dù tôi không thấy bất kỳ triển khai tốt nào của hệ thống đó trên internet. Hãy nhớ rằng thư viện JS luôn có thể bị hỏng hoặc bị thay đổi bởi MITM. Lưu trữ cục bộ có thể được sử dụng để giúp chống lại điều này, ở một mức độ nào đó.


4

Bạn có thể sử dụng SRP để sử dụng mật khẩu an toàn qua một kênh không an toàn. Ưu điểm là ngay cả khi kẻ tấn công đánh hơi thấy lưu lượng truy cập hoặc xâm phạm máy chủ, chúng không thể sử dụng mật khẩu trên một máy chủ khác. https://github.com/alax/jsrp là một thư viện javascript hỗ trợ mật khẩu bảo mật qua HTTP trong trình duyệt hoặc phía máy chủ (thông qua nút).


1

HTTPS rất mạnh vì nó sử dụng mật mã không đối xứng. Loại mật mã này không chỉ cho phép bạn tạo một đường hầm được mã hóa mà còn có thể xác minh rằng bạn đang nói chuyện với đúng người chứ không phải tin tặc.

Đây là mã nguồn Java sử dụng mật mã không đối xứng RSA (được PGP sử dụng) để giao tiếp: http://www.hushmail.com/services/downloads/


0

bạn có thể sử dụng ssl cho máy chủ của mình, có dự án miễn phí cho ssl như letsencrypt https://letsencrypt.org/


2
Kiểm tra câu thứ ba trong câu hỏi. (Ngoài ra, luôn luôn đọc câu trả lời khác để đảm bảo bạn không thêm một bản sao ít chi tiết.)
Nathan Tuggy

0

Sử dụng https có vẻ là lựa chọn tốt nhất ở đây (hiện nay chứng chỉ không đắt như vậy). Tuy nhiên, nếu http là một yêu cầu, bạn có thể sử dụng một số mã hóa - mã hóa nó ở phía máy chủ và giải mã trong trình duyệt của người dùng (gửi khóa riêng).

Chúng tôi đã sử dụng điều đó trong khi triển khai safevia.net - mã hóa được thực hiện ở phía máy khách (người gửi / người nhận), vì vậy dữ liệu người dùng không có sẵn trên mạng cũng như lớp máy chủ.

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.