Назад в блог

Безопасность OpenEdge-приложений

Автор: Перевод:
Paul Koufalis, President, Progreswiz Consulting
progresswiz1[1]
Башкатов В.Г.
logo_rupug_transparent

Перевод выполнен с разрешения автора. При любом использовании материала статьи обязательно указание гиперссылки на источник и информации об авторе и переводчике.

ВВЕДЕНИЕ

За последние несколько лет безопасность стала горячей темой в IT-сфере. Не смотря на то, что компании доверяют своим служащим, недавние проблемы у таких компаний как, например, Enron, WorldCom, доказали, что это, по крайней мере, наивно. В сегодняшнем мире компания должна применять превентивные меры, гарантирующие сохранность и безопасность одного из своих самых важных активов – данных.

Принятие решения о проактивной защите данных должно сопровождаться пониманием того, что никакая система обеспечения безопасности не может быть надежной на 100%, так как авторизованные пользователи должны иметь доступ к данным. Для каждого замка должен быть ключ, а если есть ключ, то рано или поздно способ открыть замок будет найден, и это факт, который просто нужно принять. Ситуация усложняется ещё и тем, что при попытке улучшить безопасность приложения вы, как конечный пользователь, вероятно столкнётесь с сопротивлением разработчика приложения, не предусматривающего в настоящее время в приложении требуемый функционал. И наоборот, как поставщик приложения вы можете столкнуться с апатией и отсутствием интереса со стороны клиентов, т.к. они хотят быстрый, простой и, главное, насколько это возможно, дешевый программный продукт.

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

ЦЕЛИ И ЗАДАЧИ

Главная цель статьи заключается в том, чтобы открыть глаза читателю на проблемы безопасности, о существовании которых он даже не подозревает. Вторая, не менее важная цель – это рассказать о простых и доступных в реализации способах защиты OpenEdge-данных (далее я буду называть их уровнями защиты).

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

АУДИТОРИЯ

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

ПОНИМАНИЕ УРОВНЕЙ

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

Уровни безопасности базы данных

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

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

Основные уровни защиты OpenEdge:

ДАННЫЕ

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

По умолчанию OpenEdge обеспечивает безопасность через определенные поля таблиц метасхемы _FILE, _FIELD и _INDEX. Эти поля известны как _CAN*-поля, т.к. их имена имеют вид _CAN-READ, _CAN-WRITE, _CAN-CREATE и т.д. Они существуют с ранних версий Progress[1] и по умолчанию имеют значение «*», что означает – полный доступ для всех. Чтобы это значило? База данных, в которой не были изменены поля безопасности, является открытой на 100% для чтения, записи, создания и удаления любым ABL-клиентом, который смог подключиться к ней. Заметьте, я не говорю об аутентификации, я говорю именно о подключении. Существование и/или использование имен пользователей и паролей не является достаточным, когда заданные по умолчанию параметры безопасности оставляют неизменными. С такими параметрами буквально все запросы на установление соединения с базой данных удовлетворяются, и у всех таких подключенных процессов есть беспрепятственный доступ к данным.

Управление доступом происходит иначе, когда к базе выполняется SQL-подключение. Начиная с версий Progress 9, в СУБД было добавлено родное ядро SQL, а вместе с ним и более совершенная SQL-защита. В SQL-модели наличие пользователей является обязательным, а объекты базы данных по умолчанию принадлежат тому пользователю, который их создал. Другими словами, только создатель объекта базы данных может читать, изменять, создавать или удалять данные в пределах объекта. Любой другой пользователь для обращения к данным должен получить соответствующий доступ, который может предоставить (GRANT) владелец объекта или администратор базы данных.

Сравнивая эти две модели защиты, довольно ясно можно понять – они полностью противоположны друг другу. Модель защиты OpenEdge по умолчанию – это «GRANT * TO * (PUBLIC)», т.е. всем пользователям по умолчанию предоставлены все привилегии. В терминах SQL заданная по умолчанию безопасность OpenEdge эквивалентна выполнению команды «GRANT ALL ON object TO PUBLIC» для каждого объекта в базе. С другой стороны, модель SQL – это «GRANT Ø TO Ø (NOBODY)», т.е. по умолчанию ни у кого нет никаких привилегий.

