Làm thế nào để bạn xử lý bảo mật cơ sở dữ liệu từ một ứng dụng máy tính để bàn?


12

Trong khoảng 10 năm, tôi đã làm việc trên các ứng dụng máy khách để bàn trong nhà khác nhau với các kho dữ liệu SQL Server. Hiếm khi tôi bắt đầu những dự án này - hầu hết là công việc tiếp quản.

Một điều dường như không đổi ở mọi nơi là có một tài khoản người dùng SQL Server toàn cầu duy nhất mà ứng dụng này đã sử dụng đã cấp quyền cho cơ sở dữ liệu chung và có trong một số tình huống ngây thơ, nó thường sử sadụng tài khoản người dùng mà tôi thường cố gắng khắc phục khi có thể .

Bạn thực sự không thể ẩn tên người dùng và mật khẩu này mà ứng dụng sử dụng để truy cập cơ sở dữ liệu. Chúng thường được lưu trữ trong một inihoặc configtập tin, hoặc có thể được nướng vào chính tệp thực thi. Trong mọi trường hợp, chúng sẽ hiển thị cho người dùng nếu họ đào một ít. Trong một trường hợp, chúng tôi thực sự đã sử dụng một configtệp nhưng đã mã hóa nó, nhưng tất nhiên khóa mã hóa phải được lưu trữ trong tệp thực thi (chúng tôi không ngây thơ trước những hạn chế của việc này, nhưng nó thực sự ngăn mọi người chọc vào những người đủ hiểu biết để tìm trong configcác tập tin).

Tất cả các hệ thống này đều có hệ thống xác thực người dùng được tích hợp trong ứng dụng, nhưng tất nhiên chúng đều được quản lý thông qua chính ứng dụng, nghĩa là thông tin người dùng được lưu trữ trong cơ sở dữ liệu. Ứng dụng đã hạn chế những điều bạn có thể làm dựa trên cấp độ truy cập của mình, nhưng tất cả đều là loại nếu bạn chỉ có thể kết nối với cơ sở dữ liệu và chạy các truy vấn đặc biệt.

Tôi muốn biết những hệ thống khác làm gì để khắc phục vấn đề này. Dưới đây là các tùy chọn tôi biết:

  1. Sử dụng cơ chế bảo mật của SQL Server để duy trì danh sách người dùng và vai trò và làm cho ứng dụng máy tính để bàn thêm và xóa người dùng thông qua các truy vấn T-SQL.
  2. Thay vì kết nối trực tiếp với cơ sở dữ liệu, hãy tạo một số loại dịch vụ web chạy trên máy chủ và đặt logic xác thực vào đó. Thực hiện mọi yêu cầu xác thực bảo mật.

Các tùy chọn đầu tiên hơi xấu vì bạn tách người dùng khỏi cơ sở dữ liệu để người dùng không còn là thực thể hạng nhất và bạn không thể tham chiếu chúng với các mối quan hệ khóa ngoài, v.v.

Thứ hai có vẻ như là một vấn đề hiệu suất lớn và rất nhiều công việc phụ, cộng với việc bạn không thể dễ dàng sử dụng các trình ánh xạ ORM như NHibernate (tôi nghĩ).

Có ai có kinh nghiệm với điều này? Thực hành tốt nhất?

Biên tập

Suy nghĩ thêm một chút, SQL Server xác thực có thể giải quyết vấn đề này không? Ví dụ: nếu người dùng của bạn phải có thể chèn và cập nhật các bản ghi bảng thời gian để bạn có thể chỉnh sửa bảng thời gian của mình, thì không có cách nào máy chủ SQL có thể không cho phép truy cập vào các hàng khác trong bảng chi tiết bảng thời gian, nghĩa là bạn cũng có thể đọc và viết bảng thời gian của người khác .


Về chủ đề ràng buộc; không sử dụng ORM như NHibernate là (tôi nghĩ) không phải là vấn đề. Nếu bạn sử dụng các dịch vụ web làm ví dụ, bạn sẽ tìm thấy nhiều cách để liên kết hiệu quả dữ liệu của bạn với XML.
jasonk

