Как вы справляетесь с безопасностью базы данных из настольного приложения?

12

Около 10 лет я работал над различными внутренними клиентскими приложениями для настольных компьютеров с хранилищами данных SQL Server. Редко я начинал эти проекты - большинство из них занимаются поглощением.

Одна вещь, которая везде казалась постоянной, заключалась в том, что существовала единственная глобальная учетная запись пользователя SQL Server, которая использовалась этим приложением, которая предоставляла ему разрешение для общей базы данных, и да, в некоторых наивных ситуациях она использовала saучетную запись пользователя, которую я обычно пытался исправить, когда это было возможно ,

Вы не можете эффективно скрыть это имя пользователя и пароль, которые приложение использует для доступа к базе данных. Они , как правило , хранятся в одном iniили configфайл, или , возможно , запеченные в сам исполняемый файл. Во всех случаях они видны пользователю, если они немного копают. В одном случае мы фактически использовали configфайл, но зашифровали его, но, конечно, ключ шифрования должен был быть сохранен в исполняемом файле (мы не были наивны в отношении ограничений этого, но он действительно не позволял людям ковыряться, которые были достаточно опытны смотреть в configфайлах).

Все эти системы имели встроенную в приложение систему аутентификации пользователей, но, конечно, все они управлялись через само приложение, то есть информация о пользователях сохранялась в базе данных. Приложение ограничивало то, что вы можете делать, в зависимости от уровня доступа, но это все равно, что просто подключиться к базе данных и выполнить специальные запросы.

Мне интересно знать, что делают другие системы, чтобы обойти эту проблему. Вот варианты, которые я знаю:

  1. Используйте механизм безопасности SQL Server для ведения списка пользователей и ролей, а также заставляйте настольное приложение добавлять и удалять пользователей с помощью запросов T-SQL.
  2. Вместо непосредственного подключения к базе данных создайте какой-либо веб-сервис, работающий на сервере, и добавьте туда логику аутентификации. Сделайте каждый запрос на проверку безопасности.

Первый вариант немного уродлив, потому что вы отделяете пользователей от базы данных, поэтому пользователи больше не являются объектами первого класса, и вы не можете ссылаться на них отношениями внешнего ключа и т. Д.

Второе просто кажется серьезной проблемой производительности и большой дополнительной работы, плюс вы не можете так же легко использовать ORM-сопоставители, как NHibernate (я думаю).

У кого-нибудь есть опыт с этим? Лучшие практики?

редактировать

Подумав еще немного, может ли аутентификация SQL Server решить эту проблему? Например, если ваш пользователь должен иметь возможность вставлять и обновлять записи расписания, чтобы вы могли редактировать расписание, SQL-сервер не сможет запретить доступ к другим строкам таблицы сведений о расписании, то есть вы можете читать и записывать расписания других людей.

Скотт Уитлок
источник
По теме привязок; не использовать ORM как NHibernate не является (я думаю) проблемой. Если вы используете веб-службы в качестве примера, вы найдете много способов эффективного связывания ваших данных с XML.
Джейсон
В любом случае вы не должны использовать ORM как прямое отображение между бизнес-объектами и объектами БД, это плохой подход, делающий хрупкие интерфейсы. Отправляйте запросы на бизнес-уровень, который получает необработанные сущности БД и возвращает клиенту только необходимые данные.
gbjbaanb
@gbjbaanb - конечно, я изменю всю архитектуру сегодня днем. :)
Скотт Уитлок
Я полагаю, вы могли бы подождать, пока кто-то не взломает вас, прежде чем менять его, но, с другой стороны, у вас, по крайней мере, не
возникнет
Вы можете запретить пользователю обновлять чужие записи - используя хранимую процедуру в качестве единственного способа обновления записей и используя пользователя, который запускает процедуру, как часть запроса. Смотрите CURRENT_USER
gbjbaanb

Ответы:

9

Боюсь, что добавление слоя веб-службы, вероятно, является правильным решением вашей проблемы.

Отделение клиента от базовой реализации базы данных, вероятно, также поможет вам в долгосрочной перспективе.

Добавление слоя веб-сервиса не обязательно должно ухудшать производительность ...

Действительно, с помощью соответствующего API веб-служба может фактически повысить производительность, объединяя несколько запросов к базе данных в локальной сети центра обработки данных, вместо того, чтобы требовать многократных обратных вызовов по глобальной сети.

И, конечно, уровень веб-службы часто можно масштабировать по горизонтали и добавлять соответствующее кеширование в запросы к базе данных, возможно, даже механизм уведомления об изменениях.

Уровень сервера добавляет безопасность, которую невозможно обеспечить приложениями, запущенными на удаленном клиенте. Все, что работает на клиенте, может быть взломано и не должно рассматриваться как доверенное. Вы должны действительно поместить логику представления в клиент и разместить что-то важное на оборудовании, которым вы полностью управляете.

