Câu lệnh được tham số hóa có thể dừng tất cả việc đưa vào SQL không?


79

Nếu có, tại sao vẫn có rất nhiều lần tiêm SQL thành công? Chỉ vì một số nhà phát triển quá ngu ngốc để sử dụng các câu lệnh tham số hóa?


6
Đây là một câu hỏi lớn, với câu trả lời hoàn toàn khủng khiếp (như thời gian tôi đang cho ý kiến)
Ibu

Tôi ước ai đó có danh tiếng tốt ít nhất là 15k hoặc có kinh nghiệm tốt có thể thêm đầu vào có giá trị cho câu hỏi này.
Ibu

4
Hãy xem bài nói chuyệnslide của Bill Karwin's Sql Injection Myths and Fallacy để biết thêm thông tin về chủ đề này. Anh ấy giải thích SQL injection là gì, cách thoát thường không đủ tốt và cách các thủ tục được lưu trữ và các câu lệnh được tham số hóa có thể bị xâm phạm.
Mike

2
Cũng xem một số câu trả lời của Bill Karwin cho các câu hỏi tương tự: SQL injection là gì?
Mike,

Câu trả lời:


64

Các liên kết mà tôi đã đăng trong bình luận của mình cho câu hỏi giải thích vấn đề rất tốt. Tôi đã tóm tắt cảm xúc của mình về lý do tại sao sự cố vẫn tiếp diễn, bên dưới:

  1. Những người mới bắt đầu có thể không biết về SQL injection.

  2. Một số người biết về SQL injection, nhưng nghĩ rằng thoát là giải pháp (duy nhất?). Nếu bạn thực hiện tìm kiếm nhanh trên Google php mysql query, trang đầu tiên xuất hiện là mysql_querytrang, trên đó có một ví dụ hiển thị nội suy đầu vào của người dùng đã thoát vào một truy vấn. Thay vào đó, không có đề cập nào (ít nhất là tôi không thể thấy) việc sử dụng các báo cáo đã chuẩn bị. Như những người khác đã nói, có rất nhiều hướng dẫn sử dụng phép nội suy tham số, nên không thực sự ngạc nhiên về tần suất nó vẫn được sử dụng.

  3. Thiếu hiểu biết về cách hoạt động của các câu lệnh tham số. Một số nghĩ rằng nó chỉ là một phương tiện ưa thích để thoát khỏi các giá trị.

  4. Những người khác biết về các câu lệnh tham số hóa, nhưng không sử dụng chúng vì họ đã nghe nói rằng chúng quá chậm. Tôi nghi ngờ rằng nhiều người đã nghe thấy các tuyên bố được paramterized cực kỳ chậm chạp như thế nào, nhưng chưa thực sự thực hiện bất kỳ thử nghiệm nào của riêng họ. Như Bill Karwin đã chỉ ra trong bài nói chuyện của mình, sự khác biệt về hiệu suất hiếm khi được sử dụng như một yếu tố khi xem xét việc sử dụng các báo cáo đã chuẩn bị. Những lợi ích của việc chuẩn bị một lần, thực hiện nhiều lần , thường dường như bị lãng quên, cũng như những cải tiến về bảo mật và khả năng bảo trì mã.

  5. Một số sử dụng các câu lệnh được tham số hóa ở mọi nơi, nhưng với phép nội suy các giá trị không được kiểm tra như tên bảng và cột, từ khóa và toán tử điều kiện. Tìm kiếm động, chẳng hạn như những tìm kiếm cho phép người dùng chỉ định một số trường tìm kiếm khác nhau, điều kiện so sánh và thứ tự sắp xếp, là những ví dụ chính về điều này.

  6. Cảm giác an toàn sai khi sử dụng ORM. ORM vẫn cho phép nội suy các phần câu lệnh SQL - xem 5.

  7. Lập trình là một môn học lớn và phức tạp, quản trị cơ sở dữ liệu là một môn học lớn và phức tạp, bảo mật là một môn học lớn và phức tạp. Việc phát triển một ứng dụng cơ sở dữ liệu an toàn không hề đơn giản - ngay cả những nhà phát triển có kinh nghiệm cũng có thể bị mắc kẹt.

  8. Nhiều câu trả lời trên stackoverflow không hữu ích. Khi mọi người viết các câu hỏi sử dụng SQL động và nội suy tham số, thường thiếu các câu trả lời đề xuất sử dụng các câu lệnh được tham số hóa thay thế. Trong một vài trường hợp, tôi đã có người phản bác đề xuất của tôi về việc sử dụng các tuyên bố đã chuẩn bị sẵn - thường là do chi phí hoạt động không thể chấp nhận được. Tôi thực sự nghi ngờ rằng những người hỏi hầu hết các câu hỏi này ở vị trí mà vài mili giây thừa được thực hiện để chuẩn bị một câu lệnh tham số hóa sẽ có tác động thảm khốc đối với ứng dụng của họ.