Dù sao, bạn không nên sử dụng ORM của mình làm ánh xạ trực tiếp giữa các đối tượng kinh doanh và các thực thể DB, đó là một cách tiếp cận kém tạo ra các giao diện mỏng manh. Thực hiện các yêu cầu đến một lớp nghiệp vụ nhận các thực thể DB thô và chỉ trả về dữ liệu cần thiết cho máy khách.
gbjbaanb

@gbjbaanb - chắc chắn, tôi sẽ thay đổi toàn bộ kiến ​​trúc vào chiều nay. :)
Scott Whitlock

Tôi cho rằng bạn có thể đợi cho đến khi ai đó hack bạn trước khi thay đổi nó, nhưng về mặt sáng sủa, ít nhất thì bạn sẽ không gặp vấn đề gì khi ông chủ của bạn tài trợ cho việc tái kiến ​​trúc :-)
gbjbaanb

Bạn có thể ngăn người dùng cập nhật hồ sơ của người khác - bằng cách sử dụng quy trình được lưu trữ làm cách duy nhất để cập nhật hồ sơ và sử dụng người dùng đang chạy Proc như một phần của truy vấn. Xem CURRENT_USER
gbjbaanb

Câu trả lời:


9

Tôi sợ thêm một lớp Dịch vụ Web có lẽ là giải pháp chính xác cho vấn đề của bạn.

Tách ứng dụng khách khỏi việc triển khai cơ sở dữ liệu cơ bản có thể cũng sẽ giúp bạn về lâu dài.

Thêm một lớp dịch vụ web không nhất thiết phải làm giảm hiệu suất ...

Thật vậy, với một API thích hợp, một dịch vụ web thực sự có thể cải thiện hiệu suất, bằng cách gộp nhiều truy vấn cơ sở dữ liệu trong mạng LAN của trung tâm dữ liệu, thay vì yêu cầu nhiều chuyến đi khứ hồi qua mạng LAN.

Và tất nhiên, một lớp dịch vụ web thường có thể được thu nhỏ theo chiều ngang và thêm bộ đệm phù hợp vào các truy vấn cơ sở dữ liệu của bạn, thậm chí có thể là một cơ chế thông báo thay đổi.

Một lớp máy chủ bổ sung bảo mật mà bạn không thể đảm bảo với các ứng dụng chạy trên máy khách từ xa. Bất cứ điều gì chạy trên máy khách đều có thể bị "hack" và không thực sự được xem xét theo bất kỳ cách nào đáng tin cậy. Bạn chỉ nên thực sự đưa logic trình bày vào máy khách và lưu trữ mọi thứ quan trọng trên phần cứng mà bạn có toàn quyền kiểm soát.

Tôi không biết về ứng dụng của bạn, nhưng các ứng dụng web của tôi được chia thành nhiều lớp một cách tự nhiên, với mã trình bày được tách biệt khỏi lớp kiên trì bằng ít nhất một mức logic nghiệp vụ giúp tách biệt hai cấp độ. Tôi thấy điều này làm cho lý do về ứng dụng của tôi dễ dàng hơn nhiều và nhanh hơn rất nhiều để thêm hoặc sửa đổi chức năng. Nếu các lớp được phân tách bằng mọi cách, thì việc giữ lớp trình bày trong máy khách là tương đối dễ dàng và phần còn lại trên máy chủ dưới sự kiểm soát của tôi.

Vì vậy, trong khi bạn có thể giải quyết vấn đề của mình mà không cần giới thiệu lớp "dịch vụ web", vào thời điểm bạn đã viết tất cả các thủ tục được lưu trữ (hoặc tương đương) cần thiết để điền vào các lỗ hổng trong triển khai bảo mật cơ sở dữ liệu tiêu chuẩn, có lẽ bạn nên viết ra một ứng dụng phía máy chủ mà bạn có thể viết các bài kiểm tra đơn vị thích hợp cho.


Tôi thừa nhận rằng nó không cần phải là một nút cổ chai hiệu năng, nhưng nó chắc chắn sẽ thêm một lớp bổ sung cho kiến ​​trúc, có nghĩa là bảo trì nhiều hơn nữa.
Scott Whitlock

