Các thông số có thực sự đủ để ngăn ngừa tiêm Sql không?


83

Tôi đã giảng cho cả đồng nghiệp của mình và ở đây trên SO về sự tốt đẹp của việc sử dụng các tham số trong các truy vấn SQL, đặc biệt là trong các ứng dụng .NET. Tôi thậm chí đã đi xa đến mức hứa với họ là cung cấp khả năng miễn dịch chống lại các cuộc tấn công SQL injection.

Nhưng tôi bắt đầu tự hỏi liệu điều này có thực sự đúng không. Có bất kỳ cuộc tấn công chèn SQL nào đã biết sẽ thành công đối với một truy vấn được tham số hóa không? Ví dụ, bạn có thể gửi một chuỗi gây tràn bộ đệm trên máy chủ không?

Tất nhiên, có những cân nhắc khác cần thực hiện để đảm bảo rằng một ứng dụng web an toàn (như khử trùng đầu vào của người dùng và tất cả những thứ đó) nhưng bây giờ tôi đang nghĩ đến việc tiêm SQL. Tôi đặc biệt quan tâm đến các cuộc tấn công chống lại MsSQL 2005 và 2008 vì chúng là cơ sở dữ liệu chính của tôi, nhưng tất cả các cơ sở dữ liệu đều thú vị.

Chỉnh sửa: Để làm rõ ý tôi về các tham số và truy vấn được tham số hóa. Bằng cách sử dụng các tham số, ý tôi là sử dụng "biến" thay vì xây dựng truy vấn sql trong một chuỗi.
Vì vậy, thay vì làm điều này:

SELECT * FROM Table WHERE Name = 'a name'

Chúng tôi làm điều này:

SELECT * FROM Table WHERE Name = @Name

và sau đó đặt giá trị của tham số @Name trên đối tượng truy vấn / lệnh.


chúng ta nên làm rõ ý nghĩa của các tham số (như Jonathan Leffler đã chỉ ra) - Tôi đã nghĩ đến các tham số thủ tục lưu trữ, nhưng cũng có? parms và {0} parms ...
Steven A. Lowe

Nói dễ hơn nhiều, chúng tôi không sử dụng phép nối để tạo truy vấn.

Vì thẻ là asp.net, tôi cho rằng bạn đang xây dựng các ứng dụng web. Trong trường hợp này, bạn cũng nên chăm sóc của các cuộc tấn công XSS, và có lẽ những người khác
Spikolynn

Câu trả lời:


50

Giữ chỗ là đủ để ngăn ngừa tiêm. Bạn vẫn có thể bị tràn bộ đệm, nhưng đó là một kiểu tấn công hoàn toàn khác với kiểu tấn công SQL injection (vector tấn công sẽ không phải là cú pháp SQL mà là dạng nhị phân). Vì tất cả các tham số được truyền sẽ được thoát đúng cách, không có cách nào để kẻ tấn công truyền dữ liệu sẽ được coi như SQL "sống".

Bạn không thể sử dụng các hàm bên trong trình giữ chỗ và bạn không thể sử dụng trình giữ chỗ làm tên cột hoặc bảng, vì chúng được thoát và được trích dẫn dưới dạng ký tự chuỗi.

Tuy nhiên, nếu bạn sử dụng các tham số như một phần của việc nối chuỗi bên trong truy vấn động của mình, bạn vẫn dễ bị chèn, bởi vì các chuỗi của bạn sẽ không được thoát ra ngoài mà sẽ có nghĩa đen. Sử dụng các kiểu khác cho các tham số (chẳng hạn như số nguyên) là an toàn.

Điều đó nói rằng, nếu bạn đang sử dụng đầu vào sử dụng để đặt giá trị của một cái gì đó như thế nào security_levelđó, thì ai đó có thể tự làm quản trị viên trong hệ thống của bạn và có quyền truy cập miễn phí. Nhưng đó chỉ là xác thực đầu vào cơ bản và không liên quan gì đến SQL injection.


