Безопасность OpenEdge-приложений
База данных
Имеется несколько способов для обращения к базе данных OpenEdge:
- локальное подключение через разделяемую память,
- клиент-серверное ABL-подключение,
- клиент-серверное SQL-подключение,
- подключение через единого брокера (AppServer-агент, Webspeed-агент).
Первые два способа существовали, начиная с версий 6 или 5. В то время как SQL- и AppServer-доступы являются относительно новыми.
Чтобы защитить эти пути доступа, OpenEdge традиционно положился на одного «привратника»: username/password[3]. Эта уникальная пара, хранимая в таблице метасхемы _USER, однозначно отвечает за контроль доступа к данным через _CAN*-поля, которые обсуждались в предыдущем разделе. Текущая реализация таблицы _USER незначительно изменилась относительно прошлых нескольких версий Progress/OpenEdge. Непосредственно в пределах движка СУБД нет механизмов, гарантирующих использование сложных паролей или контролирующих срок их действия, – эти функции должны быть частью вашего ABL-приложения. Таблица _USER, помимо множества различных полей, содержит два поля: одно для имени пользователя, а другое – для хранения зашифрованной версии пароля пользователя.
Чтобы укрепить безопасность данных, в OpenEdge предусмотрены три дополнительных функции защиты:
- security Administrator,
- admin – Security – Disable Blank User-ID Access,
- admin – DB Options – Disable Blank User-ID.
Администратор Безопасности
Администратор безопасности контролирует доступ к данным в базе через _CAN*-поля. В версии OpenEdge 10.1B только таблицы метасхемы контролируются посредством _CAN*-полей, такие как _FILE, _FIELD, _VIEW и _VIEW-COL[4]. В частности, для полей _FILE и _FIELD:
Имя таблицы | Имя поля |
_File | _Can-Create |
_File | _Can-Delete |
_File | _Can-Dump |
_File | _Can-Load |
_File | _Can-Read |
_File | _Can-Write |
_Field | _Can-Read |
_Field | _Can-Write |
Когда через меню «Data Administration – Security – Security Administrators» регистрируют администратора безопасности, изменяются следующие поля таблиц в таблице _FILE[5]:
File-Name | Can-Read | Can-Write | Can-Create | Can-Delete |
_User | * | * | secadmin | secadmin |
_Db-Detail | * | secadmin | secadmin | secadmin |
_Db-Option | * | secadmin | secadmin | secadmin |
и в таблице _FIELD:
File-Name | Field-Name | Can-Write |
_File | _Can-Create | secadmin |
_File | _Can-Delete | secadmin |
_File | _Can-Read | secadmin |
_File | _Can-Read | secadmin |
_Field | _Can-Read | secadmin |
_Field | _Can-Write | secadmin |
Что это означает? Смотрим на первую строку таблицы _FILE, только secadmin может создать или удалить запись в таблице с именем «_USER». Но существует одно исключение: хотя у поля _PASSWORD таблицы _USER есть атрибуты _CAN*, они будут проигнорированы движком СУБД. Таким образом, только сам пользователь может изменить свой пароль. Чтобы обойти это, администратор безопасности должен фактически удалить и создать заново запись в таблице _USER, чтобы изменить пароль пользователя.
Администратор Безопасности не то же самое что SQL-администратор базы данных, т.к. он не управляет возможностью создавать и удалять таблицы, поля или индексы.
Это подводит нас ко второй таблице – _CAN*-значения в таблице _FIELD. Первая строка может быть прочитана так: «Только пользователь secadmin может выполнять запись в поле метасхемы _FILE._CAN-CREATE». Соответствующий ABL-оператор:
FOR EACH _FILE: ASSIGN _FILE._CAN-CREATE = “*”. END.
Заметьте, это не ограничивает доступ на создание записей в таблице непосредственно. Ограничены только изменения в поле _CAN-CREATE. Точно так же другие строки в таблице определяют, что только пользователь secadmin может изменять поля _CAN-DELETE, _CAN-READ и _CAN-WRITE в таблице _FILE.
Следующими двумя примерами я надеюсь разъяснить взаимосвязь между администратором безопасности, пользователями и _CAN*-полями.
Пример 1: Ограничение доступа к таблице «Customer».
Представьте пользователей, user-id которых начинается с «cs» (Customer Service), которым должна быть предоставлена возможность изменять данные в таблице «Customer». Возможностью изменения управляют поля _FILE._CAN-WRITE, _FILE._CAN-CREATE и _FILE._CAN-DELETE, где запись из таблицы _FILE имеет значение поля _FILE._FILE-NAME = «Customer». По умолчанию эти три поля содержат значение «*», говорящее, что все user-id, включая blank user-id, могут изменять данные:
FIND _FILE NO-LOCK WHERE _FILE-NAME = “CUSTOMER”. DISPLAY _CAN-READ _CAN-WRITE _CAN-CREATE _CAN-DELETE.
Can-Read | Can-Write | Can-Create | Can-Delete |
* | * | * | * |
Чтобы ограничить доступ, выполним:
FIND _FILE EXCLUSIVE-LOCK WHERE _FILE-NAME = “CUSTOMER”. ASSIGN _CAN-WRITE = “cs*” _CAN-CREATE = “cs*” _CAN-DELETE = “cs*”. DISPLAY _CAN-READ _CAN-WRITE _CAN-CREATE _CAN-DELETE.
Can-Read | Can-Write | Can-Create | Can-Delete |
cs* | cs* | cs* | cs* |
Помните: только пользователь secadmin может изменять _FILE._CAN*-поля, поэтому он называется Администратор Безопасности, т.е. он управляет тем, какие user-id к каким данным могут обратиться.
Пример 2: Контроль того, кто может создавать новые таблицы и поля.
Чтобы контролировать, какие user-id могут изменять таблицу «Customer», администратор безопасности изменил соответствующие _FILE._ CAN*-поля, где _FILE-NAME = «customer». Чтобы установить ограничение на возможность создания новых таблиц, нужно задействовать те же принципы, только поле _FILE-NAME должно быть равно «_FILE» и/или «_FIELD».
Используя этот пример, администратор безопасности может назначить набору пользовательских user-id привилегии администратора схемы базы данных.
Примечание:
- Эти модификации доступа могут быть сделаны через «Data Administration – Admin – Security – Edit Data Security».
- Хотя это может показаться очевидным, всегда назначайте роль администратора безопасности более чем одному пользователю.
Admin – Security – Disable Blank User-ID
Эта опция была введена одновременно с _CAN*-полями. Она вставляет символ «!» в начале значения каждого из этих полей метасхемы. Это означает, что во время компиляции, или в ходе выполнения, любой пользователь, подключенный к базе данных, но не определивший действующее имя пользователя, не может получить доступ к каким-либо данным, если безопасность во время выполнения включена.
Один из минусов этой опции заключается в том, что она нединамична. Если новая таблица или поле будут созданы после включения этой опции, то в _CAN*-полях им не будет автоматически установлен символ «!». Администратор базы данных должен сделать это отдельно. В качестве альтернативы каждый раз после добавления новой таблицы или поля должна выполняться опция «Disable Blank User-ID».
Admin – DB Options – Disable Blank User-ID
Эта опция, доступная с версии OpenEdge 10.1A, препятствует подключению пользователя к базе данных без использования надлежащих параметров username/password. Различие между этой опцией и описанной выше заключается в том, что первая допускает подключение к базе данных, но не предоставляет никакого доступа к данным, а вторая сразу отказывает пользователю в подключении. Эта опция создает очень безопасную среду для базы данных, т.к. пользователь не может подключиться к ней, используя Blank User-ID, и исследовать базу с целью поиска незащищенных данных. Попытка подключения будет отклонена, и никакой доступ не будет предоставлен вообще.
С точки зрения программирования это делает создание традиционного экрана обслуживания username/password более сложным. Если подключение к базе данных выполняется через клиент-сервер, то программист может временно хранить имя пользователя и пароль в памяти и использовать эти значения, чтобы инициализировать соединение с базой данных. Другими словами, никакие базы данных не будут подключены после запуска. В правильно защищенной среде подключение к разделяемой памяти будет невозможно, поскольку пользователь не сможет подключиться к сегментам разделяемой памяти базы данных после запуска команды _progres.
Решение этой проблемы состоит в том, чтобы найти золотую середину между двумя функциями «Disable Blank User-id». Должна быть создана универсальная учетная запись, у которой не должно быть абсолютно никакого доступа к таблицам! Это накладывает на администратора базы данных определенную ответственность, чтобы гарантировать, что данное ограничение будет им поддерживаться на протяжении всей жизни базы данных. Как только соединение установлено, программа подключения может использовать функцию SETUSERID(), чтобы изменить временный user-id на реальный user-id.
Конечно, как и со многими подобными решениями, есть незначительные проблемы. Чтобы проверить достоверность пароля пользователя через функцию SETUSERID(), у универсальной учетной записи должен быть доступ на чтение в таблицу _USER. Как результат: неавторизованный пользователь потенциально может скачать имена пользователей и пароли в зашифрованном виде, запустить на досуге программу взлома, а затем использовать взломанные пароли для получения незаконного доступа к базе данных.
Кроме того, даже если эта опция включена, клиент и сервер, прежде чем проверить достоверность комбинации имени пользователя и пароля, должны обменяться информацией из метасхемы, включая информацию из таблиц и полей. С помощью сниффера[6] сетевых пакетов можно сделать запись таких предварительных подтверждений подлинности и извлечь ценную информацию из загруженных данных метасхемы.
Имена пользователей и пароли
Как упоминалось ранее, правильное имя пользователя и пароль – это единственный способ получить доступ к защищенной базе данных. Таким образом, мы должны обеспечить безопасность этих «ворот», насколько это возможно.
Первое из самых часто встречающихся нарушений – это использование универсальных пользовательских учетных записей. Не должно быть одной учетной записи «SecAdmin» с паролем, известным двум пользователям. Вместо этого нужно назначить роль администратора безопасности каждому из этих пользователей, например, «KOUP» и «JACM». Делая так, вы не допустите двусмысленности относительно того, кто и что сделал. Например, при использовании OpenEdge Auditing с такой настройкой ролей вы всегда будете знать, кто выполнил изменение, а не будете выяснять, кто из этих двух пользователей действительно использовал учетную запись «SecAdmin».
Второе: путь доступа должен быть усилен введением сложных паролей и сроков их действия. Так как OpenEdge еще не имеет такую функциональность, то задача программиста включать эти функции в своё приложение. Когда пользователь выполняет регистрацию, программа подключения должна проверить возраст пароля и в случае необходимости принудить пользователя изменить его. Кроме того, чтобы изменять пароли пользователей, которые не используют систему определенное количество дней, можно использовать ночную пакетную обработку.
Наконец, важно упомянуть об очень общей бреши в защите баз данных OpenEdge. Когда база только создается, в SQL-таблице SYSDBAUTH создается учетная запись с user-id пользователя, который её создал и учетная запись sysprogress, которая по умолчанию имеет права администратора базы. Этим двум учетным записям устанавливаются SQL-привилегии «DBA» и «RESOURCE», фактически тем самым предоставляя им неограниченный доступ к данным и метасхеме через SQL.
Однако редко конкретные учетные записи, такие как «root», «administrator» или «sysprogress», определены в таблице _USER. Но если ни один администратор безопасности базы данных не был определен, то любой пользователь может создать нового пользователя, назвав его «root[7]», и назначить любой пароль, который только захочет. В этом случае новая учетная запись может быть использована для подключения через SQL, предоставляя пользователю неограниченный доступ к базе данных.
Решения
С учетом всех вопросов доступа к данным из предыдущих разделов для обеспечения безопасности существующего OpenEdge-приложения предлагаются следующие решения:
- Не включайте DB Options – Disable Blank User-ID.
- Включите DB Options – Runtime Security (начиная с 10.1A).
- Включите Security – Disable Blank User-ID.
- Назначьте роль администратора безопасности двум пользователям.
- Не допускайте использование универсальных учетных записей.
- Внедрите использование сложных паролей и срок действия паролей через ваше приложение.
- Гарантируйте, что все записи из SYSDBAUTH существуют в таблице _USER.
Представленные решения утверждают, что если пользователь предоставил правильное имя пользователя и пароль, то он должен иметь полный доступ ко всем данным в базе. На первый взгляд, это может показаться нелогичным, так как противоречит тому, что обсуждалось в последних двух разделах! Ответ прост. Если мы не можем эффективно распределить права доступа на уровне таблиц и полей, то самое простое решение состоит в том, чтобы предоставить полный доступ всем легальным пользователям и обеспечить им безопасный способ получения доступа к данным, т.е. мы должны построить следующий внешний уровень защиты.
[3] В 10.1A для проверки достоверности пользователей стали доступны новые методы. Обсуждение этих методов – отдельная тема, которая выходит за рамки этой статьи.
[4] Последние два поля относятся к владельцам схемы не-Progress баз данных, их описание выходит за рамки этой статьи.
[5] Любопытные могут посмотреть программу prodict/user/_usradmn.p из библиотеки prodict каталога src инсталляции OpenEdge
[6] Сниффер – это программа, которая позволяет перехватывать сетевой трафик. Когда говорят о снифферах, то обычно проводят аналогию с прослушиванием телефонных разговоров.
[7] Здесь имеется в виду случай, когда база данных была создана пользователем с учетной записью «root».
Метка:OpenEdge, OpenEdge Security