Thực tiễn tốt nhất: Mật khẩu muối & tiêu?


145

Tôi đã bắt gặp một cuộc thảo luận trong đó tôi biết rằng những gì tôi đang làm thực tế không phải là mật khẩu muối mà là tiêu chúng và tôi đã bắt đầu thực hiện cả hai với một chức năng như:

hash_function($salt.hash_function($pepper.$password)) [multiple iterations]

Bỏ qua thuật toán băm đã chọn (tôi muốn đây là một cuộc thảo luận về muối và ớt và không phải là thuật toán cụ thể nhưng tôi đang sử dụng một thuật toán an toàn), đây có phải là một lựa chọn an toàn hay tôi nên làm gì đó khác đi? Đối với những người không quen thuộc với các điều khoản:

  • Một muối là một giá trị được tạo ngẫu nhiên thường được lưu trữ với các chuỗi trong cơ sở dữ liệu được thiết kế để làm cho nó không thể sử dụng bảng băm để crack mật khẩu. Vì mỗi mật khẩu đều có muối riêng, tất cả chúng phải được ép buộc riêng lẻ để bẻ khóa chúng; tuy nhiên, vì muối được lưu trữ trong cơ sở dữ liệu với hàm băm mật khẩu, thỏa hiệp cơ sở dữ liệu có nghĩa là mất cả hai.

  • Một tiêu là một giá trị tĩnh trang web rộng lưu trữ riêng biệt từ cơ sở dữ liệu (thường là mã hóa cứng trong mã nguồn của ứng dụng) được dự định là bí mật. Nó được sử dụng để thỏa hiệp cơ sở dữ liệu sẽ không khiến bảng mật khẩu của toàn bộ ứng dụng bị cưỡng bức.

Có bất cứ điều gì tôi thiếu và đang muối và tiêu mật khẩu của tôi là lựa chọn tốt nhất để bảo vệ an ninh người dùng của tôi? Có bất kỳ lỗ hổng bảo mật tiềm năng để làm điều này theo cách này?

Lưu ý: Giả sử cho mục đích thảo luận rằng ứng dụng và cơ sở dữ liệu được lưu trữ trên các máy riêng biệt, không chia sẻ mật khẩu, v.v ... vì vậy vi phạm máy chủ cơ sở dữ liệu không tự động có nghĩa là vi phạm máy chủ ứng dụng.


3
Không hoàn toàn trùng lặp, nhưng cực kỳ liên quan: stackoverflow.com/questions/16594613/ trên
ircmaxell

2
Trang web trùng lặp trùng lặp: security.stackexchange.com/q/3272/2113
Jacco

Câu trả lời:


306

Đồng ý. Thấy như tôi cần phải ghi về điều này hơnhơn , tôi sẽ làm một câu trả lời kinh điển cuối cùng trên tiêu một mình.

Ưu điểm rõ ràng của Peppers

Có vẻ khá rõ ràng rằng ớt nên làm cho chức năng băm an toàn hơn. Ý tôi là, nếu kẻ tấn công chỉ lấy được cơ sở dữ liệu của bạn, thì mật khẩu người dùng của bạn sẽ được bảo mật, phải không? Có vẻ hợp lý, phải không?

Đó là lý do tại sao rất nhiều người tin rằng ớt là một ý tưởng tốt. Nó "có ý nghĩa".

Thực tế của Peppers

Trong các lĩnh vực bảo mật và mật mã, "có ý nghĩa" là không đủ. Một cái gì đó phải được chứng minh có ý nghĩa để nó được coi là an toàn. Ngoài ra, nó phải được thực hiện theo cách có thể bảo trì. Hệ thống an toàn nhất không thể bảo trì được coi là không an toàn (bởi vì nếu bất kỳ phần nào của bảo mật đó bị hỏng, toàn bộ hệ thống sẽ sụp đổ).

Và ớt không phù hợp với các mô hình có thể chứng minh được hoặc có thể bảo trì ...

Các vấn đề lý thuyết với Peppers

