25

Lấy cảm hứng từ nhiều câu hỏi liên quan schema Tôi đã nhìn thấy ...Máy chủ SQL: Cách cho phép lược đồ?

Ownership chaining cho phép tôi GRANT EXECUTE trên một thủ tục lưu trữ mà không cần quyền rõ ràng trên bảng tôi sử dụng, nếu cả hai thủ tục lưu trữ và bàn là trong lược đồ tương tự.

Nếu chúng tôi sử dụng các lược đồ riêng biệt thì tôi phải rõ ràng CẤP XXX trên các bảng lược đồ khác nhau. Ví dụ về chuỗi quyền sở hữu thể hiện điều đó. Điều này có nghĩa là người dùng thực thi proc được lưu trữ có thể đọc/ghi trực tiếp các bảng của bạn.

Điều này sẽ giống như có quyền truy cập trực tiếp vào các biến cá thể của bạn trong một lớp, bỏ qua getter/setters, phá vỡ đóng gói.

Chúng tôi cũng sử dụng bảo mật cấp hàng để hạn chế những gì ai đó nhìn thấy và chúng tôi áp dụng điều này trong các thủ tục được lưu trữ.

Vì vậy, làm cách nào chúng tôi có thể duy trì việc tách giản đồ và ngăn truy cập bảng trực tiếp?

Tất nhiên, câu hỏi sẽ không áp dụng nếu bạn sử dụng ORM hoặc không sử dụng procs được lưu trữ. Nhưng tôi không hỏi nếu tôi nên sử dụng một ORM hay proc được lưu trữ trong trường hợp bất cứ ai cảm thấy cần phải soi sáng cho tôi ...

Chỉnh sửa, ví dụ

CREATE USER OwnsMultiSchema WITHOUT LOGIN 
GO 
CREATE SCHEMA MultiSchema1 AUTHORIZATION OwnsMultiSchema 
GO 
CREATE SCHEMA MultiSchema2 AUTHORIZATION OwnsMultiSchema 
GO 

CREATE USER OwnsOtherSchema WITHOUT LOGIN 
GO 
CREATE SCHEMA OtherSchema AUTHORIZATION OwnsOtherSchema 
GO 

CREATE TABLE MultiSchema1.T1 (foo int) 
GO 
CREATE TABLE MultiSchema2.T2 (foo int) 
GO 
CREATE TABLE OtherSchema.TA (foo int) 
GO 

CREATE PROC MultiSchema1.P1 
AS 
SELECT * FROM MultiSchema1.T1 
SELECT * FROM MultiSchema2.T2 
SELECT * FROM OtherSchema.TA 
Go 
EXEC AS USER = 'OwnsMultiSchema' 
GO 
--gives error on OtherSchema 
EXEC MultiSchema1.P1 
GO 
REVERT 
GO 

CREATE PROC OtherSchema.PA 
AS 
SELECT * FROM MultiSchema1.T1 
SELECT * FROM MultiSchema2.T2 
SELECT * FROM OtherSchema.TA 
Go 
GRANT EXEC ON OtherSchema.PA TO OwnsMultiSchema 
GO 
EXEC AS USER = 'OwnsMultiSchema' 
GO 
--works 
EXEC OtherSchema.PA 
GO 
REVERT 
GO 

Chỉnh sửa 2:

  • Chúng tôi không sử dụng "chuỗi quyền sở hữu cơ sở dữ liệu chéo"
  • Bảo mật cấp hàng là cá trích đỏ và không có liên quan: chúng tôi không sử dụng nó ở mọi nơi
+2

Có thể cung cấp ví dụ được mã hóa của kịch bản lược đồ riêng biệt mà bạn mô tả để làm rõ không? Trong kịch bản của bạn, làm hai lược đồ riêng biệt có cùng một chủ sở hữu? –

+0

Tại sao bỏ phiếu đóng cho serverfault? Nó dành cho khỉ mã, không phải là hệ thống quản trị ... – gbn

+0

@ John Sansom: vâng tôi sẽ làm. – gbn

Trả lời

21

Tôi lo sợ rằng một trong hai mô tả của bạn hoặc thụ thai của bạn sở hữu Chaining là không rõ ràng, vì vậy hãy để tôi bắt đầu với điều đó:

"Quyền sở hữu Chaining" chỉ đơn giản đề cập đến thực tế rằng khi thực hiện một Stored Procedure (hoặc View) trên SQL Server, lô thực hiện hiện tại tạm thời thu nhận quyền/quyền của Chủ sở hữu sProc (hoặc chủ sở hữu lược đồ của sProc) trong khi thực thi mã SQL đó. Vì vậy, trong trường hợp của một sProc, người dùng không thể sử dụng những privs để làm bất cứ điều gì mà mã sProc không thực hiện cho họ. Lưu ý đặc biệt là nó không bao giờ mua lại Identity của Chủ sở hữu, chỉ có quyền của nó, tạm thời (tuy nhiên, EXECUTE AS ... thực hiện việc này).

