Những thực hành tốt nhất nên được sử dụng trong một kịch bản đăng nhập PHP?


27

Tôi muốn viết lại tập lệnh đăng nhập của mình cho các trang web của khách hàng để làm cho chúng an toàn hơn. Tôi muốn biết những gì thực hành tốt nhất tôi có thể thực hiện trong này. Các bảng điều khiển được bảo vệ bằng mật khẩu rất phong phú, nhưng dường như rất ít người thực hiện các biện pháp tốt nhất về cách viết mã, tốc độ và bảo mật.

Tôi sẽ sử dụng PHP và cơ sở dữ liệu MYSQL.

Tôi đã từng sử dụng md5, nhưng tôi thấy rằng sha256 hoặc sha512 sẽ tốt hơn (cùng với băm và muối an toàn).

Một số tập lệnh đăng nhập ghi lại địa chỉ IP trong suốt phiên hoặc thậm chí là tác nhân người dùng, nhưng tôi muốn tránh điều đó vì nó không tương thích với máy chủ proxy.

Tôi cũng chậm hơn một chút so với thực tiễn tốt nhất trong việc sử dụng các phiên trong PHP 5 (lần trước tôi đọc lên là PHP 4) vì vậy một số thực tiễn tốt nhất với điều này sẽ hữu ích.

Cảm ơn.


1
Tung tập lệnh của bạn trên codereview.SE!
Chris

@Chris CodeReview giúp mã rõ ràng và tương tự. Bạn chắc chắn không nên đến với họ để bảo mật. Nếu có bất cứ điều gì, họ hầu như sẽ luôn nhắc nhở bạn đừng "tự lăn lộn", đây là câu trả lời cơ bản giống như anh ấy sẽ tham gia vào bất kỳ cộng đồng lập trình nào trên SE.
Alternatex

Câu trả lời:


21

Suy nghĩ tốt nhất là không phát minh lại bánh xe. Nhưng, tôi hiểu, trong thế giới PHP, có thể khó tìm thấy một thành phần chất lượng cao đã làm điều đó (thậm chí tôi khá chắc chắn rằng các khung công tác thực hiện những điều đó và việc triển khai của chúng đã được kiểm tra, vững chắc, được xem xét mã, v.v. )

Nếu, vì một số lý do, bạn không thể sử dụng khung, đây là một số gợi ý:

