2009-03-26 39 views
13

Có thể ai đó vui lòng chỉ cho tôi hướng dẫn mới bắt đầu về các truy vấn SQL chạy một cách an toàn được hình thành một phần từ đầu vào của người dùng không? Tôi đang sử dụng Java, nhưng một hướng dẫn trung lập ngôn ngữ cũng tốt.Tôi nên làm vệ sinh đầu vào cơ sở dữ liệu bằng Java như thế nào?

Các hành vi mong muốn là nếu ai đó vào một cái gì đó giống như GUI

very nice;) DROP TABLE FOO;

Cơ sở dữ liệu nên đối xử với nó như là một chuỗi chữ và lưu trữ nó một cách an toàn mà không thả bất kỳ bảng.

Trả lời

5

Thông thường, bạn không nên tạo ra một truy vấn concatenating đầu vào, nhưng sử dụng PreparedStatement để thay thế.

Điều đó cho phép bạn chỉ định nơi bạn sẽ đặt thông số bên trong truy vấn của mình, vì vậy Java sẽ chăm sóc khử trùng tất cả các yếu tố đầu vào cho bạn.

3

PreparedStatement? Phải, chắc chắn rồi. Nhưng tôi nghĩ có thêm một bước nữa: xác thực đầu vào từ giao diện người dùng và ràng buộc với các đối tượng trước khi đến gần cơ sở dữ liệu.

tôi có thể nhìn thấy nơi ràng buộc một String trong PreparedStatement vẫn có thể để lại cho bạn dễ bị tổn thương đến một cuộc tấn công SQL injection:

String userInput = "Bob; DELETE FROM FOO"; 
String query = "SELECT * FROM FOO WHERE NAME = ?"; 

PreparedStatement ps = connection.prepareStatement(query); 
ps.setString(1, userInput); 
ps.executeQuery(); 

tôi ta phải thừa nhận rằng tôi đã không thử nó bản thân mình, nhưng nếu điều này là từ xa có thể tôi muốn nói PreparedStatement là cần thiết nhưng không đủ. Việc xác thực và ràng buộc ở phía máy chủ là chìa khóa.

Tôi khuyên bạn nên làm điều đó với API ràng buộc của Spring.

+0

Đây chính xác là loại tấn công mà các câu lệnh chuẩn bị nhằm bảo vệ chống lại. Nó sẽ thoát khỏi; – danieltalsky

+0

Về mặt kỹ thuật, giao diện PreparedStatement không đảm bảo nó. Mặc dù nếu trình điều khiển của bạn làm điều gì đó khác, hãy tìm một nhà cung cấp mới. –

+0

@daniel - Tôi sẽ phải thử và tự mình xem. Cho dù tôi có đúng về điều đó hay không, bạn có đồng ý rằng việc xác nhận hợp lệ phía máy chủ vẫn là một ý tưởng hay không? – duffymo

3

đầu vào sử dụng của bạn thực sự sẽ phải "Bob'; delete from foo; select '" (hoặc một cái gì đó như thế) nên có dấu ngoặc kép ngầm bổ sung bởi các tuyên bố chuẩn bị sẽ được đóng lại:

SELECT * FROM FOO WHERE NAME = 'Bob'; delete from foo; select '' 

nhưng nếu bạn làm điều đó mã tuyên bố chuẩn bị sẽ báo báo giá của bạn để bạn nhận được truy vấn thực tế của

SELECT * FROM FOO WHERE NAME = 'Bob''; delete from foo; select ''' 

và tên của bạn sẽ được lưu trữ là "Bob', delete from foo; select '" thay vì chạy nhiều truy vấn.

Các vấn đề liên quan