Show
Một vài năm trước, tôi đã tham dự Laracon EU, nơi Marcus Bointon đã có một bài nói chuyện tuyệt vời về Tiền điện tử trong PHP 7. 2. Tôi rời buổi nói chuyện với sự đánh giá cao hơn nhiều về mức độ phức tạp của mật mã, cũng như cách PHP làm cho mã hóa dễ tiếp cận hơn nhờ sự ra đời của Sodium. Mã hóa dữ liệu trong PHP rất quan trọng đối với công việc của tôi trên SpinupWP, một bảng điều khiển máy chủ dựa trên đám mây có quyền truy cập gốc vào hàng nghìn máy chủ và trang web và tôi nghĩ sẽ rất hữu ích nếu chia sẻ những gì tôi đã học được kể từ đó. Thắt dây an toàn, vì đây có thể là một chuyến đi gập ghềnh Các loại mã hóaCó nhiều phương pháp mã hóa khác nhau được sử dụng ngày nay, phổ biến nhất là mã hóa băm, mã hóa khóa bí mật và mã hóa phong bì. Ngoài ra, mỗi phương pháp mã hóa có nhiều thuật toán hoặc mật mã để lựa chọn (mỗi thuật toán có điểm mạnh và điểm yếu riêng). Trong bài viết này, chúng ta sẽ xem xét triển khai cả ba phương pháp mã hóa bămThuật toán băm lấy một giá trị đầu vào và chuyển đổi nó thành một đầu ra có độ dài cố định được gọi là "thông báo tóm tắt", "giá trị băm" hoặc đơn giản là "băm". Băm là một cách duy nhất, có nghĩa là cách duy nhất để xác thực đầu ra được băm là chuyển giá trị ban đầu cho thuật toán băm và so sánh kết quả. Điều này làm cho hàm băm trở nên hoàn hảo để lưu trữ mật khẩu người dùng Điều đáng chú ý là băm không phải là một giải pháp chống đạn và không phải tất cả các thuật toán băm đều như nhau. Hãy xem xét MD5 và SHA1 nhanh và hiệu quả, khiến chúng trở nên lý tưởng để tổng kiểm tra và xác minh tệp. Tuy nhiên, tốc độ của chúng khiến chúng không phù hợp để băm mật khẩu của người dùng Với sức mạnh tính toán ngày nay của CPU/GPU hiện đại và điện toán đám mây, mật khẩu băm có thể bị bẻ khóa bằng vũ lực chỉ trong vài phút. Việc nhanh chóng tạo ra hàng tỷ hàm băm MD5 từ các từ ngẫu nhiên cho đến khi tìm thấy kết quả phù hợp là điều khá đơn giản, do đó tiết lộ mật khẩu văn bản gốc ban đầu. Thay vào đó, nên sử dụng các thuật toán băm chậm hơn có chủ ý như bcrypt hoặc Argon2 Mặc dù mật khẩu băm được tạo bởi bất kỳ thuật toán nào chắc chắn sẽ che khuất dữ liệu gốc và làm chậm bất kỳ kẻ tấn công tiềm năng nào, chúng tôi với tư cách là nhà phát triển nên cố gắng sử dụng thuật toán mạnh nhất hiện có. May mắn thay, PHP giúp việc này trở nên dễ dàng nhờ có 4
Hàm 4 không chỉ sử dụng thuật toán băm một chiều an toàn mà còn tự động xử lý và ngăn chặn các cuộc tấn công kênh phụ dựa trên thời gian. Hàm chấp nhận một 6 để được mã hóa và một thuật toán băm 7. Kể từ PHP 5. 5, bcrypt ( 8), dựa trên mật mã Blowfish, sẽ được sử dụng làm thuật toán băm mặc định. Các phiên bản sau của PHP đã giới thiệu Argon2 (PHP 7. 2) và Argon2id (PHP 7. 3) thuật toán, nhưng bcrypt vẫn là mặc định. Trên thực tế, bên cạnh những cải tiến đối với hàm 4, các tùy chọn có sẵn được coi là an toàn đến mức không có thuật toán mới nào được đưa vào ngôn ngữ cho cả PHP 8. 0 hoặc PHP8. 1Có thể sử dụng Argon2 hoặc Argon2id, nếu phiên bản PHP của bạn đã được biên dịch với sự hỗ trợ của Argon2, bằng cách chuyển hằng số 0 hoặc 1 làm đối số 7 của hàm 4. Để kiểm tra thuật toán nào được hỗ trợ trên máy chủ web của bạn, bạn có thể khởi chạy chế độ tương tác PHP từ dòng lệnh máy chủ và chạy hàm 4. Dưới đây là một ví dụ về đầu ra của lệnh đó trên máy chủ SpinupWP tiêu chuẩn, nơi có cả ba tùy chọn
Xác minh mật khẩu của người dùng cũng là một quy trình đơn giản nhờ chức năng 5. Chỉ cần chuyển mật khẩu văn bản gốc do người dùng cung cấp và so sánh nó với hàm băm được lưu trữ, như vậy
Lưu ý cách xác minh mật khẩu được thực hiện trong PHP. Nếu bạn đang lưu trữ thông tin đăng nhập của người dùng trong cơ sở dữ liệu, bạn có thể có xu hướng băm mật khẩu được nhập khi đăng nhập và sau đó thực hiện truy vấn SQL cơ sở dữ liệu, như vậy
Cách tiếp cận này dễ bị tấn công kênh bên và nên tránh. Thay vào đó, hãy trả lại người dùng và sau đó kiểm tra hàm băm mật khẩu trong PHP
Mặc dù băm rất tốt để mã hóa mật khẩu, nhưng nó không hoạt động đối với dữ liệu tùy ý mà ứng dụng của chúng tôi cần truy cập mà không có sự can thiệp của người dùng. Hãy xem xét một ứng dụng thanh toán mã hóa thông tin thẻ tín dụng của người dùng, thường được lưu từ biểu mẫu HTML. (Với các yêu cầu tuân thủ PCI và pháp lý có liên quan, chúng tôi khuyên bạn không nên xây dựng ứng dụng thanh toán của riêng mình, thay vào đó hãy sử dụng thứ gì đó như Stripe. Chúng tôi chỉ sử dụng điều này làm ví dụ). Mỗi tháng, ứng dụng của chúng tôi cần lập hóa đơn cho người dùng cho việc sử dụng tháng trước của họ. Băm dữ liệu thẻ tín dụng sẽ không hoạt động vì nó yêu cầu ứng dụng của chúng tôi có thể giải mã dữ liệu được băm, như chúng tôi đã chỉ ra trước đó, không thể thực hiện được với việc băm Mã hóa khóa bí mật để giải cứu Mã hóa khóa bí mậtMã hóa khóa bí mật (hay còn gọi là mã hóa đối xứng) sử dụng một khóa duy nhất để mã hóa và giải mã dữ liệu. Trước đây, PHP dựa vào mcrypt và openssl để mã hóa khóa bí mật. PHP7. 2 giới thiệu Natri, hiện đại hơn và được coi là an toàn hơn. Nếu bạn đang chạy phiên bản PHP cũ hơn, bạn có thể cài đặt Natri qua Thư viện cộng đồng tiện ích mở rộng PHP hay còn gọi là PECL Để mã hóa một giá trị, trước tiên, bạn cần có khóa mã hóa, khóa này có thể được tạo bằng hàm 6
Bạn cũng có thể sử dụng hàm 7 với hằng số nguyên 8 cho độ dài khóa, nhưng việc sử dụng 6 đảm bảo rằng độ dài khóa luôn chính xác (i. e. không quá ngắn), và nó dễ dàng hơn
Dù bằng cách nào, bạn thường chỉ thực hiện việc này một lần và lưu kết quả dưới dạng biến môi trường. Hãy nhớ rằng khóa này phải được giữ bí mật bằng mọi giá. Nếu khóa đã từng bị xâm phạm, thì bất kỳ dữ liệu nào được mã hóa bằng cách sử dụng nó cũng vậy Để mã hóa giá trị ban đầu, hãy chuyển giá trị đó tới hàm 0 với 1 và một 2 được tạo. Để tạo nonce, hãy sử dụng hàm 7, với hằng số nguyên 4 cho độ dài nonce, vì cùng một nonce sẽ không bao giờ được sử dụng lại
Điều này gây ra sự cố vì chúng tôi cần nonce để giải mã giá trị sau này. May mắn thay, các nonce không cần phải được giữ bí mật nên chúng ta có thể thêm nó vào trước giá trị 5 rồi 6 trước khi lưu nó vào cơ sở dữ liệu
Điều này sẽ tạo ra một chuỗi được mã hóa base64 có độ dài 76 ký tự Khi đến phần giải mã giá trị thì làm ngược lại, bắt đầu từ việc giải mã chuỗi mã hóa base64 0Bởi vì chúng tôi biết độ dài của nonce ( 4), chúng tôi có thể trích xuất nó bằng cách sử dụng 8 trước khi giải mã giá trị 1Đó là tất cả để mã hóa khóa bí mật trong PHP, nhờ có Natri Mã hóa phong bìMặc dù cách tiếp cận nêu trên chắc chắn là một bước đi đúng hướng nhưng nó vẫn khiến dữ liệu của chúng ta dễ bị tổn thương nếu khóa bí mật bị xâm phạm. Hãy xem xét một người dùng độc hại có quyền truy cập vào máy chủ lưu trữ ứng dụng của chúng tôi. Họ sẽ không quanh quẩn trên máy chủ để giải mã bất kỳ dữ liệu nhạy cảm nào. Thay vào đó, họ sẽ tạo một bản sao của dữ liệu và tất cả các tệp có liên quan trên cơ sở hạ tầng của riêng họ và làm việc để khám phá khóa bí mật mà chúng tôi đã sử dụng để mã hóa dữ liệu. Điều này khiến dữ liệu của chúng tôi bị lộ hoàn toàn Giải pháp đơn giản là không lưu trữ khóa bí mật của chúng tôi ở cùng vị trí với dữ liệu được mã hóa, nhưng điều này gây ra sự cố. Làm thế nào để chúng tôi mã hóa và giải mã theo yêu cầu? . Các công ty cung cấp cơ sở hạ tầng đám mây như AWS và Google đều có dịch vụ riêng. Là một hướng dẫn nhanh, chúng tôi sẽ tập trung vào KMS trên nền tảng đám mây của Google Google Cloud KMSCloud KMS là một dịch vụ do Google cung cấp để lưu trữ an toàn các khóa mật mã. Nó cung cấp nhiều tính năng hữu ích xung quanh việc lưu trữ khóa, bao gồm xoay khóa tự động và hủy khóa bị trì hoãn. Tuy nhiên, chúng tôi chủ yếu quan tâm đến việc lưu trữ khóa bí mật riêng biệt với ứng dụng của mình Để làm cho mọi thứ an toàn hơn, chúng tôi sẽ sử dụng một kỹ thuật được gọi là mã hóa phong bì. Về cơ bản, mã hóa phong bì liên quan đến việc mã hóa các khóa bằng một khóa khác. Chúng tôi làm điều này vì hai lý do
Thay vì gửi dữ liệu văn bản gốc của chúng tôi tới Cloud KMS, chúng tôi sẽ tạo một khóa mã hóa duy nhất mỗi khi chúng tôi ghi dữ liệu nhạy cảm vào cơ sở dữ liệu. Khóa này được gọi là khóa mã hóa dữ liệu (DEK), sẽ được sử dụng để mã hóa dữ liệu của chúng tôi. DEK sau đó được gửi tới Cloud KMS để được mã hóa, trả về khóa mã hóa khóa (được gọi là KEK). Cuối cùng, KEK được lưu trữ song song trong cơ sở dữ liệu bên cạnh dữ liệu được mã hóa và DEK bị hủy. Quá trình trông giống như vậy
Khi giải mã dữ liệu, quá trình này bị đảo ngược
Đám mây KMS và PHPGiống như hầu hết các dịch vụ Google Cloud, có một dịch vụ mà chúng ta có thể sử dụng trong các ứng dụng PHP của mình. Tài liệu Cloud KMS khá phong phú, nhưng tôi khuyên bạn nên bắt đầu với hướng dẫn Bắt đầu nhanh và hướng dẫn Xác thực, hướng dẫn này sẽ đưa bạn qua tất cả các yêu cầu Yêu cầu KMS trên đám mâyTrước tiên, bạn cần tạo một tài khoản Google Cloud và tạo một dự án Google Cloud mới. Sau đó, bạn kích hoạt Cloud KMS API và cài đặt, khởi tạo Cloud SDK. Bước này cho phép bạn chạy công cụ dòng lệnh 9 mà bạn sử dụng để tạo khóa Cloud KMS, là một phần của khóa Cloud KMS và tồn tại ở một vị trí Cloud KMS. Cuối cùng, bạn cần tạo một , cấp quyền cho tài khoản dịch vụ dựa trên dự án và sau đó lưu trữ thông tin đăng nhập tài khoản dịch vụ trong tệp thông tin đăng nhập cục bộMặc dù tất cả điều này có vẻ như cần rất nhiều công việc để thiết lập, nhưng tài liệu Google Cloud thực sự hữu ích trong việc hướng dẫn bạn thực hiện các bước Triển khai đám mây KMS PHPVới suy nghĩ này, tôi đã tạo một lớp trình trợ giúp rất đơn giản để thực hiện mã hóa phong bì, lớp này sử dụng Google Cloud KMS SDK. Tôi sẽ không xem xét mã sẵn sàng sản xuất này vì nó có thể sử dụng một số cách xử lý lỗi tốt hơn, nhưng nó cho bạn một nơi để bắt đầu. Lớp trình trợ giúp này sử dụng phiên bản mới nhất của Google Cloud KMS SDK, hiện đang ở phiên bản 1. 12 2Bạn sẽ nhận thấy rằng các phương thức mã hóa và giải mã thực tế gần giống với cách triển khai khóa bí mật được giới thiệu ở trên. Tuy nhiên, sự khác biệt là chúng tôi hiện đang sử dụng nhiều khóa mã hóa. Hãy xem hoạt động của lớp trợ giúp Cách sử dụng KeyManagerĐể sử dụng lớp trình trợ giúp này, bạn sẽ cần bắt đầu một dự án mới với sự hỗ trợ của Trình soạn thảo, cài đặt gói 0 và đảm bảo yêu cầu trình tải tự động Trình soạn thảo. Sau đó, bạn sẽ cần thiết lập hằng số 1, sử dụng tệp thông tin xác thực mà bạnCuối cùng, bạn cần thiết lập các biến 2, 3, 4 và 5 mà bạn so khớp các giá trị khi bạn. Sau đó, bạn có thể tạo một phiên bản mới của lớp KeyManager và sử dụng nó để mã hóa và giải mã 3Nếu bạn muốn xem mã này hoạt động, tôi đã tạo một kho lưu trữ GitHub để thiết lập mọi thứ cho việc triển khai đơn giản này Nếu kẻ tấn công xâm phạm hệ thống của chúng tôi, họ vẫn có thể có quyền truy cập vào triển khai Cloud KMS API của chúng tôi và sử dụng quyền đó để giải mã mọi dữ liệu được mã hóa mà họ có thể đã sao chép. Nếu đúng như vậy, bạn có thể tự hỏi làm thế nào mã hóa phong bì an toàn hơn mã hóa khóa bí mật thông thường? Sự khác biệt chính (ý định chơi chữ) là quyền truy cập API KMS có thể bị thu hồi, do đó ngăn kẻ tấn công giải mã bất kỳ dữ liệu nào mà chúng đã tạo ra. Với mã hóa khóa bí mật thông thường trong đó một khóa cục bộ duy nhất bị xâm phạm, bạn không có được sự xa xỉ đó. Kẻ tấn công có toàn bộ thời gian để giải mã dữ liệu nhạy cảm của bạn, sử dụng khóa cục bộ. Mã hóa phong bì không phải là một giải pháp hoàn hảo, nhưng nó chắc chắn làm giảm nguy cơ vi phạm dữ liệu của bạn WordPress và dữ liệu nhạy cảmMột câu hỏi phổ biến mà tôi thấy trong giới phát triển WordPress là; . Thông thường, đây là các plugin hoặc chủ đề cần có khả năng truy cập một số API của bên thứ ba (ví dụ: dịch vụ MailChimp hoặc AWS), xác thực bằng khóa truy cập API và đôi khi là khóa truy cập bí mật. Một ví dụ như vậy là WP Offload Media của riêng chúng tôi, phương tiện này cần thông tin đăng nhập truy cập vào nhà cung cấp bộ nhớ ngoại vi của bạn Nói chung, có hai tùy chọn chính để triển khai các chi tiết truy cập này
Thực tế là, bất kể bạn làm gì, nếu mã của bạn có thể đọc được bí mật, thì bất kỳ kẻ tấn công có động cơ nào cũng có thể đọc được. Như chúng ta đã thảo luận, ngay cả mã hóa phong bì cũng không hoàn toàn an toàn và với tư cách là nhà phát triển plugin, bạn có ít quyền kiểm soát hơn đối với các phương thức mã hóa dành cho chủ sở hữu trang web Theo ý kiến của tôi, tốt hơn hết là giáo dục người dùng của bạn về bảo mật. Đảm bảo rằng bạn có sẵn tài liệu mà họ có thể sử dụng để vô hiệu hóa quyền truy cập API của bên thứ ba tại nguồn nếu xảy ra vi phạm. Đảm bảo rằng tài liệu của bạn bao gồm các khía cạnh như cách giới hạn khả năng đọc hoặc ghi đối với các dịch vụ của bên thứ ba. Ví dụ: gần đây chúng tôi đã cập nhật tài liệu về nhà cung cấp dịch vụ lưu trữ sao lưu SpinupWP với thông tin chi tiết về cách Nếu bạn làm việc với chủ sở hữu trang web, hãy dạy họ cách cập nhật lõi, plugin và chủ đề WordPress, cũng như phiên bản PHP của họ, để ngăn chặn các lỗ hổng; . Nếu họ cần truy cập máy chủ, hãy đảm bảo rằng họ đang sử dụng xác thực khóa SSH và SFTP để quản lý tệp Việc thay ổ khóa vào nhà của bạn sau khi ai đó đánh cắp chìa khóa của bạn là điều tốt và tốt, nhưng tốt hơn hết là đừng bao giờ để chìa khóa của bạn bị đánh cắp ngay từ đầu kết thúcBảo mật và mã hóa dữ liệu là những chủ đề rộng lớn và tôi chỉ đề cập đến một số cách để bảo vệ dữ liệu nhạy cảm bằng PHP. Tuy nhiên, cuối cùng, bất kỳ mã hóa nào bạn triển khai vẫn dễ bị tấn công, mức độ rủi ro chỉ khác nhau. Biết các loại khác nhau có nghĩa là bạn có thể chọn triển khai chúng ở các cấp độ khác nhau của mã ứng dụng, tùy thuộc vào mức độ nhạy cảm của dữ liệu của bạn Bạn có những biện pháp phòng ngừa nào? Mục nhập này đã được đăng trong WP Migrate DB Pro, Phát triển plugin và được gắn thẻ Phát triển, Bảo mật, PHP, Mã hóa, Băm, Mật khẩu Thông tin về các Tác giảAshley giàu cóAshley là một Laravel và Vue. js quan tâm sâu sắc đến công cụ cho lưu trữ WordPress, hiệu suất máy chủ và bảo mật. Trước khi gia nhập Delicious Brains, Ashley đã phục vụ trong Lực lượng Không quân Hoàng gia với tư cách là Kỹ thuật viên CNTT @A5hleyRich Ashleyrich. com
|