Chỉ vì mục đích chính (vì vậy bạn sẽ có ý tưởng tại sao Fred -ii- nói không sử dụng mã này) - Tôi sẽ phần nào giải quyết vấn đề này, theo thứ tự, khi tôi xem xét nó (nó không phải một nghiên cứu cá nhân về người đặt ra câu hỏi - nhưng chỉ để đưa ra ý tưởng rằng cố gắng xây dựng một ứng dụng an toàn nửa chừng trên ngăn xếp LAMP đòi hỏi một chút cẩn thận và suy tính trước ... và sự hoài nghi đẫm máu đi đôi với việc giả định điều tồi tệ nhất trong nhân loại giúp đỡ):
Điểm 1
Không phải là một vấn đề lớn - nhưng thực sự nếu bạn định bắt đầu một phiên, bạn nên bắt đầu một phiên bất kể có $_POST
hay không dữ liệu hay không. Bạn có thể nên yêu cầu tệp cấu hình của mình và bắt đầu phiên ở trên cùng trước bất kỳ thứ gì khác.
Không phải lỗi đầu cuối (vì bạn không xác thực phiên) - chỉ là kỳ lạ.
Điểm 2
Bạn có đầu ra trong tệp này (echo
) do đó nó phải ở dưới gốc tài liệu và có sẵn trong cây web.
include("config.php");
Điều này không thực sự được viết đúng cách, nó có thể phải là require_once 'config.php';
(giả sử đó là tệp chương trình bắt buộc và không phải là tệp bao gồm tùy chọn có thể được phép không thành công) nhưng đó là không phải lỗi. Lỗi là bạn có tệp cấu hình bên trong gốc tài liệu của mình. Về mặt lý thuyết, cấu hình sai máy chủ hoặc lỗi đánh máy đơn giản trong tệp đó có thể cho phép nội dung của tệp đó xuất ra màn hình dưới dạng văn bản thuần túy, có khả năng tiết lộ chuỗi kết nối cơ sở dữ liệu của bạn (và ai biết được điều gì khác) với world + dog.
Các tệp cấu hình phải tồn tại bên ngoài cây web hoặc, nếu không, bên trong một thư mục được bảo vệ bằng một thứ gì đó như .htaccess
Deny from all
. Chúng sẽ không bao giờ có thể truy cập được qua HTTP.
Điểm 3
mysql
thư viện không được dùng nữa và hoàn toàn không nên được sử dụng; MySQLi hoặc PDO là cách để đi, lý tưởng nhất là với các tham số / giá trị ràng buộc:
Cá nhân tôi đã nhận được cho PDO.
Điểm 4 &5
$password = mysql_real_escape_string(stripslashes(md5($_POST['password'])));
Trước hết, thứ tự của điều này là sai. Bạn đang băm $_POST['password']
và sau đó cố gắng cắt dải - sẽ không có bất kỳ dấu gạch chéo nào sau khi nó được băm. Tuy nhiên, nếu bạn đang cố gắng ngăn mọi người sử dụng dấu gạch chéo (hoặc bất cứ thứ gì) trong mật khẩu, bạn cần xóa chúng trước khi băm chuỗi.
Tiếp theo md5
không nên được sử dụng như một thuật toán băm mật khẩu, nó được cho là yếu và có thể bị buộc phải tạo ra xung đột chuỗi thường xuyên hơn nhiều so với mức cần thiết.
Có, bạn nên chỉ lưu trữ hàm băm hoặc "dấu vân tay" của mật khẩu thay vì chính mật khẩu, nhưng lý tưởng nhất là bạn muốn muối và băm (với ít nhất sha1
) những mật khẩu đó thay vì chỉ ném chúng vào md5()
chức năng.
Xem: http://uk3.php.net/mcrypt chẳng hạn
Và thực hiện tìm kiếm "băm ướp muối mật khẩu" bằng công cụ tìm kiếm bạn chọn.
Điểm 6
SELECT id FROM $table
WHERE username = '" . $username . "'
and password = '" . $password . "';
Tôi đã thêm vào =
bị thiếu trong câu hỏi ban đầu, nhưng vẫn không khớp về tên người dùng và mật khẩu trong truy vấn của bạn ... nếu ai đó quản lý để đưa SQL vào tên người dùng của bạn, mật khẩu sẽ không bao giờ được kiểm tra. Hãy tưởng tượng:
SELECT user.id
FROM user WHERE user.username = 'fred' OR 1 = 1
-- AND user.password = 'abc123'
Tốt hơn nên chọn id người dùng và dấu vân tay mật khẩu từ cơ sở dữ liệu và sau đó đánh giá mật khẩu trong ứng dụng hơn là tin tưởng kiểm tra mật khẩu trong lớp cơ sở dữ liệu. Điều đó cũng có nghĩa là bạn có thể sử dụng thuật toán băm và ướp muối chuyên dụng trong chính ứng dụng để xác thực mật khẩu của mình.
Điểm 7
$_SESSION['user'] = $_POST["username"];
Đây chỉ là lưu trữ tên người dùng trong phiên? Điều này không nên được sử dụng như một "trình xác minh đăng nhập", đặc biệt là vì (dường như) không có gì trong phiên của bạn để ngăn chặn hijacking .
Id phiên có thể dễ dàng bị phát hiện từ cookie của phiên trực tiếp và đó là tất cả những gì cần thiết để "mượn" thông tin đăng nhập của người khác. Ít nhất bạn nên cố gắng giảm thiểu nguy cơ phiên bị chiếm quyền điều khiển bằng cách liên kết địa chỉ IP của người dùng, chuỗi UserAgent hoặc một số kết hợp dữ liệu tương đối tĩnh khác mà bạn có thể so sánh với trên mọi trang ... mặc dù vậy, trên thực tế bất kỳ cách tiếp cận nào cũng có những hạn chế (đặc biệt, như tôi đã tìm thấy, nếu bạn có khách truy cập sử dụng AOL) - nhưng bạn có thể tạo dấu vân tay phiên hiệu quả hơn 99% để giảm thiểu xâm nhập với rất ít khả năng phiên của người dùng bị kết xuất sai.
Lý tưởng nhất là bạn cũng có thể muốn tạo mã thông báo cho phiên để giảm thiểu CSRF tấn công khi người dùng cần thực hiện một hành động "đặc quyền" trên cơ sở dữ liệu (cập nhật thông tin chi tiết của họ hoặc bất cứ điều gì). Mã thông báo có thể là một mã hoàn toàn ngẫu nhiên và duy nhất được lưu trữ trong cơ sở dữ liệu và / hoặc trong cookie SSL khi người dùng đăng nhập (giả sử người dùng không thể thực hiện bất kỳ hành động nào cập nhật cơ sở dữ liệu bên ngoài HTTPS vì điều đó sẽ chỉ truyền dữ liệu bằng văn bản rõ ràng trên Internet - đó sẽ là một ý tưởng tồi ).
Mã thông báo được đưa vào trường biểu mẫu ẩn cho bất kỳ / tất cả các biểu mẫu và được kiểm tra với giá trị được lưu trữ trong cookie (hoặc phiên hoặc cơ sở dữ liệu) bất cứ khi nào biểu mẫu đó được gửi. Điều này đảm bảo rằng người gửi biểu mẫu ít nhất có một phiên trực tiếp trên trang web của bạn.