Bây giờ chúng ta đã thiết lập giai đoạn, hãy xem xét những gì sai với ớt.

  • Cho ăn một băm vào một cái khác có thể nguy hiểm.

    Trong ví dụ của bạn, bạn làm hash_function($salt . hash_function($pepper . $password)).

    Chúng tôi biết từ kinh nghiệm trong quá khứ rằng "chỉ cho ăn" một kết quả băm vào một hàm băm khác có thể làm giảm tính bảo mật tổng thể. Lý do là cả hai hàm băm có thể trở thành mục tiêu tấn công.

    Đó là lý do tại sao các thuật toán như PBKDF2 sử dụng các hoạt động đặc biệt để kết hợp chúng (hmac trong trường hợp đó).

    Vấn đề là trong khi nó không phải là một vấn đề lớn, nó cũng không phải là một điều tầm thường để ném xung quanh. Các hệ thống tiền điện tử được thiết kế để tránh các trường hợp "nên hoạt động" và thay vào đó tập trung vào các trường hợp "được thiết kế để hoạt động".

    Mặc dù điều này có vẻ hoàn toàn là lý thuyết, nhưng thực tế không phải vậy. Ví dụ, Bcrypt không thể chấp nhận mật khẩu tùy ý . Vì vậy, vượt qua bcrypt(hash(pw), salt)thực sự có thể dẫn đến một băm yếu hơn nhiều so với bcrypt(pw, salt)nếu hash()trả về một chuỗi nhị phân.

  • Làm việc chống lại thiết kế

    Cách bcrypt (và các thuật toán băm mật khẩu khác) được thiết kế là để làm việc với một muối. Khái niệm về một hạt tiêu không bao giờ được giới thiệu. Điều này có vẻ như tầm thường, nhưng nó không phải là. Lý do là một muối không phải là một bí mật. Nó chỉ là một giá trị mà kẻ tấn công có thể biết. Mặt khác, một hạt tiêu, theo định nghĩa là một bí mật mật mã.

    Các thuật toán băm mật khẩu hiện tại (bcrypt, pbkdf2, v.v.) tất cả đều được thiết kế để chỉ nhận một giá trị bí mật (mật khẩu). Thêm một bí mật khác vào thuật toán chưa được nghiên cứu.

    Điều đó không có nghĩa là nó không an toàn. Điều đó có nghĩa là chúng ta không biết nó có an toàn không. Và khuyến nghị chung với bảo mật và mật mã là nếu chúng ta không biết, thì không.

    Vì vậy, cho đến khi các thuật toán được thiết kế và hiệu đính bởi các nhà mật mã để sử dụng với các giá trị bí mật (ớt), các thuật toán hiện tại không nên được sử dụng với chúng.

  • Sự phức tạp là kẻ thù của an ninh

    Dù bạn có tin hay không, sự phức tạp là kẻ thù của an ninh . Làm cho một thuật toán có vẻ phức tạp có thể an toàn hoặc có thể không. Nhưng cơ hội khá quan trọng là nó không an toàn.

Các vấn đề quan trọng với Peppers

  • Nó không thể duy trì

    Việc thực hiện ớt của bạn ngăn cản khả năng xoay phím tiêu. Vì hạt tiêu được sử dụng ở đầu vào cho hàm một chiều, bạn không bao giờ có thể thay đổi hạt tiêu trong suốt vòng đời của giá trị. Điều này có nghĩa là bạn cần phải đưa ra một số hack mạnh mẽ để có được nó để hỗ trợ xoay vòng phím.

    Điều này cực kỳ quan trọng vì nó được yêu cầu bất cứ khi nào bạn lưu trữ bí mật mật mã. Không có cơ chế xoay khóa (định kỳ và sau khi vi phạm) là một lỗ hổng bảo mật rất lớn.

    Và phương pháp tiêu hiện tại của bạn sẽ yêu cầu mọi người dùng phải hoàn toàn vô hiệu hóa mật khẩu của họ bằng cách xoay hoặc đợi cho đến khi đăng nhập tiếp theo của họ để xoay (có thể không bao giờ) ...

    Mà về cơ bản làm cho cách tiếp cận của bạn ngay lập tức không đi.

  • Nó yêu cầu bạn phải cuộn tiền điện tử của riêng bạn

    Vì không có thuật toán hiện tại nào hỗ trợ khái niệm hạt tiêu, nên nó yêu cầu bạn phải soạn thảo thuật toán hoặc phát minh ra thuật toán mới để hỗ trợ hạt tiêu. Và nếu bạn không thể thấy ngay tại sao đó là một điều thực sự tồi tệ:

    Bất cứ ai, từ người nghiệp dư không biết gì nhất đến người viết mật mã giỏi nhất, đều có thể tạo ra một thuật toán mà chính anh ta không thể phá vỡ.

    KHÔNG BAO GIỜ cuộn tiền điện tử của riêng bạn ...