63

Khi các bài báo nói về các truy vấn tham số ngăn chặn các cuộc tấn công SQL, họ không thực sự giải thích tại sao, nó thường là trường hợp "Nó có, vì vậy đừng hỏi tại sao" - có thể vì họ không biết chính họ. Dấu hiệu chắc chắn của một nhà giáo dục tồi là không thể thừa nhận rằng họ không biết điều gì đó. Nhưng tôi lạc đề. Khi tôi nói, tôi thấy hoàn toàn có thể hiểu được nhầm lẫn là điều đơn giản. Hãy tưởng tượng một truy vấn SQL động

sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND Pass=' + password

vì vậy, một lần tiêm sql đơn giản sẽ chỉ là đặt Tên người dùng là 'HOẶC 1 = 1-- Điều này sẽ thực hiện truy vấn sql một cách hiệu quả:

sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS=' + password

Điều này cho biết hãy chọn tất cả khách hàng mà tên người dùng của họ là trống ('') hoặc 1 = 1, là boolean, tương đương với true. Sau đó, nó sử dụng - để nhận xét phần còn lại của truy vấn. Vì vậy, cái này sẽ chỉ in ra tất cả bảng khách hàng, hoặc làm bất cứ điều gì bạn muốn với nó, nếu đăng nhập, nó sẽ đăng nhập với đặc quyền của người dùng đầu tiên, thường có thể là quản trị viên.

Giờ đây, các truy vấn được tham số hóa làm điều đó theo cách khác, với mã như:

sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'

parameters.add("User", username)
parameters.add("Pass", password)

trong đó tên người dùng và mật khẩu là các biến trỏ đến tên người dùng và mật khẩu đã nhập được liên kết

Bây giờ tại thời điểm này, bạn có thể đang nghĩ, điều này không thay đổi bất cứ điều gì cả. Chắc chắn bạn vẫn có thể đặt vào trường tên người dùng một cái gì đó như Không ai HOẶC 1 = 1 '-, thực hiện truy vấn một cách hiệu quả:

sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND Pass=?'

Và điều này có vẻ như là một lập luận hợp lệ. Nhưng bạn có thể đã sai.

Cách hoạt động của các truy vấn được tham số hóa, đó là sqlQuery được gửi dưới dạng một truy vấn và cơ sở dữ liệu biết chính xác truy vấn này sẽ làm gì và chỉ khi đó, nó mới chèn tên người dùng và mật khẩu đơn thuần dưới dạng giá trị. Điều này có nghĩa là chúng không thể thực hiện truy vấn, vì cơ sở dữ liệu đã biết truy vấn sẽ làm gì. Vì vậy, trong trường hợp này, nó sẽ tìm kiếm tên người dùng "Không ai HOẶC 1 = 1 '-" và một mật khẩu trống, mật khẩu này sẽ dẫn đến sai.

Tuy nhiên, đây không phải là một giải pháp hoàn chỉnh và việc xác thực đầu vào vẫn cần được thực hiện, vì điều này sẽ không ảnh hưởng đến các vấn đề khác, chẳng hạn như các cuộc tấn công XSS, vì bạn vẫn có thể đưa javascript vào cơ sở dữ liệu. Sau đó, nếu điều này được đọc ra trên một trang, nó sẽ hiển thị dưới dạng javascript bình thường, tùy thuộc vào bất kỳ xác nhận đầu ra nào. Vì vậy, thực sự điều tốt nhất cần làm vẫn là sử dụng xác nhận đầu vào, nhưng sử dụng truy vấn được tham số hóa hoặc các thủ tục được lưu trữ để ngăn chặn bất kỳ cuộc tấn công SQL nào.