Когда дело доходит до управления SQL- и OpenEdge- безопасностью, задачи администратора базы данных, так же как и модели защиты, противоположны. На стороне OpenEdge доступ установлен в «PUBLIC», поэтому администратор базы данных должен изменить _CAN*-поля, чтобы ограничить возможности пользователей. Это достигается путем замены знака «*» (PUBLIC) на конкретные ID пользователей и/или маски. Например, «FIN*» означает, что всем пользователям, имена которых начинаются на «FIN», предоставлены привилегии _CAN*. Кроме того, доступ может быть запрещен знаком «!», если он один, это означает, что «пустому пользователю» (Blank User ID) доступ запрещен, если он имеет дополнительные символы или выражения (маску), например, «!FIN*», то это означает, что всем пользователям, имена которых начинаются с «FIN», привилегии _CAN* запрещены. В SQL мы явно выполняем оператор GRANT в следующем виде «GRANT privilege ON object TO user-id». Например, команда «GRANT SELECT ON PUB.CUSTOMER TO KOUP» разрешает пользователю, аутентифицированному как KOUP, выбирать данные из таблицы CUSTOMER в схеме PUB.

Другой очень важный факт относительно безопасности OpenEdge заключается в том, что до 10.1A _CAN*-ограничения применялись только в момент компиляции. Например, пользователь, компилирующий программу, которая изменяет таблицу CUSTOMER, должен иметь права на _CAN-WRITE, чтобы получить доступ к этой таблице. Однако, как только r-код сгенерирован, любой пользователь может использовать его, чтобы успешно изменить таблицу CUSTOMER – _CAN*-поля полностью игнорируются. Для примера представим себе разработчика, у которого обычно нет доступа к промышленной базе данных. Если он попытается выполнить запросы к этой базе, то настройки _CAN*-полей будут препятствовать ему, а его запросы не будут компилироваться. Однако тот же самый разработчик может скомпилировать свой запрос на идентичной базе данных разработки, к которой у него, по-видимому, есть полный доступ, и сгенерировать r-код, чтобы затем успешно выполнить его на промышленной базе данных.

Чтобы нейтрализовать эту брешь в защите, специалисты Progress разработали функцию DBAUTHKEY, которая внедряет уникальный идентификатор базы данных в r-код, и это позволяет выполнить его только на конкретной базе данных. Другими словами, r-код, откомпилированный на базе данных разработки, не будет выполнен при подключении к промышленной базе данных. К сожалению, профессиональные хакеры нашли способ обойти безопасность DBAUTHKEY (как и в случае других функций защиты данных). Сегодня функция DBAUTHKEY подобна сигналу тревоги на вашем автомобиле – достаточное средство устрашения против бесхитростных атак, но бесполезное против интеллектуального и решительного противника. Тем не менее, есть смысл в использовании функции DBAUTHKEY, она чрезвычайно проста в реализации, но в то же время её сравнительно сложно обойти. В сочетании с другими решениями, предлагаемыми в статье, эта функция уменьшает вероятность взлома вашей базы данных.

Реальное решение проблемы «_CAN*» было реализовано в OpenEdge 10.1A. У администратора базы данных появилась возможность с помощью опции «Enable run-time security» установить проверку прав доступа во время выполнения r-кода. Если эта опция включена, то каждая ABL-попытка доступа к базе данных будет проверяться независимо от источника запроса (в данном случае – r-код или динамически сгенерированный запрос).

Теперь у администратора базы данных есть возможность проверить достоверность доступа во время выполнения. Остается определить, какие пользователи должны иметь доступ к тем или иным таблицам. Легко сказать: «Пользователь X имеет доступ к записям о коммерческих заказах». Труднее экстраполировать этот функционал доступа к базе данных. Какие таблицы и поля требуются для доступа к коммерческим заказам? Их необходимо только читать, или заказы разрешено изменять, создавать и удалять? Что если изменение записи о коммерческих заказах вызывает другие программы, отвечающие за обновление запасов, поставок, заказов на выполнение работ или на планирование? Возможно, что пользователю также должен быть предоставлен доступ к таблицам в базе данных, связанным с этими действиями, но только в пределах строгих границ заказа. Другими словами, пользователь может изменить имеющийся уровень запасов, подтверждая заказ, но не может войти в блок «Обслуживание Запасов» и вручную управлять уровнями запасов.