3
Nó thêm một lớp, nhưng không nhất thiết phải bảo trì. Hãy xem xét rằng với tất cả logic được đặt trong dịch vụ, không phải máy khách, các thay đổi có thể được 'triển khai' mà không yêu cầu người dùng cập nhật ứng dụng khách của họ.
GrandmasterB

5

Tương tự như câu trả lời của jmoreno, bạn có thể từ chối người dùng truy cập mọi thứ ngoài các quyền EXECUTE trên các thủ tục được lưu trữ, sau đó tận dụng chuỗi quyền sở hữu để quy trình được lưu trữ thực hiện các thao tác cần thiết trên các bảng.

Xem tại đây để biết chi tiết https://msdn.microsoft.com/en-us/l Library / bb669058 (v = vs.110) .aspx

Khi người dùng nhập tên người dùng / mật khẩu của họ, tôi lưu trữ chúng và gửi dưới dạng tham số cho mỗi cuộc gọi thủ tục được lưu trữ. Sau đó, bạn có thể xác minh chúng dựa trên các giá trị được lưu trữ trong một bảng trước khi thực hiện thao tác mong muốn.

Chắc chắn không phải là từ cuối cùng trong bảo mật, nhưng có thể cần thiết nếu PC của bạn có thông tin đăng nhập chung, hạn chế khả năng sử dụng các nhóm AD của bạn để cấp quyền hoặc bạn có quyền truy cập hạn chế vào chính AD.


2

Một cách tiếp cận là sử dụng các nhóm AD và các thủ tục được lưu trữ để hạn chế những gì người dùng có thể làm - ví dụ DB bảng thời gian của bạn, có thể cho phép chèn, cập nhật và xóa giờ của người dùng, nhưng không cho phép cập nhật giờ của bất kỳ ai khác. ID người dùng sẽ được cung cấp bởi công cụ DB, người dùng sẽ không có quyền truy cập trực tiếp vào các bảng DB, chỉ để sp chạy các truy vấn dựa trên id đăng nhập của họ.

Tất nhiên điều này không phải lúc nào cũng khả thi, nhưng nó có thể. Cách tiếp cận tốt nhất sẽ phụ thuộc vào yêu cầu và nguồn lực của bạn.


Đây là điều tôi chưa từng xem xét. Tôi không chắc nó phù hợp tuyệt vời, nhưng nó sẽ hoạt động.
Scott Whitlock

1

Những gì bạn gợi ý là 'dịch vụ web' được gọi là kiến trúc n-tier . Nói chung, đó là cách để đi trong trường hợp có khả năng xảy ra sự cố về bảo mật hoặc cấu hình (ví dụ: phân phối ứng dụng trên nhiều văn phòng). Tuy nhiên, nó không phải là 'dựa trên web'. Nhiều người làm việc với các giao thức khác.

Bạn tạo một máy chủ ứng dụng để hoạt động như một trung gian giữa máy khách và cơ sở dữ liệu (và các tài nguyên khác). Máy chủ ứng dụng xử lý xác thực dựa trên ứng dụng của bạn và thực hiện các hành động thay mặt khách hàng. Trong thực tế, lý tưởng nhất là bạn sẽ không thực hiện bất kỳ SQL nào trong máy khách của mình - thay vào đó bạn gọi các phương thức trên máy chủ ứng dụng. Máy chủ ứng dụng sẽ xử lý tất cả các thao tác dữ liệu.

Có một số lợi ích cho cách tiếp cận. Bạn không cần phải cấu hình các kết nối cơ sở dữ liệu và trình điều khiển trên máy khách. Bạn không lưu trữ người dùng cơ sở dữ liệu, mật khẩu và máy chủ. Cấu hình của các máy khách thậm chí không cần thiết - chỉ cần trỏ chúng vào mã đến đúng url hoặc địa chỉ. Ngoài ra, với 'logic' trong máy chủ ứng dụng, bạn không phải lặp lại khi phát triển các ứng dụng khác - cùng một máy chủ ứng dụng có thể được sử dụng lại bởi các loại khách hàng khác nhau.