Đề xuất liên quan đến bảo mật

  • Sử dụng PBKDF2 hoặc Bcrypt nếu bạn có thể . Nó đã được thực hiện cho điều đó.

    Đặt vấn đề: cả hai thuật toán có thể làm cho quá trình băm chậm tùy ý, đó chính xác là những gì bạn muốn khi băm mật khẩu (các lựa chọn thay thế nhanh hơn có nghĩa là lực lượng vũ phu dễ dàng hơn). Tốt nhất, bạn nên điều chỉnh các tham số để quá trình trở nên chậm hơn và chậm hơn theo thời gian trên cùng một phần cứng, trong khi phần cứng mới, nhanh hơn được phát hành.

  • Nếu bạn không thể, ít nhất đừng sử dụng MD5 / SHA1. Không bao giờ. Hãy quên nó đi . Sử dụng SHA512 thay thế, ví dụ. Dùng muối cũng vậy.

    Đặt vấn đề: MD5 và SHA1 quá nhanh. Nếu kẻ tấn công có quyền truy cập vào cơ sở dữ liệu của bạn có chứa các giá trị băm và có một máy mạnh mẽ (thậm chí không đặc biệt), thì việc buộc mật khẩu sẽ nhanh chóng và dễ dàng. Nếu không có muối, khả năng kẻ tấn công tìm thấy mật khẩu thực sự tăng lên (điều này có thể gây hại thêm nếu mật khẩu được sử dụng lại ở nơi khác).

  • Trong PHP 5.5.0 trở lên, sử dụng password_hashpassword_verify.

    Đặt vấn đề: gọi một chức năng được cung cấp bởi khung là dễ dàng, vì vậy nguy cơ mắc lỗi sẽ giảm. Với hai hàm này, bạn không phải suy nghĩ về các tham số khác nhau, chẳng hạn như hàm băm. Hàm đầu tiên trả về một chuỗi đơn sau đó có thể được lưu trữ trong cơ sở dữ liệu. Hàm thứ hai sử dụng chuỗi này để xác minh mật khẩu.

  • Bảo vệ bạn khỏi lực lượng vũ phu . Nếu người dùng gửi mật khẩu sai khi cô ấy đã gửi một mật khẩu sai khác 0,01 giây trước, đó là một lý do tốt để chặn mật khẩu. Trong khi con người có thể đánh máy nhanh, có lẽ họ không thể nhanh.

    Một biện pháp bảo vệ khác là đặt giới hạn thất bại mỗi giờ. Nếu người dùng gửi 3600 mật khẩu sai trong một giờ, 1 mật khẩu mỗi giây, thật khó để tin rằng đây là người dùng hợp pháp.

    Đặt vấn đề: nếu mật khẩu của bạn được băm theo cách không an toàn, lực lượng vũ phu có thể rất hiệu quả. Nếu mật khẩu được lưu trữ an toàn, lực lượng vũ trang vẫn đang lãng phí tài nguyên và băng thông mạng của máy chủ của bạn, gây ra hiệu suất thấp hơn cho người dùng hợp pháp. Phát hiện lực lượng vũ phu không dễ để phát triển và làm cho đúng, nhưng đối với bất kỳ hệ thống nhỏ bé nào, nó hoàn toàn xứng đáng.

  • Đừng yêu cầu người dùng của bạn thay đổi mật khẩu của họ sau mỗi bốn tuần. Điều này cực kỳ khó chịu và làm giảm tính bảo mật, vì nó khuyến khích bảo mật dựa trên nó.

    Đặt vấn đề: ý tưởng buộc mật khẩu thay đổi cứ sau n tuần bảo vệ hệ thống khỏi lực lượng vũ phu là sai. Các cuộc tấn công vũ phu thường thành công trong vòng vài giây, vài phút, vài giờ hoặc vài ngày, điều này làm cho các thay đổi mật khẩu hàng tháng không liên quan. Mặt khác, người dùng rất tệ trong việc ghi nhớ mật khẩu. Nếu, hơn nữa, họ cần thay đổi chúng, họ sẽ cố gắng sử dụng mật khẩu rất đơn giản hoặc chỉ lưu ý mật khẩu của họ trên post-it.

  • Kiểm toán mọi thứ, mọi lúc. Lưu trữ đăng nhập, nhưng không bao giờ lưu trữ mật khẩu trong nhật ký kiểm toán. Đảm bảo rằng nhật ký kiểm toán không thể được sửa đổi (nghĩa là bạn có thể thêm dữ liệu vào cuối, nhưng không sửa đổi dữ liệu hiện có). Hãy chắc chắn rằng nhật ký kiểm toán phải được sao lưu thường xuyên. Tốt nhất, các bản ghi nên được lưu trữ trên một máy chủ chuyên dụng có quyền truy cập rất hạn chế: nếu một máy chủ khác bị hack, kẻ tấn công sẽ không thể xóa sạch các bản ghi để che giấu sự hiện diện của anh ta (và đường dẫn được thực hiện trong cuộc tấn công).

  • Đừng nhớ thông tin xác thực người dùng trong cookie, trừ khi người dùng yêu cầu làm điều đó (Hộp kiểm Ghi nhớ tôi phải được bỏ chọn theo mặc định để tránh lỗi của con người).

Đề xuất dễ sử dụng

  • Hãy để người dùng nhớ mật khẩu nếu cô ấy muốn, ngay cả khi hầu hết các trình duyệt đã có tính năng này.
  • Không sử dụng phương pháp tiếp cận của Google khi thay vì hỏi tên người dùng và mật khẩu, đôi khi người dùng chỉ được hỏi mật khẩu , tên người dùng đã được hiển thị trong a <span/>. Các trình duyệt không thể điền vào trường mật khẩu trong trường hợp này (ít nhất Firefox không thể làm điều đó), do đó, nó buộc phải đăng xuất, sau đó đăng nhập bằng một hình thức thông thường, được trình duyệt điền vào.
  • Không sử dụng cửa sổ bật lên hỗ trợ JavaScript để đăng nhập. Nó phá vỡ các tính năng ghi nhớ mật khẩu của trình duyệt (và hút trong mọi trường hợp).
  • Cho phép người dùng nhập tên người dùng hoặc địa chỉ thư của cô ấy . Khi tôi đăng ký, đôi khi tên người dùng tôi muốn nhập đã được sử dụng, vì vậy tôi phải phát minh ra một tên mới. Tôi có tất cả cơ hội để quên tên này trong hai giờ.
  • Luôn giữ liên kết đến tính năng "Quên mật khẩu của tôi" gần biểu mẫu đăng nhập. Không chỉ hiển thị khi người dùng không đăng nhập được: người dùng hoàn toàn không nhớ mật khẩu của mình mà không biết rằng cô ấy phải gửi nhầm để xem liên kết "Quên mật khẩu của tôi".
  • Đừng sử dụng bảo mật bằng cách đăng nó .
  • Đừng phát minh ra các quy tắc ngu ngốc liên quan đến mật khẩu để làm cho nó yếu hơn . Ví dụ: "Mật khẩu của bạn phải bắt đầu bằng một chữ cái viết thường."; "Mật khẩu của bạn không thể chứa dấu cách."