Cách tốt hơn

Vì vậy, trong số tất cả các vấn đề chi tiết ở trên, có hai cách xử lý tình huống.

  • Chỉ cần sử dụng các thuật toán khi chúng tồn tại

    Nếu bạn sử dụng bcrypt hoặc mã hóa chính xác (với chi phí cao), tất cả các mật khẩu từ điển yếu nhất sẽ được an toàn về mặt thống kê. Kỷ lục hiện tại về băm bcrypt với chi phí 5 là 71k băm mỗi giây. Với tốc độ đó, ngay cả mật khẩu ngẫu nhiên 6 ký tự cũng sẽ mất nhiều năm để bẻ khóa. Và xem xét chi phí đề xuất tối thiểu của tôi là 10, điều đó làm giảm giá trị băm mỗi giây xuống 32 lần. Vì vậy, chúng tôi chỉ nói về khoảng 2200 băm mỗi giây. Ở tốc độ đó, thậm chí một số cụm từ trong từ điển hoặc sửa đổi có thể an toàn.

    Ngoài ra, chúng ta nên kiểm tra các loại mật khẩu yếu đó trước cửa và không cho phép chúng vào. Vì việc bẻ khóa mật khẩu ngày càng tiến bộ, do đó, yêu cầu chất lượng mật khẩu cũng vậy. Đây vẫn là một trò chơi thống kê, nhưng với kỹ thuật lưu trữ phù hợp và mật khẩu mạnh, mọi người nên thực sự rất an toàn ...

  • Mã hóa Hash đầu ra trước khi lưu trữ

    Có tồn tại trong lĩnh vực bảo mật, một thuật toán được thiết kế để xử lý mọi thứ chúng ta đã nói ở trên. Đó là một mật mã khối. Điều đó tốt, bởi vì nó có thể đảo ngược, vì vậy chúng tôi có thể xoay các phím (yay! Khả năng bảo trì!). Nó tốt vì nó được sử dụng như thiết kế. Điều đó tốt bởi vì nó cung cấp cho người dùng không có thông tin.

    Hãy nhìn vào dòng đó một lần nữa. Giả sử kẻ tấn công biết thuật toán của bạn (cần thiết để bảo mật, nếu không, nó bảo mật thông qua che khuất). Với cách tiếp cận tiêu truyền thống, kẻ tấn công có thể tạo mật khẩu trọng điểm và vì anh ta biết muối và đầu ra, anh ta có thể vũ phu ép hạt tiêu. Ok, đó là một cú sút xa, nhưng nó có thể. Với một mật mã, kẻ tấn công không nhận được gì. Và vì muối được chọn ngẫu nhiên, mật khẩu trọng tâm thậm chí sẽ không giúp anh ấy / cô ấy. Vì vậy, điều tốt nhất họ còn lại là tấn công các hình thức được mã hóa. Điều đó có nghĩa là trước tiên họ phải tấn công hàm băm được mã hóa của bạn để khôi phục khóa mã hóa và sau đó tấn công băm. Nhưng có rất nhiều nghiên cứu về sự tấn công của mật mã, vì vậy chúng tôi muốn dựa vào đó.

TL / DR