Điểm mấu chốt là hiểu được vấn đề được đưa ra bởi câu trả lời của Steve Lowe, cũng được chỉ ra trong bài báo @mikekidder trích dẫn - bạn phải cảnh giác ở bất kỳ nơi nào của Dynamic SQL, cho dù trong ứng dụng hay trong máy chủ. SQL động rất nguy hiểm - nhưng có thể an toàn.
Jonathan Leffler

"không có cách nào để kẻ tấn công truyền dữ liệu sẽ được coi như SQL 'sống'". - Điều này không hoàn toàn đúng, hãy xem ví dụ bên dưới.
Booji Boy

Tất cả các ví dụ dưới đây đang xác định "truy vấn được tham số hóa" có nghĩa là các tham số chấp nhận mã SQL. Định nghĩa thông thường là một truy vấn sử dụng bộ sưu tập các tham số DBMS của bạn. Ngăn chặn lỗi DBMS, kỹ thuật thứ hai này ngăn chặn việc đưa vào SQL.
HTTP 410

2
Tôi đã đọc từng liên kết. Vui lòng trích dẫn bất kỳ liên kết nào đề cập đến một cuộc tấn công chèn ép đang hoạt động chống lại bộ sưu tập Tham số DBMS. Thật vậy, liên kết mà bạn đã đăng cụ thể đề cập đến cách tiếp cận này là đánh bại việc tiêm SQL (xem phần "Sử dụng Tham số SQL Kiểu An toàn").
HTTP 410

Chào! Bạn có thể cung cấp liên kết đến ngữ pháp SQL của Oracle hoặc bất kỳ thứ gì tương tự để chứng minh câu trả lời đó không. Tôi hiểu điều đó và hoàn toàn đồng ý với bạn nhưng sẽ thật tuyệt nếu có liên kết chính thức đến tài liệu, ngữ pháp, v.v. BestRegards, Raimbek
Raimbek Rakhimbek

13

Không, vẫn có nguy cơ bị chèn SQL bất kỳ lúc nào bạn nội suy dữ liệu chưa được kiểm chứng vào một truy vấn SQL.

Các tham số truy vấn giúp tránh rủi ro này bằng cách tách các giá trị chữ khỏi cú pháp SQL.

'SELECT * FROM mytable WHERE colname = ?'

Điều đó tốt thôi, nhưng có những mục đích khác của việc nội suy dữ liệu vào một truy vấn SQL động không thể sử dụng các tham số truy vấn, vì nó không phải là giá trị SQL mà thay vào đó là tên bảng, tên cột, biểu thức hoặc một số cú pháp khác.

'SELECT * FROM ' + @tablename + ' WHERE colname IN (' + @comma_list + ')'
' ORDER BY ' + @colname'

Không quan trọng bạn đang sử dụng các thủ tục được lưu trữ hay đang thực thi các truy vấn SQL động trực tiếp từ mã ứng dụng. Rủi ro vẫn còn đó.

Cách khắc phục trong những trường hợp này là sử dụng FIEO khi cần thiết:

  • Đầu vào Bộ lọc: xác thực rằng dữ liệu trông giống như số nguyên hợp pháp, tên bảng, tên cột, v.v. trước khi bạn nội suy chúng.

  • Escape Output: trong trường hợp này "output" có nghĩa là đưa dữ liệu vào một truy vấn SQL. Chúng tôi sử dụng các hàm để biến đổi các biến được sử dụng dưới dạng các ký tự chuỗi trong biểu thức SQL, để các dấu ngoặc kép và các ký tự đặc biệt khác bên trong chuỗi được thoát ra. Chúng ta cũng nên sử dụng các hàm để chuyển đổi các biến sẽ được sử dụng làm tên bảng, tên cột, v.v. Đối với các cú pháp khác, như viết động toàn bộ biểu thức SQL, đó là một vấn đề phức tạp hơn.


12

Dường như có một số nhầm lẫn trong chủ đề này về định nghĩa của "truy vấn được tham số hóa".

  • SQL chẳng hạn như một proc được lưu trữ chấp nhận các tham số.
  • SQL được gọi bằng cách sử dụng bộ sưu tập các tham số DBMS.

Với định nghĩa cũ, nhiều liên kết cho thấy các cuộc tấn công đang hoạt động.