Thậm chí tốt hơn, nếu (hoặc khi) ai đó hack máy tính để bàn của bạn (hoặc máy chủ web tương đương dựa trên web), kẻ tấn công có thể có quyền truy cập đầy đủ vào HĐH, nhưng họ vẫn không có quyền truy cập vào DB. Và do đó, họ không thể chạy "select * từ người dùng" được chuyển đến một tệp mà họ lấy đi, giải phóng chúng và để CEO của bạn giải thích với truyền thông tại sao hệ thống bảo mật của bạn bị xâm phạm. Nếu bạn cũng sử dụng các sprocs trên DB chỉ cho phép thực thi quyền truy cập, thì kẻ tấn công cũng có thể hack ứng dụng của bạn và họ vẫn không thể lấy toàn bộ cơ sở dữ liệu người dùng của bạn.
gbjbaanb

1

Công nghệ đã thay đổi một chút. Nếu bạn xác thực từng người dùng với chính cơ sở dữ liệu và sử dụng các vai trò cơ sở dữ liệu, giờ đây bạn có thể sử dụng cái được gọi là Chế độ xem cập nhật để giải quyết vấn đề này, ít nhất là trong SQL Server.

Đây là một khung nhìn có thể cập nhật có thể trông giống như một bảng được gọi là SomeTablenơi mỗi hàng trong bảng đó được liên kết với một nhân viên. Nhân viên sẽ có thể thấy các hàng được liên kết với họ và các thành viên của vai trò nhân sự sẽ có thể thấy tất cả các hàng, ví dụ:

CREATE VIEW [dbo].[vwSomeTable]
AS
    SELECT SomeTable.*
    FROM SomeTable
        INNER JOIN Employee ON SomeTable.Employee_ID = Employee.Employee_ID
    WHERE Employee.Username = USER_NAME() OR IS_MEMBER('HR_Role')=1

GO

Sau đó, những gì bạn làm là cung cấp quyền đọc (và có thể ghi) trên chế độ xem ( vwSomeTable) cho tất cả người dùng và không cung cấp quyền trên bảng ( SomeTable).

Bạn có thể kiểm tra như thế này:

EXECUTE AS USER = 'Some_Regular_Username'
SELECT * FROM vwSomeTable

... chỉ nên trả lại hàng của họ. Hoặc là:

EXECUTE AS USER = 'Some_HR_Username'
SELECT * FROM vwSomeTable

... Sẽ trả về tất cả các hàng. Lưu ý rằng bạn sẽ cần quyền thực thi dưới dạng (mạo danh) để thực hiện kiểm tra này.

Các khung nhìn có thể cập nhật, do đó, ngay cả người dùng thông thường cũng có thể làm điều này, miễn là hàng được liên kết với Employeehàng của họ :

UPDATE vwSomeTable
SET SomeColumn = 5
WHERE SomeTable_ID = 'TheID'

0

Sử dụng xác thực dựa trên chứng chỉ là cách "chính xác" để triển khai tài khoản sql được chia sẻ. Mục tiêu là nó loại bỏ việc sử dụng mật khẩu cho loại điều này.

Cập nhật:

Tôi cho rằng hiểu lầm câu hỏi. Tôi nghĩ rằng nó phải làm với việc cố gắng tìm một giải pháp thay thế cho việc đặt tên người dùng và mật khẩu db trong cấu hình ứng dụng hoặc sao lưu vào chính ứng dụng.

Bạn có thể loại bỏ vấn đề quản lý mật khẩu trong các ứng dụng bằng cách sử dụng chứng chỉ phía máy khách. Bản thân chứng chỉ là không đủ, bạn phải có một hệ thống phân phối và quản lý có khả năng hoạt động như thu hồi chứng chỉ.

Tham khảo: http://en.wikipedia.org/wiki/Public-key_infr Hạ tầng


Bạn có thể cung cấp thêm một số thông tin về điều này? Nghe có vẻ như nó trực giao với mục đích của câu hỏi ban đầu của tôi, nhưng thật thú vị.
Scott Whitlock

0