Остановитесь и задумайтесь: мы почти завершили полный цикл! Первоначально безопасностью управляли только через приложение. Этого, как оценивалось, было недостаточно из-за многих способов, которые использовались для обращения к данным вне границ приложения. В результате, чтобы управлять доступом к данным независимо от источника, была реализована безопасность во время выполнения. Однако в приложении может потребоваться более либеральный доступ пользователя к данным для поддержания функциональных требований. Приложение может требовать, чтобы к определенным объектам был предоставлен косвенный доступ, тогда как прямой доступ к тем же объектам должен быть запрещен! Как это сделать? Мы предоставим доступ на этот уровень безопасности и более надежно защитим внешние уровни, ограничив каналы, через которые пользователь может обратиться к данным! Прежде чем я начну рассказывать, как это сделать, мы должны изучить следующий уровень защиты, реализованный в самой СУБД[2].

База данных

Имеется несколько способов для обращения к базе данных 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.

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

СРЕДА

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

Среда разработки

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

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

Лицензии Разработки

На основании лицензионных ключей из файла конфигурации progress.cfg, который размещен в инсталляционном каталоге, Progress обеспечивает три уровня доступа к базе данных:

  1. Runtime: могут выполняться только предварительно откомпилированные программы (r-код).
  2. Query: в данном случае могут выполняться запросы, которые не изменяют базу данных, могут быть откомпилированы на лету, но только предварительно откомпилированные программы (r-код) могут изменять данные.
  3. Full Dev: пользователь может выполнять запросы, которые могут читать, изменять, создавать или удалять данные.

Относительно этих лицензий существует одно простое правило:

«Пользователи, обладающие лицензиям разработки, не должны иметь возможность обращения к промышленным данным с этими лицензиями».

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

DBAUTHKEY

Как упоминалось ранее, функция DBAUTHKEY устанавливает ограничение, которое определяет, какие программы (r-код) могут быть выполнены на тех или иных базах данных. При использовании функции DBAUTHKEY программы, откомпилированные на незащищенной тестовой базе данных, не могут быть выполнены на промышленной базе данных.

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

PROPATH

Незащищенный PROPATH является одной из самых простейших, и в то же время, самой недооцененной «брешью» в безопасности, которую я когда-либо встречал. Переменная окружения PROPATH закладывает основу, в пределах которой команды RUN находят ABL-программы, которые они пытаются выполнить. Если возможность изменения PROPATH не заблокирована, или если он содержит символ точки «.», то это позволяет хакерам вместо исходного кода программы подставлять свой собственный код, используя то же самое имя и структуру каталогов как в оригинале.

Ограничение возможностей PROPATH также препятствует другой распространенной практике – выполнению тестирования разработчиками в промышленной среде. Разработчик должен осуществить исправление, но у него нет прямой возможности воспроизвести проблему на промышленной базе. Чтобы выйти из этой ситуации, он изменяет свой личный PROPATH в промышленной среде и выполняет тестовую версию программы вместо оригинала. Типичный результат: вместо того, чтобы исправить исходную проблему, тестовая программа привела к ещё большему нарушению целостности данных.

Дополнительно. Ограничьте возможности использования каталогов и файлов, найденных в PROPATH. Эти каталоги содержат все необходимые приложению программы, которым должны быть выставлены права только на чтение для обычных пользователей, т.е. чтобы они могли их только выполнять. Если вы блокируете изменение PROPATH, но позволяете пользователю записать в один из каталогов PROPATH инородную программу, то базе данных может быть причинен наибольший ущерб, т.к. её будут использовать все пользователи.

AppServer

AppServer – это фактически ABL-клиент, который может выполнить программу от имени удаленного пользователя. Буквально можно сказать, что пользователь, подключаясь к AppServerу, говорит: «Пожалуйста, выполни эту программу». Потенциальный хакер может положить свою программу где-нибудь на сервере, на котором работает AppServer и запросить, чтобы AppServer её выполнил. Теперь, если окажется, что у AppServerа есть более высокий доступ безопасности, чем у пользователя (например: если AppServer запущен пользователем root), то он благополучно выполнит программу хакера от имени пользователя!

Чтобы избежать этого, необходимо ограничить возможность хакера выкладывать программы туда, где AppServer может их обнаружить. Однако мы также можем ограничить сам AppServer, используя функцию SESSION:EXPORT. Эта функция позволяет ограничить список выполняемых программ на AppServerе.

$DLC

Для установки продуктов OpenEdge требуется учетная запись root (или administrator), но по умолчанию доступ открыт для всех ко всему содержимому инсталляционного каталога. Нет ничего проще этого для того, чтобы облегчить жизнь похитителя данных.

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