Nhưng định nghĩa "bình thường" là định nghĩa sau. Với định nghĩa đó, tôi không biết bất kỳ cuộc tấn công SQL injection nào sẽ hoạt động. Điều đó không có nghĩa là không có, nhưng tôi vẫn chưa thấy nó.

Từ các nhận xét, tôi không thể hiện bản thân đủ rõ ràng, vì vậy đây là một ví dụ hy vọng sẽ rõ ràng hơn:

Cách tiếp cận này dành cho SQL injection

exec dbo.MyStoredProc 'DodgyText'

Cách tiếp cận này không áp dụng cho SQL injection

using (SqlCommand cmd = new SqlCommand("dbo.MyStoredProc", testConnection))
{
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter newParam = new SqlParameter(paramName, SqlDbType.Varchar);
    newParam.Value = "DodgyText";
    .....
    cmd.Parameters.Add(newParam);
    .....
    cmd.ExecuteNonQuery();
}

Bạn có thể làm rõ ý của bạn về việc thu thập các tham số DBMS trái ngược với một thủ tục chấp nhận các tham số không?
Rune Grimstad

Rune, đọc phần "Sử dụng Tham số SQL Loại-An toàn" của liên kết này: msdn.microsoft.com/en-us/library/ms161953.aspx
HTTP 410

Câu trả lời của tôi là câu hỏi ban đầu của Rune, trước khi nó được chỉnh sửa với bản cập nhật.
mikekidder

Tôi đã đọc đi đọc lại bài viết trên msdn về việc tiêm sql và tôi vẫn không thấy có sự khác biệt như thế nào giữa các tham số mà một thủ tục được lưu trữ và các tham số mà một truy vấn động lấy. Ngoài thực tế là các truy vấn động là động. Bạn vẫn phải ràng buộc các tham số, phải không?
Rune Grimstad

Đó là sự ràng buộc tạo nên sự khác biệt. Nếu bạn gọi trực tiếp một proc được lưu trữ với các tham số, không có quá trình lọc đầu vào nào được thực hiện. Nhưng nếu bạn ràng buộc bởi (ví dụ) bằng cách sử dụng bộ sưu tập tham số SqlCommand trong .NET, tất cả các tham số sẽ được lọc và coi như văn bản thuần túy.
HTTP 410

10

bất kỳ tham số sql nào của loại chuỗi (varchar, nvarchar, v.v.) được sử dụng để tạo truy vấn động vẫn dễ bị tấn công

nếu không, việc chuyển đổi kiểu tham số (ví dụ: thành int, thập phân, ngày tháng, v.v.) sẽ loại bỏ mọi nỗ lực đưa sql qua tham số

CHỈNH SỬA: một ví dụ, trong đó tham số @ p1 được dùng để làm tên bảng

create procedure dbo.uspBeAfraidBeVeryAfraid ( @p1 varchar(64) ) 
AS
    SET NOCOUNT ON
    declare @sql varchar(512)
    set @sql = 'select * from ' + @p1
    exec(@sql)
GO

Nếu @ p1 được chọn từ danh sách thả xuống, nó là một vectơ tấn công sql-injection tiềm năng;

Nếu @ p1 được lập trình có lập trình với khả năng người dùng can thiệp thì nó không phải là vectơ tấn công sql-injection tiềm năng


Không; toàn bộ điểm là chuỗi được truyền tới DBMS không phải là một phần của câu lệnh SQL. Do đó, giá trị trong chuỗi không có sự khác biệt đối với cách diễn giải của SQL - chỉ với các giá trị được tham chiếu bởi SQL.
Jonathan Leffler

Đó cũng là cách tôi xem các thông số. Họ có nhiệm vụ ngăn chặn vấn đề này.
Rune Grimstad

2
Steven đúng nếu ví dụ bạn đang truyền một chuỗi vào một sp sử dụng nó để chạy một cái gì đó như sp_executeSql (máy chủ sql) thì bạn vẫn có nguy cơ tiêm sql.
alexmac

@Steven: đó không phải là một tham số cho SQL; bạn sẽ phải có một trình giữ chỗ (dấu chấm hỏi) thay cho việc nối chuỗi. Và SQL không cho phép bạn chỉ định tên bảng bằng trình giữ chỗ. Đó là một lỗ hổng SQL injection thuần túy - vấn đề ban đầu.
Jonathan Leffler

