2010-03-08 54 views
58

Tôi sử dụng API dự kiến ​​một chuỗi SQL. Tôi lấy đầu vào của người dùng, thoát nó và chuyển nó vào API. Đầu vào của người dùng khá đơn giản. Nó yêu cầu các giá trị cột. Cũng giống như vậy:Cách thoát khỏi các truy vấn SQL đơn giản trong C# cho SqlServer

string name = userInput.Value; 

Sau đó, tôi xây dựng một truy vấn SQL:

string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'", 
          name.replace("'", "''")); 

Đây có phải là đủ an toàn? Nếu không, có chức năng thư viện đơn giản làm cho các giá trị cột an toàn:

string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'", 
          SqlSafeColumnValue(name)); 

API sử dụng SQLServer làm cơ sở dữ liệu.

+3

Bạn ** cần ** để sử dụng thông số. – SLaks

+1

@SLaks, Hiển nhiên API không cho phép. Có lẽ anh ta cần một API mới. –

+3

@sri bạn sẽ nhận được câu trả lời tốt hơn nếu bạn giải thích lý do tại sao bạn không thể/sẽ không sử dụng thông số. – Foole

Trả lời

87

Kể từ khi sử dụng SqlParameter không phải là một lựa chọn, chỉ cần thay thế 'với ''(đó là hai dấu nháy đơn, không phải là một trích dẫn kép) trong chuỗi ký tự. Đó là nó.

Đối với các trình gỡ xuống sẽ là: đọc lại dòng đầu tiên của câu hỏi. "Sử dụng các thông số" cũng là phản ứng ruột của tôi.

EDIT: có, tôi biết về các cuộc tấn công SQL injection. Nếu bạn cho rằng trích dẫn này dễ bị tổn thương, vui lòng cung cấp thông tin phản hồi hoạt động. Tôi nghĩ là không.

+2

-1: Và điều đó bảo vệ chống lại những thứ như Little Bobby như thế nào? (http://xkcd.com/327/ nếu bạn không biết điều đó có nghĩa là gì). Trong khi các tham số có thể không phải là một lựa chọn, giải pháp thay thế đơn với dấu ngoặc kép chắc chắn không phải là 'nó' như trạng thái câu trả lời của bạn. –

+11

Có một chút 'sau Robert. Như thế đấy. Khi được trích dẫn đúng cách, tên không chính thống của Bobby sẽ được lưu trữ trong toàn bộ cơ sở dữ liệu. –

+0

Tôi đang nói theo nghĩa bóng. Bạn sẽ không có dấu ngoặc kép, ví dụ, đối số dạng số. Đó là loại * đó là vấn đề, không phải là ví dụ chính xác. (Ví dụ, cú pháp chính xác đó sẽ không hoạt động với SQL Server, nhưng vấn đề vẫn được áp dụng.) –

2

đơn giản:

const string sql = "SELECT * FROM SOME_TABLE WHERE Name = @name"; 

và thêm tham số @name với giá trị:

cmd.CommandText = sql; 
cmd.Parameters.AddWithValue("@name", name); 
+30

Anh ta vẫn cần lấy câu lệnh SQL thực tế ra khỏi đối tượng lệnh để chuyển tới API. – manu08

-10

Nếu bạn cần phải thoát khỏi một chuỗi cho một truy vấn MSSQL thử điều này:

System.Security.SecurityElement.Escape(Value) 
+8

Xin lỗi Kevin nhưng chức năng Escape chỉ thoát XML không SQL (http://msdn.microsoft.com/en-us/library/system.security.securityelement.escape.aspx) –

0

Tôi đã sử dụng sql năng động (Tôi có thể nghe thấy xử bắn tải súng trường của họ) cho chức năng tìm kiếm, nhưng nó sẽ phá vỡ bất cứ khi nào một người dùng đã tìm kiếm ai đó có họ như "O'Reilly".

Tôi cố gắng tìm ra một công việc xung quanh (đọc "hack"):

Tạo một hàm vô hướng có giá trị trong sql đó thay thế một giá duy nhất với hai dấu nháy đơn, thoát một cách hiệu quả các vi phạm báo duy nhất, vì vậy
"... Họ LIKE '% O'Reilly%' VÀ ..." trở thành "... Họ LIKE '% O''Reilly%' VÀ ..."

chức năng này được gọi từ bên trong sql bất cứ khi nào tôi nghi ngờ các lĩnh vực có thể chứa một ký tự trích dẫn duy nhất tức là: firstname, lastname.

CREATE FUNCTION [dbo].[fnEscapeSingleQuote] 
    (@StringToCheck NVARCHAR(MAX)) 
RETURNS NVARCHAR(MAX) 
AS 
BEGIN 
    DECLARE @Result NVARCHAR(MAX) 
    SELECT @Result = REPLACE(@StringToCheck, CHAR(39), CHAR(39) + CHAR(39)) 
    RETURN @Result 
END 

Không phải là rất thanh lịch hoặc hiệu quả, nhưng nó hoạt động khi bạn đang ở trong một pinch.

0

Người ta có thể thay thế 'bằng' 'thay vì tham số hóa khi cần giải quyết vấn đề trong một số lượng lớn quảng cáo sql trong một thời gian ngắn với ít nguy cơ vỡ và thử nghiệm tối thiểu.

0

Tốt nhất là sử dụng tham số sql, nhưng sau đó bạn có giới hạn cho 2300 tham số cho truy vấn. Trong hầu hết các trường hợp, điều này sẽ là quá đủ. Nhưng trong những trường hợp hiếm hoi khi bạn vượt quá giới hạn này, tôi thấy đây là một tùy chọn.

0

SqlCommand và khung thực thể sử dụng exec sp_executesql....

Vì vậy, có thực sự là một thay thế cho chuỗi thô với mẫu thoát của riêng bạn có lẽ. Với SqlCommand bạn đang sử dụng kỹ thuật các truy vấn parameterised nhưng bạn đang bỏ qua việc trừu tượng hóa ADO.Net của mã SQL nằm bên dưới.

Vì vậy, trong khi mã của bạn không ngăn SQL Injection, câu trả lời cuối cùng là sp_executesql không phải là SqlCommand.

Có nói rằng, tôi chắc chắn có các yêu cầu xử lý đặc biệt để tạo chuỗi SQL Injection-proof sử dụng sp_executesql.

xem: How to return values from a dynamic SQL Stored Procedure to the Entity Framework?

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