Во-вторых, во всех каталогах $DLC ограничьте возможность чтения библиотек программ, к которым нормальный пользователь во время работы не должен обращаться. Например, библиотеки программ, содержащие программы Progress Editor и Data Dictionary, не требуются обычным пользователям. Ограничьте возможность доступ к этим файлам.

Также ограничьте права доступа на выполнение инструментальных средств Progress в каталоге $DLC/bin, таких как _mprosrv (запуск базы данных), _mprshut (останов базы данных), _proutil (общая утилита базы данных) и _rfutil (утилита для работы с After-Imaging).

Наконец, ограничьте возможности доступа ко всем файлам в каталоге $DLC/properties. Они содержат стартовую информацию, используемую AdminServerом, AppServerами, продуктом OpenEdge Management и прочими процессами OpenEdge. Только члены группы администратора базы данных должны иметь возможность изменять эти файлы.

Запуск процессов сервера

Считается, что после установки Progress с использованием учетной записи root процессы сервера должны по умолчанию запускаться с помощью этой же учетной записи. Так не должно быть. Учетная запись root должна быть ограничена только выполнением процессов операционной системы. Для сервера базы данных – AdminServerа и AppServerов – должны  быть созданы отдельные сервисные учетные записи. Причем это должны быть учетные записи без возможности подключения к серверу (no-login accounts.). Мы ведь не хотим создавать универсальные учетные записи, к которым у нескольких пользователей есть пароль. Вместо того чтобы запускать процессы, используя параметры доступа сервисной учетной записи, можно использовать такие инструментальные средства как «su» или «sudo».

Это особенно важно для AdminServerа, поскольку по умолчанию он запускает дочерние элементы (AppServer, WebSpeed Transaction Server, NameServer, и т.д) с использованием той же самой учетной записи. Если установлен OpenEdge Management, то он работает в той же самой JVM[8] что и AdminServer, тем самым предоставляя администратору OpenEdge Management полный «рутовый» доступ к серверу. То же верно для WebSpeed. Любой обратившийся к странице WebSpeed Workshop может потенциально иметь доступ к командной строке UNIX с «рутовыми» полномочиями.

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

Shell-доступ

Хотя об этом можно было и не говорить, я чувствую, что обязан заявить, что ни у одного пользователя не должно быть shell-доступа в UNIX. Пользовательский скрипт доступа должен немедленно направлять пользователя в его приложение. Для запуска приложения должна использоваться UNIX-команда «exec». Без этого нетерпеливый пользователь может нажать комбинацию клавиш во время выполнения скрипта и оказаться в командной строке.

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

Решения

Повторюсь еще раз: область Вашей ответственности заключается в том, чтобы сделать задачу хакера наиболее трудной – установить на его пути большое количество барьеров. Кроме того, Вы не должны помогать ему, «разбрасывая вокруг» различные инструментальные средства.

  • Не обновляйте базы разработчиков промышленными данными.

  • Не предоставляйте пользователям полные лицензии разработки для доступа к промышленным данным.

  • Используйте функцию DBAUTHKEY.

  • Удалите точку («.») из PROPATH.

  • Ограничьте возможность доступа к файлам и утилитам в инсталляционном каталоге OpenEdge.

  • Не используйте учетную запись «root» для запуска сервера базы данных и различных фоновых процессов.

  • Не предоставляйте пользователям доступ к Shell.

ФАЙЛОВАЯ СИСТЕМА

В клиент-серверной среде у пользователей, как правило, нет доступа к серверу, содержащему базу данных, и тем более к файловой системе. Однако существует большое количество OpenEdge-приложений, полностью основанных на архитектуре host-based и имеющих символьный интерфейс (ChUI) с прямым подключением к разделяемой памяти базы данных. В подобных типах развертывания должны быть защищены файловые системы, содержащие базу данных, коды программ и различные служебные файлы.

У обычных пользователей не должно быть доступа для записи в любой из файлов или каталогов, содержащих инсталляцию OpenEdge, а также не должно быть возможности изменения кодов программ или файлов базы данных непосредственно. Например, только у пользователя root должен быть доступ для записи в каталог $DLC с возможным исключением каталога $DLC/properties, т.е. изменять файлы настроек в этом каталоге можно позволить и другим специальным пользователям. Точно так же нужно разрешить запись кодов программ в каталоги лишь группе пользователей, внедряющих приложение.

Бит SetUID