Я не знаю о ваших приложениях, но мои веб-приложения естественным образом разделены на несколько уровней, при этом код представления отделен от уровня постоянства как минимум одним уровнем бизнес-логики, который разделяет их. Я считаю, что это значительно упрощает анализ моего приложения и позволяет намного быстрее добавлять или изменять функциональность. Если слои в любом случае разделены, относительно легко сохранить уровень представления в клиенте, а остальные на сервере под моим контролем.

Таким образом, хотя вы можете решить свои проблемы, не вводя слой «веб-службы», к тому времени, когда вы напишите все хранимые процедуры (или их эквиваленты), необходимые для заполнения пробелов в стандартной реализации безопасности базы данных, вам, вероятно, будет лучше писать серверное приложение, для которого вы можете написать надлежащие модульные тесты.

Билл Мичелл
источник
Я признаю, что это не должно быть узким местом в производительности, но это, безусловно, добавляет дополнительный уровень в архитектуру, что означает гораздо больше обслуживания.
Скотт Уитлок
3
Это добавляет слой, но не обязательно обслуживание. Учтите, что со всей логикой, размещенной в службе, а не на клиенте, изменения можно «развернуть», не требуя от пользователей обновления своих клиентских приложений.
GrandmasterB
5

Подобно ответу jmoreno, вы можете запретить пользователю доступ ко всему, кроме разрешений EXECUTE для хранимых процедур, а затем воспользоваться цепочкой владения, чтобы хранимая процедура выполняла необходимые операции над таблицами.

Подробности смотрите здесь https://msdn.microsoft.com/en-us/library/bb669058(v=vs.110).aspx

Когда пользователь вводит свое имя пользователя / пароль на стороне клиента, я сохраняю их и отправляю как параметры для каждого вызова хранимой процедуры. Затем вы можете сверять их со значениями, хранящимися в таблице, перед выполнением требуемой операции.

Определенно, это не последнее слово в области безопасности, но оно может понадобиться, если на ваших компьютерах есть общие логины, ограничивающие вашу возможность использовать группы AD для разрешений или у вас ограниченный доступ к самой AD.

Джеймс К
источник
2

Один из подходов состоит в том, чтобы использовать группы AD и хранимые процедуры, чтобы ограничить то, что может делать пользователь - например, ваша БД табеля рабочего времени может разрешать вставку, обновление и удаление часов пользователя, но не позволяет обновлять чьи-либо часы. Идентификатор пользователя будет предоставлен механизмом БД, у пользователя не будет прямого доступа к таблицам БД, а только к тем, которые запускают запросы на основе своего идентификатора входа в систему.

Конечно, это не всегда возможно, но может быть. Лучший подход будет зависеть от ваших требований и ресурсов.

jmoreno
источник
Это то, что я не учел. Я не уверен, что это отлично подходит, но это сработает.
Скотт Уитлок
1

То, на что вы намекаете как «веб-сервис», называется n-уровневой архитектурой . Как правило, это хороший способ в тех случаях, когда возможны проблемы с безопасностью или конфигурацией (например, распространение приложения во многих офисах). Однако он не обязательно должен быть «веб-ориентированным». Многие работают с другими протоколами.

Вы создаете сервер приложений, который выступает в качестве посредника между клиентом и базой данных (и другими ресурсами). Сервер приложений обрабатывает вашу аутентификацию на основе приложений и выполняет действия от имени клиента. На самом деле, в идеале вы не должны выполнять SQL на своем клиенте, а скорее вызывать методы на сервере приложений. Сервер приложений будет обрабатывать все манипуляции с данными.

У этого подхода есть ряд преимуществ. Вам не нужно настраивать соединения с базой данных и драйверы на клиентах. Вы не храните пользователей базы данных, пароли и серверы. Конфигурирование клиентов даже не требуется - просто укажите их в коде по правильному URL или адресу. Кроме того, благодаря «логике» на сервере приложений вам не нужно повторяться при разработке других приложений - один и тот же сервер приложений может быть повторно использован различными типами клиентов.

GrandmasterB
источник
Еще лучше, если (или когда) кто-то взломает ваши рабочие столы (или веб-сервер в веб-эквиваленте), злоумышленник может иметь полный доступ к ОС, но у него все еще нет доступа к БД. И поэтому они не могут затем запустить «select * from users», переданный в файл, который они забирают, взломать на досуге и позволить вашему генеральному директору объяснить СМИ, почему ваша безопасная система была взломана. Если вы также используете sprocs в БД, которая разрешает только исполнительный доступ, то злоумышленник может также взломать ваш сервер приложений и все равно не сможет получить всю вашу пользовательскую базу данных.
gbjbaanb
1

Технология немного изменилась. Если вы аутентифицируете каждого пользователя в самой базе данных и используете роли базы данных, теперь вы можете использовать так называемое обновляемое представление для решения этой проблемы, по крайней мере, в SQL Server.