1
Điều này bổ sung rất nhiều cho những gì tôi đang tìm kiếm, nhưng bạn có thể giải thích thêm về những gì bạn sẽ làm để "xác thực đầu vào"? Bạn cũng đã đề cập rằng có những cuộc tấn công khác có thể xảy ra với truy vấn, tức là XSS, nhưng bạn có thể giải thích điều đó sẽ xảy ra như thế nào không? Vì vậy, về cơ bản, làm thế nào chúng ta sẽ bảo vệ hoàn toàn khỏi SQL Injection, hoặc chúng ta đang xem xét tất cả các loại tiêm? cảm ơn.
XaolingBao

3
@JosipIvic: Với số lượng người đã hỏi cách hoạt động của các câu lệnh tham số hóa, thật là sốc khi thấy rất ít - nếu có thì thực sự - hãy chia nhỏ câu trả lời như bạn đã làm. Cảm ơn bạn đã viết một lời giải thích rõ ràng như vậy với một ví dụ khá trực quan.
daOnlyBG

Xuất sắc. Một ví dụ vẽ lên hàng nghìn từ khi họ nói!
Drenai

10

Câu hỏi hay đấy. Câu trả lời là ngẫu nhiên hơn là xác định và tôi sẽ cố gắng giải thích quan điểm của mình, sử dụng một ví dụ nhỏ.

Có nhiều tài liệu tham khảo trên mạng gợi ý chúng ta sử dụng các tham số trong các truy vấn của mình hoặc sử dụng thủ tục được lưu trữ với các tham số để tránh SQL Injection (SQLi). Tôi sẽ cho bạn thấy rằng các thủ tục được lưu trữ (ví dụ) không phải là chiếc gậy thần kỳ chống lại SQLi. Trách nhiệm vẫn thuộc về lập trình viên.

Hãy xem xét Quy trình lưu trữ của SQL Server sau đây sẽ lấy hàng người dùng từ bảng 'Người dùng':

create procedure getUser
 @name varchar(20)