Часто недооценивается атрибут setuid-бит (только для UNIX), который позволяет пользователю выполнить программу с уровнем безопасности владельца программы. В случае с OpenEdge клиентская исполняемая программа _progres принадлежит пользователю root, поэтому все ABL-пользователи инициализируют свои сессии от имени этого пользователя. Однако как только процесс инициализации закончен, программа _progres автоматически понизит свой уровень безопасности до уровня пользователя, который её запустил.

Почему был выбран такой путь? Если приложение было правильно внедрено, то пользователи не должны иметь возможностей для изменения файлов базы данных и сегментов разделяемой памяти напрямую, что не дает неправомерному пользователю случайно или преднамеренно удалить или физически разрушить базу данных. Однако чтобы позволить программе _progres подключаться к базе данных, она запускает свою сессию от имени пользователя root, который имеет полный доступ ко всем файлам и в состоянии открыть файлы базы данных и сегменты разделяемой памяти. Как только это сделано, программа понижает свой уровень безопасности, но сохраняет открытые хэндлы к файлам базы данных и разделяемой памяти.

Защита базы данных

По крайней мере, все файлы базы данных и каталоги должны принадлежать одной обслуживающей учетной записи (напр.: prodba), и только этой учетной записи нужно разрешить чтение и запись в эти каталоги и файлы. Как объяснялось выше, у пользователей, которые подключаются к базе данных при запуске, не возникнет никаких проблем связанных с подключением к разделяемой памяти. Но пользователи, которые попытаются подключиться к базе данных после запуска сессии, столкнутся с ошибкой прав доступа и будут вынуждены выполнить подключение через клиент-сервер.

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

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

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

Решения

  • Удалите все права на чтение, запись и выполнение у всех файлов базы данных и каталогов, в которых они хранятся.

  • Удалите права на запись у всех каталогов с кодами программ.

  • Удалите права на запись у всех файлов параметров и каталогов, в которых они хранятся.

  • Не храните исходный код программ на промышленных серверах. Выполняйте компиляцию этих программ на серверах разработки и используйте только полученный r-код на промышленных серверах.

СЕРВЕР

Как уже говорилось ранее, в клиент-серверной среде у пользователя вообще не должно быть никакого доступа к промышленному серверу базы данных, кроме как через предопределенные ABL-, SQL- и AppServer- порты. Локальные пользователи должны иметь доступ к серверу только через терминальную сессию. Если нет необходимости в иных настройках для достижения четкой цели, то всё остальное должно быть закрыто. К сожалению, это не всегда так. Введите на вашем UNIX- или Windows- сервере команду «netstat -a | grep LISTEN» и вы увидите всех «слушателей», которые ждут подключения извне.

Дополнительно: по умолчанию к большинству серверов обращаются через незашифрованные утилиты, такие как telnet и ftp. Поэтому достаточно просто выполнить прослушивание пакетов с открытым текстом и извлечь из них пользовательские имена и пароли.

Наконец, на некоторых серверах работают утилиты совместного использования файлов, например, «Samba». В то время как «Samba» может показаться простой в установке, настройке и выполнении, она по умолчанию довольно небезопасна. Простой пример: администраторы устанавливают «Samba» так, чтобы пользователи могли генерировать отчеты в текстовые файлы, а затем открывать их через обычный проводник Windows. Тем самым они  предоставляют всем пользователям доступ к их домашним каталогам в UNIX. Однако это также дает пользователю возможность изменить свой профайл (.profile), который задает сценарий входа в Unix. В результате пользователь может сам себе предоставить доступ к Unix-оболочке (shell access).

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

Решения

  • Остановите все сетевые службы, в которых нет необходимости.

  • Замените все стандартные утилиты на их аналоги, позволяющие использовать шифрование.

  • С осторожностью используйте инструментальные средства для разделяемого доступа к файлам, такие как «Samba». Выполняйте их тщательную настройку и тестирование.

СЕТЬ

Самый внешний уровень защиты – это сеть. Правильно настраивая сеть, системные и сетевые администраторы могут полностью управлять доступом к серверу, содержащему файлы и менеджера базы данных. Самый простой способ достичь этого – использовать Virtual Local Networks, или VLAN.