Không đi qua bcrypt. Lý do của bạn để đề nghị đó là gì? Tại sao không phải md5 / sha1? Cảm ơn cho phần còn lại của các đề xuất!
baritoneuk

Lý do rất đơn giản: bcryptđược thực hiện bởi những người có trình độ cao. Nó cũng đã được thử nghiệm, xem xét, v.v. Vì vậy, không có lý do gì để tự thực hiện điều tương tự. Nó giống như tạo thuật toán mật mã của riêng bạn cho trang web của bạn. * "Tại sao không phải là md5 / sha1?": Xem ví dụ en.wikipedia.org/wiki/MD5#Securance
Arseni Mourzenko

5
bcrypt chậm và như được đề cập bởi các chuyên gia. md5 là một thuật toán băm không phải là một mã hóa không hoàn toàn giống nhau. Băm một tệp nhanh là tốt, md5 sẽ được sử dụng ở đây ... băm mật khẩu không cần quá nhanh, bcrypt có thể giúp ở đây. Lý do tôi nói điều này là lực lượng vũ phu trở nên khó khăn hơn khi thuật toán mật mã "chậm".
Chris

2
@baritoneuk: tối thiểu là mát mẻ. Nhưng tôi không thể đếm được có bao nhiêu trang web tôi đã truy cập có các hạn chế như độ dài tối đa , không có các ký tự không phải là chữ và số, v.v. , họ chỉ lưu trữ nó trong cơ sở dữ liệu của họ rõ ràng.
Carson63000

1
@Brian Ortiz: không phải lúc nào cũng vậy. Đôi khi nó là một ý tưởng tốt để thiết lập một giới hạn. Nếu bạn không làm điều đó, bạn có kiểm tra xem ứng dụng của bạn có hoạt động được không? Làm sao? Nếu bạn không kiểm tra nó, làm thế nào bạn có thể chắc chắn nếu nó hoạt động? Thay vào đó, khi đặt giới hạn cho một giá trị hợp lý, như 100, bạn có thể dễ dàng kiểm tra mật khẩu 100 ký tự.
Arseni Mourzenko

6
  1. Trang web của bạn nên sử dụng HTTPS. Bạn không nên trình bày một trang đăng nhập hoặc chấp nhận đăng nhập từ một kết nối không được mã hóa.
  2. Cookie của bạn nên được giới hạn chỉ ở HTTP được giới hạn ở các kết nối an toàn nếu bạn sử dụng HTTPS.
  3. Quá trình đăng nhập sẽ mất không dưới 2 giây (1 nếu bạn nghĩ 2 giây là quá dài). Sử dụng hàm băm an toàn khi lưu trữ và xác minh mật khẩu và sử dụng loại muối khó đoán hơn. Sử dụng bcryptnếu có thể. Nếu không, sử dụng một số loại băm lặp khác.
  4. Không bao giờ soạn các truy vấn cơ sở dữ liệu của bạn theo bất kỳ cách nào yêu cầu sử dụng các hàm như mysql_real_escape_string. Không bao giờ sử dụng nối chuỗi để tạo truy vấn của bạn. Sử dụng các truy vấn chuẩn bị, tham số. Hầu hết, nếu không phải tất cả, trình điều khiển DB cho PHP hỗ trợ nó. Nếu bạn không biết làm thế nào để làm điều đó, hãy dành một số thời gian học tập làm thế nào để prepare, bindexecutesử dụng bất cứ điều gì DB bạn đang sử dụng. Đó là cách chắc chắn duy nhất để bảo vệ bạn trước việc tiêm SQL. PDO hỗ trợ này.
  5. Khuyến khích người dùng của bạn không sử dụng cùng một mật khẩu họ sử dụng cho email của họ. Nhắc nhở họ rằng nếu trang web của bạn bị xâm phạm và nếu họ sử dụng cùng một mật khẩu ở cả hai nơi, ai đó có thể chiếm quyền điều khiển email của họ.