,@pass varchar(20)
as
declare @sql as nvarchar(512)
set @sql = 'select usrID, usrUName, usrFullName, usrRoleID '+
           'from Users '+
           'where usrUName = '''+@name+''' and usrPass = '''+@pass+''''
execute(@sql)

Bạn có thể nhận kết quả bằng cách chuyển các tham số tên người dùng và mật khẩu. Giả sử mật khẩu ở dạng văn bản tự do (chỉ để đơn giản hóa ví dụ này) thì một cuộc gọi thông thường sẽ là:

DECLARE @RC int
DECLARE @name varchar(20)
DECLARE @pass varchar(20)

EXECUTE @RC = [dbo].[getUser] 
   @name = 'admin'
  ,@pass = '!@Th1siSTheP@ssw0rd!!'
GO

Nhưng ở đây chúng ta có một kỹ thuật lập trình không tốt được lập trình viên sử dụng bên trong thủ tục được lưu trữ, vì vậy kẻ tấn công có thể thực thi những điều sau:

DECLARE @RC int
DECLARE @name varchar(20)
DECLARE @pass varchar(20)

EXECUTE @RC = [TestDB].[dbo].[getUser] 
   @name = 'admin'
  ,@pass = 'any'' OR 1=1 --'
GO

Các tham số trên sẽ được chuyển làm đối số cho thủ tục được lưu trữ và lệnh SQL cuối cùng sẽ được thực thi là:

select usrID, usrUName, usrFullName, usrRoleID 
from Users 
where usrUName = 'admin' and usrPass = 'any' OR 1=1 --'

..mà sẽ lấy lại tất cả các hàng từ người dùng

Vấn đề ở đây là ngay cả khi chúng ta tuân theo nguyên tắc "Tạo một thủ tục được lưu trữ và chuyển các trường để tìm kiếm dưới dạng tham số" thì SQLi vẫn được thực hiện. Điều này là do chúng tôi chỉ sao chép thực hành lập trình sai của chúng tôi bên trong thủ tục được lưu trữ. Giải pháp cho vấn đề là viết lại Quy trình đã lưu trữ của chúng tôi như sau:

alter procedure getUser
 @name varchar(20)
,@pass varchar(20)
as
select usrID, usrUName, usrFullName, usrRoleID 
from Users 
where usrUName = @name and usrPass = @pass

Những gì tôi đang cố gắng nói là các nhà phát triển trước tiên phải tìm hiểu một cuộc tấn công SQLi là gì và cách có thể được thực hiện và sau đó để bảo vệ mã của họ cho phù hợp. Làm theo 'phương pháp hay nhất' một cách mù quáng không phải lúc nào cũng là cách an toàn hơn ... và có lẽ đây là lý do tại sao chúng ta gặp rất nhiều 'phương pháp hay nhất'- thất bại!


Tôi có thể hiểu quan điểm của bạn và tôi có lỗi về điều này. Đôi khi cần tạo truy vấn sql động mà tôi đã sử dụng nối các tham số. Làm thế nào bạn đề nghị tôi đi về nó?
TheProvost

@TheProvost đó là một câu hỏi hay. Cân nhắc sp_executesql: msdn.microsoft.com/en-us/library/ms188001.aspx
Tim

@Tim Chào bạn. Tôi mới sử dụng sql động. Sự khác biệt giữa sp_executesql và EXECUTE (@SqlQuery) là gì
TheProvost

2
tôi nghĩ bài đăng này giải thích tốt một ví dụ đơn giản: codeproject.com/Tips/586207/… - nhưng về cơ bản, EXECUTE (@SqlQuery) không có gì để ngăn chặn việc tiêm sql, tuy nhiên sp_executesql (@SqlQuery, ..., ...) không ngăn cản nó. Các ví dụ trong bài viết microsoft sẽ hữu ích.
Tim

Tim có giải pháp TheProvost ...;) Bạn có thể sử dụng sp_executesql (@QUERY, @PARAMETERS, @VARS) ... cho trường hợp SQL động ...;)
Andreas Venieris, 16/10/15

5

Đúng vậy, việc sử dụng các câu lệnh đã chuẩn bị sẵn sẽ dừng tất cả các lần tiêm SQL, ít nhất là trên lý thuyết. Trong thực tế, các câu lệnh được tham số hóa có thể không phải là các câu lệnh được chuẩn bị thực sự, ví dụ như PDOtrong PHP giả lập chúng theo mặc định, vì vậy nó mở ra cho một cuộc tấn công biên .

Nếu bạn đang sử dụng các tuyên bố chuẩn bị thực sự, mọi thứ đều an toàn. Chà, ít nhất là miễn là bạn không nối SQL không an toàn vào truy vấn của mình như phản ứng của việc không thể chuẩn bị tên bảng chẳng hạn.

Nếu có, tại sao vẫn có rất nhiều lần tiêm SQL thành công? Chỉ vì một số nhà phát triển quá ngu ngốc để sử dụng các câu lệnh tham số hóa?

Vâng, giáo dục là điểm chính ở đây, và là cơ sở mã kế thừa. Rất nhiều hướng dẫn sử dụng tính năng thoát và chúng không thể dễ dàng xóa khỏi web.


1
Câu trả lời được liên kết thực ra không liên quan gì đến các câu đã chuẩn bị sẵn.
Ý thức chung của bạn

1
@YourCommonSense: Đó là về các truy vấn được tham số hóa, chúng có thể không được chuẩn bị thực tế nhưng được mô phỏng tùy thuộc vào trình điều khiển được sử dụng. Điều quan trọng là phải biết và rất nhiều kết nối ...
kelunik

1
Câu trả lời khác trong cùng một trang có một nhận xét rất hay: "Nếu TẤT CẢ các truy vấn của bạn đều được tham số hóa, bạn cũng được bảo vệ khỏi việc đưa vào lệnh thứ 2. Việc tiêm lệnh thứ nhất đang quên rằng dữ liệu người dùng là không đáng tin cậy. Việc tiêm lệnh thứ hai là quên rằng dữ liệu cơ sở dữ liệu. không đáng tin cậy (vì ban đầu nó đến từ người dùng). "
Rodrigo

@kelunik, câu trả lời được liên kết cũng không phải về các truy vấn được tham số hóa, mà là về một thư viện về cơ bản giả mạo chúng. Truy vấn được tham số hóa là truy vấn được gửi đến máy chủ với các giá trị tham số riêng biệt.
Panagiotis Kanavos

@PanagiotisKanavos: Tôi biết khá rõ nội dung của câu trả lời đó. Nó chỉ là một ví dụ (và một khá phổ biến) mà các truy vấn tham số bạn sử dụng có thể không thực sự được thực hiện như chuẩn bị phát biểu ...
kelunik

3

Tôi tránh sự tuyệt đối trong lập trình; luôn luôn có một ngoại lệ. Tôi rất khuyến khích các thủ tục được lưu trữ và các đối tượng lệnh. Phần lớn cơ sở của tôi là sử dụng SQL Server, nhưng thỉnh thoảng tôi vẫn chơi với MySql. Có nhiều lợi thế cho các thủ tục được lưu trữ bao gồm các kế hoạch truy vấn được lưu trong bộ nhớ cache; vâng, điều này có thể được thực hiện với các tham số và SQL nội tuyến, nhưng điều đó mở ra nhiều khả năng hơn cho các cuộc tấn công tiêm và không giúp loại bỏ các mối quan tâm. Đối với tôi, việc bảo mật cơ sở dữ liệu cũng dễ dàng hơn nhiều vì các ứng dụng của tôi thường chỉ có quyền thực thi cho các thủ tục được lưu trữ nói trên. Nếu không có quyền truy cập bảng / chế độ xem trực tiếp, việc tiêm bất cứ thứ gì khó hơn nhiều. Nếu người dùng ứng dụng bị xâm phạm, người dùng chỉ có quyền thực thi chính xác những gì đã được xác định trước.

Theo quan điểm của tôi.


Điều này liên quan đến câu hỏi như thế nào? Bạn sẽ gọi và chuyển các tham số cho thủ tục được lưu trữ như thế nào? Sử dụng nối chuỗi hoặc bằng cách sử dụng truy vấn được tham số hóa? Bên cạnh đó - điều gì sẽ xảy ra nếu ai đó sử dụng nối chuỗi bên trong thủ tục được lưu trữ để tạo truy vấn "động"? Chỉ vì nó là một thủ tục lưu trữ không có nghĩa là nó an toàn hơn
Panagiotis Kanavos

Nói chung, tôi sử dụng một đối tượng lệnh và tôi cũng tránh chạy "truy vấn động" theo thiết kế.
Derek

2

Tôi sẽ không nói "ngu ngốc".

Tôi nghĩ rằng các hướng dẫn là vấn đề. Hầu hết các hướng dẫn, sách về SQL, bất cứ thứ gì giải thích SQL với các giá trị nội tuyến, hoàn toàn không đề cập đến các tham số ràng buộc. Những người học từ các hướng dẫn này không có cơ hội học đúng.


2
Nó không phải là đủ. Tại sao mọi người không sử dụng framework hoặc một số orm? Tại sao họ không thử nghiệm "tiêm câm" với một số thử nghiệm ngu ngốc? Bởi vì đôi khi ông chủ không trả lương cao cho bạn hoặc ông ấy trả cho bạn X số tiền cho một dự án và bạn cần phải chạy từ dự án này sang dự án khác và từ dự án này sang dự án khác để có được một số tiền. Bạn phải nhanh hơn và nhanh hơn. Người viết mã bị căng thẳng và bị ép quá mức, vì vậy mã hoạt động nhưng nó viết rất tệ.
jedi

2

Bởi vì hầu hết các mã không được viết với tính bảo mật và quản lý, được đưa ra lựa chọn giữa việc thêm các tính năng (đặc biệt là thứ hiển thị có thể bán được) và bảo mật / ổn định / độ tin cậy (khó bán hơn nhiều), họ hầu như luôn chọn trước đây. An ninh chỉ là mối quan tâm khi nó trở thành một vấn đề.


2

Câu lệnh được tham số hóa có thể dừng tất cả việc đưa vào SQL không?

Có, miễn là trình điều khiển cơ sở dữ liệu của bạn cung cấp một trình giữ chỗ cho mọi ký tự SQL có thể. Hầu hết các trình điều khiển tuyên bố chuẩn bị không. Giả sử, bạn sẽ không bao giờ tìm thấy trình giữ chỗ cho tên trường hoặc cho một mảng giá trị. Điều này sẽ khiến một nhà phát triển rơi vào việc điều chỉnh truy vấn bằng tay, sử dụng cách ghép nối và định dạng thủ công. Với kết quả dự đoán.

Đó là lý do tại sao tôi tạo trình bao bọc Mysql của mình cho PHP hỗ trợ hầu hết các ký tự có thể được thêm động vào truy vấn, bao gồm cả mảng và số nhận dạng.

Nếu có, tại sao vẫn có rất nhiều lần tiêm SQL thành công? Chỉ vì một số nhà phát triển quá ngu ngốc để sử dụng các câu lệnh tham số hóa?

Như bạn có thể thấy, trong thực tế, không thể có tất cả các truy vấn của bạn được tham số hóa, ngay cả khi bạn không ngu ngốc.


Nếu TẤT CẢ các truy vấn của bạn được tham số hóa (đến từ dữ liệu người dùng hoặc từ dữ liệu cơ sở dữ liệu của bạn), thì có vẻ như bạn đã được bảo vệ, như đã nêu trong nhận xét được bình chọn nhiều nhất ở đây: stackoverflow.com/a/134138/1086511
Rodrigo

Tôi đã hỏi ý kiến ​​của bạn, chỉ vì bạn có vẻ đủ hợp lý. Tôi không nghĩ rằng phương pháp của bạn sẽ là tốt nhất nếu những gì tôi đã đọc được ở những nơi khác. Dù sao, tôi sẽ thích nếu bạn cải thiện "với các công cụ thông thường, bạn không thể tham số hóa TẤT CẢ các truy vấn của mình".
Rodrigo

Tôi bắt đầu đọc câu trả lời của bạn, cho đến khi tôi có ý tưởng xác định "các chữ SQL". Ý tưởng này dường như không hoàn toàn đúng với tôi (có vẻ như quá tải). Nếu đúng là các truy vấn tham số tránh được đưa vào trong PHP (tôi vẫn đang nghiên cứu), thì bước tiếp theo của tôi là tránh tiêm javascript. Sau đó, tôi sẽ quay lại để nghiên cứu giải pháp của bạn. Ngoài ra, tôi đang sử dụng postgres, và có thể giải pháp của bạn là mysql cụ thể?
Rodrigo

Ok, bây giờ tôi đã đọc nó (một lần nữa) và không nghĩ rằng "không thể có tất cả các truy vấn của bạn được tham số hóa" là một cải tiến. Nó không thể trong MySQL? Nó cũng không thể trong PostgreSQL? Tại sao? Có bất kỳ truy vấn nào bên ngoài tập lệnh php của tôi không? Ở đâu? Tôi nghĩ rằng theo số nhận dạng, bạn có nghĩa là một từ dành riêng mà bạn cố gắng loại bỏ khỏi mảng $ _POST của mình? Đây dường như không phải là cách để đi, đối với tôi (theo trực giác, tất nhiên, tôi có thể sai). Ngoài ra, tôi không hiểu câu "Bạn đã cố gắng ràng buộc nó bao giờ chưa?" Ràng buộc những gì?
Rodrigo

Điều đó không dễ tìm thấy trên web như tôi nghĩ. Vui lòng thêm một tài liệu tham khảo nếu bạn có thể.
Rodrigo

2

Trước tiên, câu trả lời của tôi cho câu hỏi đầu tiên của bạn: Vâng, theo như tôi biết, bằng cách sử dụng các truy vấn tham số hóa, việc tiêm SQL sẽ không thể thực hiện được nữa. Đối với những câu hỏi sau của bạn, tôi không chắc và chỉ có thể cho bạn biết ý kiến ​​của tôi về những lý do:

Tôi nghĩ sẽ dễ dàng hơn khi "chỉ" viết chuỗi truy vấn SQL bằng cách nối một số phần khác nhau (thậm chí có thể phụ thuộc vào một số kiểm tra logic) cùng với các giá trị được chèn. Nó chỉ là tạo truy vấn và thực thi nó. Một ưu điểm khác là bạn có thể in (echo, output hoặc bất cứ thứ gì) chuỗi truy vấn sql và sau đó sử dụng chuỗi này cho một truy vấn thủ công tới cơ sở dữ liệu.

Khi làm việc với các câu lệnh đã chuẩn bị, bạn luôn phải thực hiện thêm ít nhất một bước nữa: Bạn phải xây dựng truy vấn của mình (tất nhiên là bao gồm các tham số) Bạn phải chuẩn bị truy vấn trên máy chủ. Bạn phải ràng buộc các tham số với giá trị thực tế bạn muốn để sử dụng cho truy vấn của bạn Bạn phải thực hiện truy vấn.

Đó là một phần công việc nhiều hơn (và không đơn giản để lập trình) đặc biệt là đối với một số công việc "nhanh chóng và bẩn thỉu" thường được chứng minh là tồn tại rất lâu ...

Trân trọng,

Cái hộp


1

Để bảo vệ ứng dụng của bạn khỏi SQL injection, hãy thực hiện các bước sau:

Bước 1. Hạn chế đầu vào. Bước 2. Sử dụng các tham số với các thủ tục được lưu trữ. Bước 3. Sử dụng các tham số với SQL động.

Tham khảo http://msdn.microsoft.com/en-us/library/ff648339.aspx


8
Các thủ tục được lưu trữ một mình thực sự không phải là một trợ giúp. Có thể tạo chuỗi truy vấn động trong một thủ tục được lưu trữ, giống như trong mã máy khách.
Phil Miller,

@Fahad Tôi có thể đặt lại từ khóa # 2 là "Sử dụng các câu lệnh được tham số hóa trong các truy vấn và trong các thủ tục được lưu trữ." +1 cho nhận xét của Novelocrat rằng việc sử dụng các thủ tục được lưu trữ mà không có tham số không giúp bạn nhiều.
Matthew

1

SQL injection là một tập hợp con của vấn đề lớn hơn về chèn mã, trong đó dữ liệu và mã được cung cấp qua cùng một kênh và dữ liệu bị nhầm lẫn với mã. Các truy vấn được tham số hóa ngăn điều này xảy ra bằng cách hình thành truy vấn sử dụng ngữ cảnh về dữ liệu là gì và mã là gì.

Trong một số trường hợp cụ thể, điều này là không đủ. Trong nhiều DBMS, có thể thực thi động SQL với các thủ tục được lưu trữ, tạo ra một lỗ hổng chèn SQL ở cấp DBMS. Việc gọi một thủ tục được lưu trữ như vậy bằng cách sử dụng các truy vấn được tham số hóa sẽ không ngăn chặn việc khai thác SQL injection trong thủ tục. Một ví dụ khác có thể được nhìn thấy trong bài đăng trên blog này .

Thông thường hơn, các nhà phát triển sử dụng chức năng không chính xác. Thông thường, mã trông giống như thế này khi được thực hiện đúng cách:

db.parameterize_query("select foo from bar where baz = '?'", user_input)

Một số nhà phát triển sẽ nối các chuỗi với nhau và sau đó sử dụng truy vấn được tham số hóa, điều này không thực sự tạo nên sự khác biệt về dữ liệu / mã đã nói ở trên, cung cấp các đảm bảo bảo mật mà chúng tôi đang tìm kiếm:

db.parameterize_query("select foo from bar where baz = '" + user_input + "'")

Việc sử dụng đúng các truy vấn được tham số hóa cung cấp khả năng bảo vệ rất mạnh, nhưng không phải là không thể xuyên thủng, chống lại các cuộc tấn công SQL injection.


1

ngay cả khi các câu lệnh đã chuẩn bị được sử dụng đúng cách trong toàn bộ mã riêng của ứng dụng web, lỗi chèn SQL vẫn có thể tồn tại nếu các thành phần mã cơ sở dữ liệu xây dựng truy vấn từ đầu vào của người dùng theo cách không an toàn. Sau đây là ví dụ về thủ tục được lưu trữ dễ bị chèn SQL vào tham số @name:

CREATE PROCEDURE show_current_orders
(@name varchar(400) = NULL)
AS
DECLARE @sql nvarchar(4000)
SELECT @sql = ‘SELECT id_num, searchstring FROM searchorders WHERE ‘ +
‘searchstring = ‘’’ + @name + ‘’’’;
EXEC (@sql)
GO

Ngay cả khi ứng dụng chuyển giá trị tên do người dùng cung cấp tới thủ tục được lưu trữ một cách an toàn, thì bản thân thủ tục này sẽ nối trực tiếp giá trị này vào một truy vấn động và do đó dễ bị tấn công.

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.