Сети VLAN позволяют администратору сети отделить сетевой трафик, предназначенный для сервера от всего другого сетевого трафика. Используя программное обеспечение систем сетевой защиты (firewall), например, Checkpoint, администратор может определить, какие компьютеры из каких других VLAN могут получить доступ к сетевым ресурсам VLAN с сервером базы данных. Например, сеть может быть настроена так, чтобы серверы базы данных находились в VLAN 10.10.10.x; все пользователи, относящиеся к финансам – в VLAN 10.10.20.x; а все сотрудники склада находятся в VLAN 10.10.30.x. С помощью firewall администратор может настроить так, чтобы рабочие станции из VLAN 10.10.20.x имели доступ к VLAN 10.10.10.x, и запретить доступ к рабочим станциям из VLAN 10.10.30.x. Отметьте, что это не исключает несанкционированное использование рабочей станции финансистов из VLAN 10.10.20.x. Если вице-президент по финансам уйдет домой вечером и оставит свою рабочую станцию разблокированной, то любой человек потенциально может получить доступ к финансовым данным всей компании!

Открытые сетевые порты также могут предоставить доступ потенциальному злоумышленнику для взлома базы данных. Обычные попытки подключения через программу _progres обрабатываются и защищены функциями безопасности OpenEdge. И наоборот – нельзя так легко управлять сетевым доступом непосредственно к серверу базы данных или к TCP/IP-порту брокера. Такое взломанное подключение, вероятно, не будет следовать стандартным протоколам установления связи и, таким образом, не обязательно будет разъединено. Нельзя быть полностью уверенным в том, что таким образом из базы данных может быть извлечена полезная информация, но это все еще остается вероятным. Всё, что необходимо, – это хакер с правильными инструментальными средствами и мотивацией попробовать выполнить взлом.

Кроме того, как уже отмечалось ранее, рабочие станции или сервера с полными Progress-лицензиями разработки не должны иметь возможности доступа к промышленным серверам баз данных. Самый простой способ достигнуть этого – снова использовать VLAN-сегрегацию. Если человек выполняет двойную роль (разработка и поддержка), то он может легко получить доступ к промышленным данным через отдельный компьютер или через удаленный рабочий стол (например, программное обеспечение Citrix), установленный на компьютере. Учитывая, что стоимость более-менее адекватной рабочей станции меньше тысячи долларов, то нет аргументов против установки двух рабочих станций для поддержки двух пользовательских ролей.

Решения

  • Изолируйте и контролируйте доступ к серверам баз данных через VLAN-сети.

  • Не позволяйте доступ к промышленным серверам рабочим станциям и серверам разработчиков.

ПОЛЬЗОВАТЕЛИ

Грустно об этом говорить, но именно сотрудники наиболее вероятно являются потенциальной брешью в защите организации. Независимо от того, сколько вы им платите, всё равно найдется кто-то, кому всегда не хватает лишних нескольких сотен, а то и тысяч долларов. А если для того, чтобы заработать эти деньги, нужно лишь извлечь немного информации из вашей базы данных – что сможет их остановить? Хорошо, предположим, что все ваши сотрудники честные и заслуживают доверия, но ведь ещё никто не отменял человеческий фактор, вследствие которого ваши данные могут быть повреждены или окажутся доступными для чужих людей. Идеальный пример: разработчик, у которого на рабочем столе Windows открыто много окон, некоторые из них подключены к промышленной среде, а некоторые к среде разработки. Не трудно понять, что рано или поздно он ошибётся и случайно сделает что-нибудь в промышленной среде вместо среды разработки.

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

Еще один пример, о котором упоминалось ранее – пользователи, которые не блокируют свои рабочие станции. Достаточно одной или двух минут нахождения за таким рабочем столом, чтобы распечатать или отправить по e-mail данные, к которым вор обычно не имел доступа. В итоге все действия по обеспечению безопасности могут быть сведены к нулю из-за пресловутого человеческого фактора. Не существует простых правил для его исключения, и уж тем более будет сложно добиться исполнения этих правил, даже если их создать!


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

[2] СУБД – Система Управления Базами Данных

[3] В 10.1A для проверки достоверности пользователей стали доступны новые методы. Обсуждение этих методов — отдельная тема, которая выходит за рамки этой статьи.

[4] Последние два поля относятся к владельцам схемы не-Progress баз данных, их описание выходит за рамки этой статьи.

[5] Любопытные могут посмотреть программу prodict/user/_usradmn.p из библиотеки prodict каталога src инсталляции OpenEdge

[6] Сниффер – это программа, которая позволяет перехватывать сетевой трафик. Когда говорят о снифферах, то обычно проводят аналогию с прослушиванием телефонных разговоров.

[7] Здесь имеется в виду случай, когда база данных была создана пользователем с учетной записью «root».

[8] JVM – Java Virtual Machine


Назад в блог