@Steven: có thể thuật ngữ 'tham số' đã bị quá tải một lần quá thường xuyên. : D
Jonathan Leffler

6

Tràn bộ đệm không phải là SQL injection.

Truy vấn tham số đảm bảo bạn an toàn trước SQL injection. Họ không đảm bảo rằng không có khả năng bị khai thác dưới dạng lỗi trong máy chủ SQL của bạn, nhưng không có gì đảm bảo điều đó.


2

Dữ liệu của bạn không an toàn nếu bạn sử dụng sql động theo bất kỳ hình dạng hoặc hình thức nào vì quyền phải ở cấp bảng. Có, bạn đã giới hạn loại và số lượng cuộc tấn công tiêm từ truy vấn cụ thể đó, nhưng không giới hạn quyền truy cập mà người dùng có thể nhận được nếu họ tìm thấy đường vào hệ thống và bạn hoàn toàn có thể truy cập vào những người dùng nội bộ truy cập vào những gì họ không nên để thực hiện hành vi lừa đảo hoặc đánh cắp thông tin cá nhân để bán. SQL động thuộc bất kỳ loại nào đều là một thực hành nguy hiểm. Nếu bạn sử dụng procs được lưu trữ không động, bạn có thể đặt quyền ở cấp procesdure và không người dùng nào có thể làm bất cứ điều gì ngoại trừ những gì được định nghĩa bởi procs (tất nhiên là ngoại trừ quản trị viên hệ thống).


vì vậy bài học ở đây là nếu bạn phải sử dụng sql động, chỉ làm như vậy bên trong một thủ tục được lưu trữ. +1 lời khuyên tốt!
Steven A. Lowe

1
Không - SQL động trong các procs được lưu trữ vẫn có thể tạo ra các lỗi chèn SQL bằng cách nội suy dữ liệu chưa được kiểm chứng vào truy vấn động.
Bill Karwin

Không bài học ở đây là không bao giờ sử dụng SQL động
HLGEM

@HLGEM - đúng, ô tô gây ra tai nạn giao thông, vì vậy chúng ta đừng bao giờ sử dụng ô tô.
Bill Karwin

Nhưng SQL động trong một proc được lưu trữ chạy (theo mặc định) với sự cho phép của người gọi, không giống như SQL tĩnh chạy với sự cho phép của chủ sở hữu proc được lưu trữ. Đây là một dấu hiệu đặc biệt quan trọng.
HTTP 410

1

Có thể một proc được lưu trữ dễ bị tấn công bởi các kiểu chèn SQL đặc biệt thông qua tràn / cắt ngắn, hãy xem: Injection Enabled by Data Truncation tại đây:

http://msdn.microsoft.com/en-us/library/ms161953.aspx


Nếu bạn đọc chi tiết bài viết, bạn sẽ thấy rằng việc sử dụng bộ sưu tập Tham số của SQL Server ngăn chặn cuộc tấn công này. Và đó là định nghĩa bình thường của "Truy vấn được tham số hóa" - nó sử dụng bộ sưu tập Tham số của DBMS.
HTTP 410

1

Chỉ cần nhớ rằng với các tham số, bạn có thể dễ dàng lưu trữ chuỗi hoặc nói tên người dùng nếu bạn không có bất kỳ chính sách nào, "); thả người dùng bảng; -"

Bản thân điều này sẽ không gây ra bất kỳ tác hại nào, nhưng bạn nên biết rõ hơn vị trí và cách ngày đó được sử dụng thêm trong ứng dụng của bạn (ví dụ: được lưu trữ trong một cookie, được truy xuất sau này để làm những việc khác.


1

Bạn có thể chạy sql động làm ví dụ

DECLARE @SQL NVARCHAR(4000);
DECLARE @ParameterDefinition NVARCHAR(4000);

SELECT  @ParameterDefinition = '@date varchar(10)'

SET @SQL='Select CAST(@date AS DATETIME) Date'

EXEC sp_executeSQL @SQL,@ParameterDefinition,@date='04/15/2011'
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.