+1 cho HTTPS, vì ngày càng có nhiều lưu lượng truy cập thông qua các mạng WiFi công cộng. Nhưng tôi không đồng ý với quan điểm 3: 2 giây là quá dài từ quan điểm của người dùng. 0,5 s. là tốt, đặc biệt là nếu các kỹ thuật chống vũ phu khác được sử dụng.
Arseni Mourzenko

Tôi đang bối rối về điểm số 4. Làm thế nào để bạn thoát khỏi quy ước thoát dữ liệu với mysql_real_escape_opes? Tất cả dữ liệu người dùng gửi không nên được tin cậy và lọc theo.
chrisw

@chrisw: Có, tất cả đầu vào của người dùng nên được xử lý như thể nó độc hại. Nhưng khi bạn sử dụng các truy vấn tham số, thì không có cách nào tốt nhất để ngăn chặn việc tiêm SQL . Nếu bạn không sử dụng các truy vấn đã chuẩn bị và tham số hóa, bạn dễ bị SQL tiêm. mysql_real_escape_stringlà bảo mật sai - nó không phải là một sự đảm bảo. Truy vấn tham số là.
greyfade

Bây giờ tôi đồng ý sau khi đọc thêm về nó. Hàm: mysql_real_escape_opes thường an toàn cho hầu hết các phần, tôi sẽ không coi đó là trách nhiệm lớn, nhưng tôi có thể thấy cách sử dụng các câu lệnh được chuẩn bị hiệu quả hơn nhiều.
chrisw

1
Bạn có thể sử dụng PDO.
Felix G

1

Sử dụng hàm băm một chiều (tốt nhất là SHA512 bằng cách sử dụng http://au2.php.net/manual/en/feft.hash.php ) ... theo cách đó, nếu ai đó hack cơ sở dữ liệu của bạn, ngay cả khi họ biết muối , họ không thể trích xuất mật khẩu (không có bảng cầu vồng, sẽ rất lỏng lẻo cho SHA512).

Sử dụng HTTPS.

Không gửi xác nhận tên người dùng / mật khẩu qua email lại cho người dùng khi họ đăng ký.

Nếu bạn cho phép cookie để 'nhớ tôi' - hãy thêm thông tin đăng nhập để truy cập chức năng quản trị và chỉnh sửa hồ sơ.

Nếu người dùng nhận được mật khẩu sai, đừng nói rằng họ đã nhập sai mật khẩu (nói rằng họ đã nhận được 'tên người dùng hoặc mật khẩu sai') - theo cách đó, sẽ ít manh mối hơn về tên người dùng hợp lệ.

Hãy thử và triển khai tên màn hình so với đăng nhập - theo cách đó, ít người dùng sẽ hiển thị tên đăng nhập của họ trên danh sách người dùng.


Hoàn toàn đồng ý với bit về việc không gửi email bằng văn bản đơn giản bằng email. Tôi đã mất số lần các trang web làm điều này. Nếu bạn có 1 mật khẩu cho tất cả các trang web (điều may mắn là tôi không có) thì có khả năng tất cả các trang web đều bị xâm phạm. Các trang web như vậy có thể lưu trữ mật khẩu trong văn bản đơn giản quá. thở dài
baritoneuk

1
  • Không bao giờ sử dụng thuật toán băm MD5 hoặc SHA1. Luôn bám sát những cái mới hơn như SHA512
  • Luôn luôn sử dụng muối được tạo ngẫu nhiên mạnh
  • Không bao giờ gửi email cho người dùng mật khẩu của họ, ngay cả trong trường hợp "Quên mật khẩu"
  • Không bao giờ sử dụng các hàm mysql_ *. Họ đã khấu hao lâu. Bám sát PDO
  • Không bao giờ lưu trữ mật khẩu trong phiên hoặc cookie

0

Dưới đây là một lời khuyên: hãy đảm bảo rằng cookie của bạn không thể được truy cập bằng JS để ngăn chặn hành vi trộm cắp, hãy xem Bảo vệ cookie của bạn: Bài viết trên http: //Only của Jeff Atwood

... Thông qua việc xây dựng thông minh, URL không đúng định dạng chỉ có thể rít qua bộ khử trùng. Mã kết xuất cuối cùng, khi được xem trong trình duyệt, tải và thực thi một tập lệnh từ máy chủ từ xa đó.

... Bất cứ ai tải trang hồ sơ người dùng được tiêm tập lệnh này đều vô tình truyền cookie trình duyệt của họ đến một máy chủ từ xa độc ác!

Như chúng tôi đã thiết lập, một khi ai đó có cookie trình duyệt của bạn cho một trang web nhất định, về cơ bản họ có chìa khóa để vương quốc cho danh tính của bạn ở đó ...

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.