Vì vậy, cách tiếp cận điển hình để tận dụng này để bảo mật là:

  1. Đặt tất cả các bảng dữ liệu (và tất cả các lần xem phi an ninh cũng) vào Schema riêng của họ, chúng ta hãy gọi nó [dữ liệu ] (mặc dù thông thường [dbo] được sử dụng vì nó đã có và quá đặc quyền cho lược đồ của người dùng). Đảm bảo rằng không có Người dùng, Lược đồ hoặc Chủ sở hữu hiện tại nào có quyền truy cập vào lược đồ [dữ liệu] này.

  2. Tạo giản đồ có tên [exec] cho tất cả các sProcs (và/hoặc có thể là bất kỳ Chế độ xem bảo mật nào). Đảm bảo rằng chủ sở hữu của giản đồ này có quyền truy cập vào lược đồ [dữ liệu] (điều này rất dễ dàng nếu bạn đặt dbo là chủ sở hữu của giản đồ này).

  3. Tạo một vai trò db mới được gọi là "Người dùng" và cấp cho nó quyền truy cập EXECUTE vào lược đồ [exec]. Bây giờ, hãy thêm tất cả người dùng vào vai trò này. Đảm bảo rằng người dùng của bạn chỉ có quyền Kết nối và không có quyền truy cập được cấp cho bất kỳ giản đồ nào khác, bao gồm [dbo].

Bây giờ, người dùng của bạn chỉ có thể truy cập dữ liệu bằng cách thực thi sProcs trong [exec]. Họ không thể truy cập bất kỳ dữ liệu nào khác hoặc thực thi bất kỳ đối tượng nào khác.

Tôi không chắc chắn nếu điều này trả lời câu hỏi của bạn (bởi vì tôi đã không chắc chắn câu hỏi là chính xác), do đó, cảm thấy tự do để chuyển hướng tôi.


Đối với an ninh row-level, đây là cách tôi luôn luôn làm điều đó với các chương trình an ninh trên:

  1. tôi luôn luôn thực hiện an ninh row-level như một loạt các lượt xem gương-wrap mỗi bảng và so sánh danh tính của người dùng (thường với Suser_Sname() hoặc một trong những người khác) vào danh sách bảo mật được khóa từ mã bảo mật trong chính hàng đó. Đây là các Chế độ xem bảo mật.

  2. Tạo giản đồ mới được gọi là [hàng], cấp cho chủ sở hữu quyền truy cập vào giản đồ [dữ liệu] và không có gì khác. Đặt tất cả các Security-Views trong lược đồ này.

  3. Thu hồi quyền truy cập của chủ sở hữu [exec] vào lược đồ [dữ liệu] và thay vào đó cấp quyền truy cập dữ liệu cho lược đồ [hàng].

Xong. Bây giờ bảo mật mức hàng đã được thực hiện bằng cách trượt một cách rõ ràng giữa các sProcs và các bảng.


Cuối cùng, đây là một Mua sắm lưu trữ mà tôi sử dụng để giúp tôi nhớ bao nhiêu này che khuất công trình công cụ bảo mật và tương tác với chính nó (oops, phiên bản chỉnh sửa mã):

CREATE proc [TestCnxOnly].[spShowProc_Security_NoEX] as 
--no "With Execute as Owner" for this version 
--create User [UserNoLogin] without login 
--Grant connect on database :: TestSecurity to Guest 
--alter database TestSecurity set trustworthy on 

--Show current user context: 
select current_user as current_ 
, session_user as session 
, user_name() as _name 
, suser_name() as [suser (sproc)] 
, suser_sname() as sname 
, system_user as system_ 


--Execute As Login = 'UserNoLogin' 
select current_user as current_ 
, session_user as session 
, user_name() as _name 
, suser_name() as [suser (after exec as)] 
, suser_sname() as sname 
, system_user as system_ 