Вот как может выглядеть обновляемое представление для таблицы, в SomeTableкоторой каждая строка в этой таблице связана с сотрудником. Сотрудник должен иметь возможность видеть связанные с ним строки, а члены роли HR должны видеть все строки, например:

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

Затем вы даете всем пользователям права на чтение (и, возможно, на запись) на view ( vwSomeTable), а на table ( SomeTable) не даете никаких разрешений .

Вы можете проверить это так:

EXECUTE AS USER = 'Some_Regular_Username'
SELECT * FROM vwSomeTable

... которые должны возвращать только свои строки. Или:

EXECUTE AS USER = 'Some_HR_Username'
SELECT * FROM vwSomeTable

... который вернет все строки. Обратите внимание, что для выполнения этого теста вам потребуются разрешения на выполнение (олицетворение).

Представления являются обновляемыми, так что даже обычный пользователь может сделать это, если строка связана с их Employeeстрокой:

UPDATE vwSomeTable
SET SomeColumn = 5
WHERE SomeTable_ID = 'TheID'
Скотт Уитлок
источник
0

Использование аутентификации на основе сертификатов является «правильным» способом реализации общей учетной записи SQL. Цель состоит в том, чтобы исключить использование пароля для такого рода вещей.

Обновить:

Я полагаю, что неправильно понял вопрос. Я подумал, что это связано с попыткой найти альтернативу введению имени пользователя и пароля в базе данных либо в конфигурации приложения, либо обратно в само приложение.

Вы можете устранить проблему управления паролями в приложениях, используя вместо этого сертификаты на стороне клиента. Одного сертификата недостаточно, у вас должна быть система распределения и управления, способная выполнять такие операции, как отзыв сертификата.

Ссылка: http://en.wikipedia.org/wiki/Public-key_infrastructure

dietbuddha
источник
Можете ли вы предоставить больше информации об этом? Похоже, это может быть ортогонально намерению моего первоначального вопроса, но это интересно.
Скотт Уитлок
0

При создании нового решения для безопасности настольных компьютеров мы выбрали решение для веб-службы, которое я постараюсь описать ниже.

Мы компилируем исполняемые файлы настольных приложений в отдельной среде от разработчиков. И вычислите HASH из того исполняемого файла, который записан в базу данных.

Один веб-сервис, который предоставляет всю необходимую информацию для запуска приложения, пароль БД, информацию о строке подключения, разрешения пользователя и т. Д.

мы используем единый вход в БД для каждого приложения и записываем данные пользователя в базу данных в переменные сеанса, чтобы иметь возможность проверять записи.

DLL обрабатывает весь обмен данными от настольного приложения до веб-сервиса, который доступен только при сборке токена в DLL.

Чтобы иметь возможность получить пароль БД приложения из веб-службы, DLL вычисляет HASH вызывающих DLL во время выполнения и передает в качестве параметра веб-службе, которая проверяет токен DLL и вычисленный HASH исполняемой среды выполнения, записанному при ее развертывании. (приложение доступно только в общей сетевой установке).

То, как мы упали, - это хорошее решение проблемы безопасности, в которой мы больше всего заинтересованы и хорошо знакомы с некоторыми недостатками дизайна. Мы почти заканчиваем эту реализацию, и пока мы довольны результатами.

Изменить: Вы можете заменить идею хеширования с помощью цифровых подписей и сертификатов X.509.

Витор Арбекс
источник
1
Кажется довольно очевидным, где явная дыра в безопасности. DLL, о которой вы говорите, находится в клиентской системе, и код вашего сервера не может проверить, что он обращается к законной копии DLL или взломанной / вредоносной / поддельной. Вы просто создали много работы для себя, не добавляя много, если таковые имеются, дополнительной безопасности. Все, что нужно злоумышленнику, - это токен и алгоритм, оба из которых находятся в DLL для всех, кто хочет посмотреть.
Скотт Уитлок
@ ScottWhitlock, да, я согласен. мы пытаемся запутать DLL, и трафик будет проходить через HTTPS. Мы пытаемся улучшить это, мне бы очень хотелось узнать, как это улучшить. Но это решение уже решает множество проблем, с которыми сталкивается текущая система, включая простые текстовые пароли, хранящиеся в сетевых файлах. Также веб-сервис позволяет повторно использовать большую часть кода, доступного любому клиентскому языку, который мы здесь используем, включая клиентов Delphi и Clipper (Harbor)!
Витор Арбекс
В вашей системе пользователь входит в систему и предположительно проходит проверку подлинности через веб-сервис. Предполагая использование HTTPS, разве это не достаточно хорошо? Вам не нужно доверять клиентскому программному обеспечению, поскольку вы знаете, что пользователь является тем, кем они говорят, и вы управляете веб-службой, поэтому убедитесь, что веб-служба предоставляет только ту информацию, которую данный пользователь имеет право просматривать. Даже если они перепроектировали клиента и написали свой собственный, какой ущерб они могли бы нанести? Только ваш веб-сервис знает пароль БД, и это должно быть безопасно.
Скотт Уитлок