Xây dựng một giải pháp bảo mật máy tính để bàn mới, chúng tôi đã chọn giải pháp dịch vụ web mà tôi sẽ cố gắng mô tả dưới đây.

Chúng tôi biên dịch các tệp thực thi ứng dụng máy tính để bàn trong một môi trường riêng biệt từ các nhà phát triển. Và tính toán một HASH từ thực thi đó được ghi vào cơ sở dữ liệu.

Một dịch vụ web cung cấp tất cả thông tin cần thiết để ứng dụng chạy, mật khẩu DB, thông tin chuỗi kết nối, quyền người dùng, v.v ...

chúng tôi sử dụng một bản ghi DB duy nhất cho mỗi ứng dụng và ghi lại chi tiết người dùng trong cơ sở dữ liệu theo các biến phiên để có thể kiểm tra các bản ghi.

Một DLL xử lý tất cả các giao tiếp từ ứng dụng máy tính để bàn đến dịch vụ web, chỉ có thể truy cập được với mã thông báo được tích hợp vào DLL.

Để có thể lấy mật khẩu DB của ứng dụng từ dịch vụ web, DLL tính toán người gọi DLL HASH trong thời gian chạy và chuyển dưới dạng tham số cho dịch vụ web xác thực mã thông báo DLL và thời gian chạy thực thi đã tính HASH cho người được ghi khi triển khai (ứng dụng chỉ khả dụng trong một cài đặt chia sẻ mạng duy nhất).

Bằng cách đó, chúng tôi đã giảm nó là một giải pháp tốt cho vấn đề bảo mật mà chúng tôi quan tâm nhất và nhận thức rõ về một vài lỗi thiết kế. Gần như đã hoàn thành việc thực hiện này và cho đến nay chúng tôi hài lòng với kết quả.

Chỉnh sửa: Bạn có thể thay thế ý tưởng băm bằng cách sử dụng chữ ký số và chứng chỉ X.509.


1
Có vẻ như khá rõ ràng nơi lỗ hổng bảo mật rõ ràng. DLL mà bạn nói đến nằm trên hệ thống của máy khách và không có cách nào để mã máy chủ của bạn xác minh rằng nó đang nói chuyện với một bản sao hợp pháp của DLL hoặc bị hack / độc hại / giả mạo. Bạn chỉ cần tạo ra rất nhiều công việc cho chính mình mà không cần thêm nhiều, nếu có, bảo mật thêm. Tất cả những gì một người độc hại cần là mã thông báo và thuật toán, cả hai đều nằm trong DLL cho bất kỳ ai muốn tìm.
Scott Whitlock

@ScottWhitlock, Vâng, tôi đồng ý. chúng tôi đang xem xét việc làm xáo trộn DLL và lưu lượng truy cập qua HTTPS. Chúng tôi đang cố gắng cải thiện điều đó, tôi thực sự thích bất kỳ đầu vào nào trong cách cải thiện nó. Nhưng giải pháp đó đã giải quyết được rất nhiều vấn đề mà hệ thống hiện tại gặp phải, bao gồm cả mật khẩu văn bản đơn giản được lưu trữ trong các tệp mạng. Ngoài ra, dịch vụ web cho phép tái sử dụng rất nhiều mã có thể được chấp nhận bởi bất kỳ ngôn ngữ máy khách nào chúng tôi sử dụng ở đây, bao gồm các máy khách Delphi và Clipper (Harbor)!
Vitor Arbex

Trong hệ thống của bạn, người dùng đăng nhập và có lẽ được xác thực bởi dịch vụ web. Giả sử sử dụng HTTPS, điều đó có đủ tốt không? Bạn không cần phải tin tưởng vào phần mềm máy khách, vì bạn biết rằng người dùng là người họ nói và bạn kiểm soát dịch vụ web, vì vậy hãy đảm bảo rằng dịch vụ web chỉ cung cấp thông tin mà người dùng cụ thể được phép xem. Ngay cả khi họ thiết kế ngược lại máy khách và tự viết, họ có thể gây ra thiệt hại gì? Chỉ dịch vụ web của bạn biết mật khẩu DB và điều đó sẽ an toàn.
Scott Whitlock
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.