Đừng dùng ớt. Có một loạt vấn đề với họ, và có hai cách tốt hơn: không sử dụng bất kỳ bí mật phía máy chủ nào (vâng, nó ổn) và mã hóa hàm băm đầu ra bằng cách sử dụng mật mã khối trước khi lưu trữ.


6
Cảm ơn vì đã bao gồm phần cuối cùng của việc mã hóa giá trị băm, đây là câu trả lời tôi hoàn toàn có thể đồng ý. Nếu mã hóa trở thành một phần của mật khẩu api của bạn , sẽ không có lý do gì để không sử dụng nó, vì vậy có lẽ ... (tôi rất thích viết tài liệu cho nó)
martinstoeckli

2
@martinstoeckli: Tôi sẽ không đồng ý thêm bước mã hóa vào API băm đơn giản hóa. Lý do là việc lưu trữ bí mật (chìa khóa) khó hơn rất nhiều so với mọi người nhận ra và việc bắn vào chân bạn khá dễ dàng. Đối với 99,9% người dùng ngoài kia, bcrypt thô là quá đủ cho tất cả nhưng mật khẩu đơn giản nhất ...
ircmaxell

7
@ircmaxell - Ở phía bên kia, bạn sẽ chẳng mất gì cả. Trong trường hợp xấu nhất, khi khóa được biết đến, kẻ tấn công vẫn phải bẻ khóa băm BCrypt (tình huống tương tự như không có mã hóa). Điều này không giống như lưu trữ khóa để mã hóa dữ liệu, đây là về việc thêm một bí mật phía máy chủ. Ngay cả một khóa mã hóa cứng cũng sẽ bảo vệ các mật khẩu yếu đó, miễn là kẻ tấn công không có quyền kiểm soát máy chủ / mã. Tình huống này không phải là hiếm gặp: ngoài SQL-tiêm, còn vứt bỏ các bản sao lưu, các máy chủ bị loại bỏ có thể dẫn đến tình huống này. Rất nhiều người dùng PHP làm việc trên các máy chủ được lưu trữ.
martinstoeckli

2
@martinstoeckli Tôi sẽ phải đồng ý với ircmaxwell ở đây, tôi không nghĩ rằng mã hóa thuộc về mật khẩu api. Mặc dù, có thể lưu ý rằng để bảo mật tối đa mã hóa băm của bạn là một điều khoản bổ sung có thể được sử dụng.
foochow

Tôi có một câu hỏi liên quan đến mã hóa đầu ra trước khi lưu trữ. Nếu tôi không nhầm, các khóa mã hóa thường được sử dụng để mã hóa các tin nhắn duy nhất hoặc tạm thời. Tuy nhiên, nếu bạn có 200.000 mật khẩu người dùng, tất cả được mã hóa với cùng một khóa và được lưu trữ cùng nhau, điều đó có làm cho việc tấn công khóa dễ dàng hơn không? Bây giờ bạn có 200.000 tin nhắn, so với chỉ 1 hoặc 2.
AgmLauncher

24

Nắm tay chúng ta nên nói về lợi thế chính xác của hạt tiêu :

  • Hạt tiêu có thể bảo vệ mật khẩu yếu khỏi một cuộc tấn công từ điển, trong trường hợp đặc biệt, nơi kẻ tấn công có quyền truy cập đọc vào cơ sở dữ liệu (chứa băm) nhưng không có quyền truy cập vào mã nguồn với hạt tiêu.

Một kịch bản điển hình sẽ là SQL-SQL, vứt bỏ các bản sao lưu, các máy chủ bị loại bỏ ... Những tình huống này không phổ biến như âm thanh và thường không thuộc quyền kiểm soát của bạn (lưu trữ máy chủ). Nếu bạn dùng...

  • Một loại muối duy nhất cho mỗi mật khẩu
  • Một thuật toán băm chậm như BCrypt

... mật khẩu mạnh được bảo vệ tốt. Gần như không thể tạo ra một mật khẩu mạnh trong những điều kiện đó, ngay cả khi muối được biết đến. Vấn đề là mật khẩu yếu, là một phần của từ điển vũ phu hoặc là dẫn xuất của chúng. Một cuộc tấn công từ điển sẽ tiết lộ những điều đó rất nhanh, bởi vì bạn chỉ kiểm tra các mật khẩu phổ biến nhất.