EXEC('select current_user as current_ 
, session_user as session 
, user_name() as _name 
, suser_name() as [suser (in Exec(sql))] 
, suser_sname() as sname 
, system_user as system_') 

EXEC sp_ExecuteSQL N'select current_user as current_ 
, session_user as session 
, user_name() as _name 
, suser_name() as [suser (in sp_Executesql)] 
, suser_sname() as sname 
, system_user as system_' 

--Revert 
select current_user as current_ 
, session_user as session 
, user_name() as _name 
, suser_name() as [suser (aftr revert)] 
, suser_sname() as sname 
, system_user as system_ 

[CHỈNH SỬA: phiên bản mã đã sửa)

+0

Tôi thường hiểu quyền sở hữu chuỗi theo ví dụ này: Một proc được lưu trữ trong các bảng truy cập schema1 trong schema1 = quyền bảng (bao gồm DENY) không được chọn. Bảng trong, ví dụ, schema2 được kiểm tra. Ví dụ của tôi cho thấy rằng với EXEC MultiSchema1.P1 – gbn

+0

Ví dụ của riêng tôi đã vượt qua câu trả lời của bạn. Các bit tôi đã mất là nếu chủ sở hữu * của các lược đồ có liên quan là như nhau, sau đó quyền không được kiểm tra. Điều này sau đó là ý nghĩa của việc phân tách người dùng/lược đồ mà tôi thực sự cần phải đọc. Tuy nhiên, chúng tôi có tiền tố SQL 2005 trước và không nghĩ rằng nó thông qua – gbn

+0

Ví dụ đó hoạt động vì nó nằm trong cùng một lược đồ, do đó proc được lưu trữ và bảng có cùng một chủ sở hữu, do đó quyền truy cập được cho phép vì chủ sở hữu luôn có * mặc định * quyền truy cập vào nội dung của riêng họ. Tuy nhiên, lưu ý rằng điều này không phải là độc quyền của DENY, vv bất cứ điều gì có thể ngăn chặn chủ sở hữu của lược đồ chắc chắn sẽ ngăn chặn procs lưu trữ mà họ sở hữu cũng. – RBarryYoung

4

Bạn có thể:

Grant Execute On Schema::[schema_name] To [user_name] 

để cho phép người dùng thực hiện bất kỳ thủ tục trong lược đồ. Nếu bạn không muốn anh ta có thể thực hiện tất cả chúng, bạn có thể từ chối thực thi một thủ tục cụ thể cho người dùng. Từ chối sẽ được ưu tiên trong trường hợp này.

+0

Đúng, nhưng còn các bảng trong các lược đồ khác nhau được các thủ tục lưu sẵn sử dụng thì sao? Tôi không muốn từ chối bất kỳ quyền nào – gbn

8

2c của tôi: Chuỗi quyền sở hữu là kế thừa. Nó bắt đầu từ những ngày không có lựa chọn thay thế, và so với các lựa chọn thay thế ngày nay là không an toàn và thô.

Tôi nói thay thế không phải là quyền của lược đồ, cách thay thế là ký mã. Với việc ký mã, bạn có thể cấp các quyền cần thiết về chữ ký của thủ tục và cấp quyền truy cập thực thi rộng rãi cho quy trình trong khi truy cập dữ liệu được kiểm soát chặt chẽ. Việc ký mã cung cấp kiểm soát chi tiết hơn và chính xác hơn, và nó không thể bị lạm dụng theo cách mà chuỗi quyền sở hữu có thể. Nó hoạt động bên trong lược đồ, nó hoạt động trên lược đồ, nó hoạt động trên cơ sở dữ liệu và không yêu cầu lỗ hổng bảo mật lớn của quyền sở hữu cơ sở dữ liệu chéo được mở. Và nó không yêu cầu việc chiếm quyền sở hữu đối tượng cho các mục đích truy cập: chủ sở hữu của thủ tục có thể là bất kỳ người dùng nào.

Đối với câu hỏi thứ hai về bảo mật cấp hàng: bảo mật cấp hàng không thực sự tồn tại trong các phiên bản SQL Server 2014 trở về trước, như một tính năng được cung cấp bởi động cơ. Bạn có cách giải quyết khác nhau, và những cách giải quyết đó thực sự hiệu quả hơn với việc ký mã hơn là với chuỗi quyền sở hữu. Kể từ khi sys.login_token chứa chữ ký và chữ ký ngữ cảnh, bạn thực sự có thể thực hiện các kiểm tra phức tạp hơn mức bạn có thể trong ngữ cảnh chuỗi quyền sở hữu.

Vì phiên bản 2016 SQL Server hỗ trợ đầy đủ row level security.

+0

Mức độ bảo mật cấp hàng thực sự là một cá trích đỏ .. chúng tôi cũng sử dụng SUSER_SNAME thông qua THAM GIA từ các bảng bảo mật để kiểm soát quyền truy cập. – gbn

+0

Đó là "di sản" bit và sau đó thời gian/nỗ lực/laziness lý do tại sao tôi đã không theo dõi. + 1 anyway. Cảm ơn – gbn

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