Câu hỏi thứ hai là làm thế nào để áp dụng hạt tiêu ?

Một cách thường được đề xuất để áp dụng một hạt tiêu, là kết hợp mật khẩu và hạt tiêu trước khi chuyển nó vào hàm băm:

$pepperedPassword = hash_hmac('sha512', $password, $pepper);
$passwordHash = bcrypt($pepperedPassword);

Có một cách khác thậm chí còn tốt hơn:

$passwordHash = bcrypt($password);
$encryptedHash = encrypt($passwordHash, $serverSideKey);

Điều này không chỉ cho phép thêm một bí mật phía máy chủ, nó còn cho phép trao đổi $ serverSideKey, nếu điều này là cần thiết. Phương pháp này liên quan đến công việc nhiều hơn một chút, nhưng nếu mã đã tồn tại (thư viện) thì không có lý do gì để không sử dụng nó.


Vì vậy, bạn muốn nói rằng một hạt tiêu có thêm an ninh chỉ trong một muối, nói ngắn gọn? Cảm ơn sự giúp đỡ về cách thực hiện.
Glitch Desire

1
@LightningDust - Có, đối với mật khẩu yếu, miễn là hạt tiêu được giữ bí mật. Nó giảm nhẹ một số loại mối đe dọa được xác định rõ.
martinstoeckli

@martinstoeckli chắc chắn là một cách tốt để thực hiện điều này. Thật tốt khi thấy ai đó có một số kinh nghiệm bảo mật hỗ trợ phương pháp này. Một AES_ENCRYPT($passwordHash, $serverSideKey)cuộc gọi MySQL cũng sẽ là một cách thích hợp để thực hiện điều này?
foochow

1
@Foo_Chow - Tôi không biết việc triển khai chức năng MySQL, nhưng có vẻ như họ đã sử dụng chế độ EBC, để tránh vectơ IV. Cùng với bản rõ đã biết (giá trị băm luôn bắt đầu bằng cùng một ký tự), đây có thể là một vấn đề. Trên trang chủ của tôi, tôi đã xuất bản một triển khai ví dụ, xử lý mã hóa này.
martinstoeckli

@martinstoeckli thú vị, không quá quen thuộc với các khái niệm; tuy nhiên có vẻ như một IV sẽ được mong muốn cho kết quả mạnh mẽ nhất. Dường như không thêm nhiều chi phí cho lợi ích gia tăng.
foochow

2

Điểm của muối và hạt tiêu là tăng chi phí tra cứu mật khẩu được tính toán trước, được gọi là bảng cầu vồng.

Nói chung, cố gắng tìm một xung đột cho một hàm băm duy nhất là khó (giả sử hàm băm là an toàn). Tuy nhiên, với các giá trị băm ngắn, có thể sử dụng máy tính để tạo tất cả các giá trị băm có thể thành tra cứu trên đĩa cứng. Đây được gọi là Bảng cầu vồng. Nếu bạn tạo một bảng cầu vồng, sau đó bạn có thể đi ra thế giới và nhanh chóng tìm thấy mật khẩu hợp lý cho bất kỳ hàm băm (không được đánh giá cao) nào.

Quan điểm của hạt tiêu là làm cho bảng cầu vồng cần thiết để hack danh sách mật khẩu của bạn trở nên độc đáo. Do đó, lãng phí nhiều thời gian hơn cho kẻ tấn công để xây dựng bảng cầu vồng.

Tuy nhiên, điểm quan trọng của muối là làm cho bảng cầu vồng cho mỗi người dùng là duy nhất cho người dùng, làm tăng thêm độ phức tạp của cuộc tấn công.

Thực sự quan điểm của bảo mật máy tính là gần như không bao giờ làm cho nó (về mặt toán học) là không thể, chỉ là không thực tế về mặt toán học và vật lý (ví dụ trong các hệ thống bảo mật, sẽ cần tất cả entropy trong vũ trụ (và hơn thế nữa) để tính toán mật khẩu của một người dùng).


Vì vậy, một muối + hạt tiêu cung cấp bất kỳ bảo mật hơn so với chỉ một muối? Hoặc tôi sẽ tốt hơn khi bỏ hạt tiêu và chạy nhiều lần lặp lại của tiền điện tử?
Glitch Desire

2
Điều chính về bảng cầu vồng là bạn không tạo một bảng cho một cuộc tấn công cụ thể, bạn tải xuống một bảng có sẵn. Có các bảng cầu vồng dài có sẵn cho các thuật toán băm phổ biến chỉ là một google!
Richard

1
@LightningDust Tôi không thể nghĩ ra bất kỳ lý do nào. Tuy nhiên Richard trong một chủ đề khác đã đưa ra một. Bạn có thể ẩn hạt tiêu trong mã nguồn của mình, điều đó có nghĩa là một nơi khác mà kẻ tấn công của bạn cần có quyền truy cập, chỉ để có được một bảng cầu vồng cùng nhau.
Aron

@Aron - Vâng, đó là những gì tôi nghĩ, vì chúng tôi có các máy chủ ứng dụng tách biệt với các máy chủ cơ sở dữ liệu (nghĩa là, nếu bạn roottruy cập vào máy chủ db của chúng tôi, bạn vẫn không có quyền truy cập vào máy chủ ứng dụng của chúng tôi), mà ẩn tiêu trong mã nguồn (trong tập tin cấu hình của chúng tôi) sẽ cung cấp bảo mật bổ sung.
Glitch Desire

1

Không thể thấy việc lưu trữ một giá trị được mã hóa cứng trong mã nguồn của bạn là có liên quan đến bảo mật. Đó là bảo mật thông qua che khuất.

Nếu một hacker lấy được cơ sở dữ liệu của bạn, anh ta sẽ có thể bắt đầu vũ phu ép buộc mật khẩu người dùng của bạn. Sẽ không mất nhiều thời gian để hacker đó xác định hạt tiêu của bạn nếu anh ta quản lý để bẻ khóa một vài mật khẩu.


1
Nó sẽ làm cho một bảng cầu vồng được tính toán trước cho một bảng mật khẩu không được mã hóa trở nên vô dụng. Nói tóm lại, ngay cả khi kẻ tấn công biết hạt tiêu của bạn, anh ta sẽ cần tạo một bàn cầu vồng mới.
Aron

3
Nó tăng cường băm dựa trên dữ liệu không có sẵn trong cơ sở dữ liệu, đó là một điều tốt. Những thứ trong cơ sở dữ liệu có thể được tiết lộ trong các lỗ hổng - ít có khả năng một giá trị trong mã sẽ được truy cập theo cùng một cách.
Richard

Muối là chức năng một chiều, thậm chí vũ phu thành công - việc buộc mật khẩu sẽ chỉ cung cấp cho bạn mật khẩu đó và sẽ không giúp bạn có được giá trị hạt tiêu.
Glitch Desire

1
@LightningDust Tôi nghĩ bạn có nghĩa là "Băm là các chức năng bẫy". Có, không thể tìm ra muối và / hoặc hạt tiêu của bạn từ hàm băm an toàn (thực tế đó là định nghĩa của hàm băm an toàn).
Aron

6
@Aron Security Through Obscurance có thể là một kỹ thuật hợp lệ được sử dụng như một lớp phòng thủ. Vấn đề là nó không bao giờ nên được dựa vào như một phòng thủ, mà thay vào đó được sử dụng để "làm chậm kẻ tấn công". Nếu đó không phải là trường hợp, một cái gì đó như honeypot sẽ không được sử dụng. Thay vào đó, chúng tôi có thể sử dụng bảo mật một cách hiệu quả thông qua che khuất để giúp những kẻ tấn công làm chậm, miễn là chúng tôi không dựa vào nó để bảo mật cho ứng dụng của mình.
ircmaxell
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.