Каждый администратор базы данных или специалист по информационной безопасности в компании рано или поздно сталкивается с пугающей картиной при анализе журнала регистрации «1С:Предприятия». Просматривая события, мы обнаруживаем сотни записей с критической ошибкой «Доступ. Отказ в доступе». Самое удивительное, что эти события регистрируются под учетными записями рядовых сотрудников (например, бухгалтеров по материалам), а объектами ограничений выступают документы начисления зарплаты, кадровые приказы («Набор персонала») или конфиденциальные справочники.
Первая реакция руководства и службы безопасности — паника. Возникает подозрение, что сотрудники целенаправленно пытаются взломать систему, обойти ограничения прав и получить доступ к закрытой финансовой информации. Однако в 95% случаев это поведение является стандартной технической особенностью работы самой платформы 1С. Давайте подробно разберем, какие именно действия с базой данных порождают эти события, почему они происходят незаметно для пользователей и как оптимизировать систему, чтобы очистить журнал от технического «мусора».
Рассмотрим самую частую ситуацию в бухгалтерских конфигурациях (например, в «Управлении производственным предприятием 1.3» или «Бухгалтерии предприятия»). Бухгалтер-материалист открывает стандартный отчет — карточку счета или оборотно-сальдовую ведомость по счету 10 или 41. У этого пользователя есть полные права на чтение бухгалтерского регистра накопления или регистра бухгалтерии Хозрасчетный, но полностью закрыт доступ к документам начисления зарплаты и кадровым документам.
При формировании отчета система обращается к записям регистра. Каждая проводка или движение в регистре жестко связаны со своим документом-основанием через системное поле Регистратор. Проанализируем, что происходит на уровне платформы:
Посмотрим на пример запроса, который неявно выполняется платформой при выводе движений регистра:
// Пример запроса, извлекающего данные движений вместе с регистратором
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Регистр.Период КАК Период,
| Регистр.Регистратор КАК Регистратор,
| Регистр.Сумма КАК Сумма
|ИЗ
| РегистрБухгалтерии.Хозрасчетный КАК Регистр
|ГДЕ
| Регистр.Счет = &Счет";
Если в выборку попадает регистратор, на который у текущего сеанса наложен запрет чтения, СУБД вернет данные, но при попытке платформы преобразовать внутреннюю ссылку в понятное представление для пользователя произойдет генерация ошибки отказа в правах в фоновом режиме.
Второй по частоте источник ложных записей в журнале регистрации — это программный код разработчиков конфигурации. Особенно остро эта проблема стоит в старых типовых решениях или базах, работающих в режиме совместимости с версиями платформы 8.2 (например, 8.2.13 или 8.2.16).
При запуске системы, открытии различных панелей инструментов, формировании командного интерфейса или динамических меню система должна определить, какие кнопки и функции показывать конкретному пользователю. Для этого разработчики пишут код проверки прав. Выясним причину массовости этого события на примере следующего шаблона кода:
// Программная проверка прав для настройки видимости интерфейса
Если НЕ ПравоДоступа("Чтение", Метаданные.Документы.ЗарплатаКВыплатеОрганизаций) Тогда
ЭлементыФормы.ПанельЗарплата.Видимость = Ложь;
КонецЕсли;
Метод ПравоДоступа() возвращает булево значение (Истина или Ложь). С точки зрения логики кода это абсолютно штатная проверка, которая не прерывает работу программы. Однако на уровне платформы (особенно в старых релизах и при использовании режимов совместимости) каждый возврат значения Ложь в этой функции принудительно записывается в журнал регистрации как событие «Доступ. Отказ в доступе».
Представим, что у пользователя при входе в систему проверяются права на 50 различных документов и справочников, к которым у него нет доступа. При каждом запуске программы или обновлении интерфейса в журнал регистрации будет мгновенно записываться 50 ложных сообщений об отказе в доступе. Для стороннего наблюдателя это выглядит так, будто пользователь каждую секунду совершает попытки несанкционированного чтения данных.
Давайте разберем, как влияют запросы к базе данных на появление записей в журнале регистрации. Здесь критически важно понимать разницу между поведением платформы при наличии и отсутствии ключевого слова РАЗРЕШЕННЫЕ.
Проанализируем ситуацию, когда в коде отчета или обработки выполняется запрос к таблице документов без этого ключевого слова:
// Запрос без ограничения выборки разрешенными данными
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка, Номер, Дата ИЗ Документ.ЗарплатаКВыплатеОрганизаций";
Результат = Запрос.Выполнить();
Если у текущего пользователя нет роли, дающей право на чтение этой таблицы, то при выполнении метода Выполнить() произойдет следующее:
Теперь рассмотрим правильный с точки зрения безопасности сценарий с использованием ключевого слова РАЗРЕШЕННЫЕ:
// Безопасный запрос с фильтрацией на уровне СУБД
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ РАЗРЕШЕННЫЕ Ссылка, Номер, Дата ИЗ Документ.ЗарплатаКВыплатеОрганизаций";
Результат = Запрос.Выполнить();
В этом случае платформа не генерирует ошибку. СУБД просто молча отсеет те записи, к которым у пользователя нет доступа на уровне ограничений RLS (Row-Level Security), либо вернет пустой результат, если доступ к таблице закрыт полностью на уровне ролей. В большинстве современных релизов платформы 1С при использовании ВЫБРАТЬ РАЗРЕШЕННЫЕ ложные события «Отказ в доступе» в журнал регистрации не записываются, так как фильтрация считается штатным действием.
Однако, если у пользователя настроены сложные ограничения доступа на уровне записей (RLS) и в процессе выполнения запроса СУБД натыкается на связанные запрещенные таблицы, система может продолжить логировать факты фильтрации. Это зависит от глобальных настроек использования событий журнала регистрации в конфигурации.
Динамические списки (используемые в формах списков и общих журналах) работают по принципу фонового конструирования запросов. Если пользователь открывает общий журнал документов, система пытается оптимизировать отображение информации.
Даже если в динамическом списке настроен отбор по разрешенным типам документов, платформа при инициализации формы может запрашивать метаданные всех входящих в журнал объектов. Это необходимо для:
В этот момент фоновые механизмы платформы осуществляют проверку прав на недоступные пользователю типы документов (такие как кадровые приказы или начисления). Как результат — очередная порция ложных отказов в доступе регистрируется в системе под учетной записью открывшего форму сотрудника.
Еще одна неочевидная причина появления ошибок доступа — неявное чтение связанных объектов в коде. Разберем типичную ошибку программирования, которая приводит к лавинообразному заполнению журнала регистрации.
Предположим, у нас есть регистр сведений, хранящий информацию о связанных задачах. Одним из измерений регистра является реквизит с типом ЛюбаяСсылка. Программист пишет код обработки записей этого регистра:
// Неявное обращение к реквизитам связанного объекта через точку
Для Каждого СтрокаЗаписи Из ТаблицаЗаписей Цикл
ОрганизацияСсылка = СтрокаЗаписи.ОбъектСвязи.Организация;
КонецЦикла;
Если в поле ОбъектСвязи содержится ссылка на документ, к которому у текущего пользователя нет прав (например, на зарплатный документ), то при попытке выполнить выражение СтрокаЗаписи.ОбъектСвязи.Организация платформа попытается прочитать объект СУБД целиком, чтобы извлечь значение реквизита Организация.
Так как права на чтение объекта отсутствуют, транзакция чтения завершится неудачей на уровне платформы. Код может продолжить выполнение (вернув в результат Неопределено или пустое значение), но в журнал регистрации будет записано событие отказа в доступе к документу-источнику.
Посмотрим на практические критерии, которые помогут администратору базы данных или руководителю ИТ-отдела отличить реальные инциденты безопасности от технических особенностей платформы:
Рассмотрим комплекс мер, направленных на минимизацию количества ложных событий «Отказ в доступе» в базе данных:
Если ваша конфигурация позволяет, откажитесь от старых режимов совместимости (например, совместимости с 8.2.13 или 8.2.16). В современных версиях платформы 1С:Предприятие 8.3 алгоритмы логирования оптимизированы: вызовы функций проверки прав вроде ПравоДоступа(), возвращающие Ложь, больше не забивают журнал регистрации ложными записями об ошибках.
Замените в разрабатываемых модулях прямые вызовы проверки прав метаданных на более безопасные конструкции. Например, вместо циклического перебора метаданных и вызова ПравоДоступа(), проверяйте принадлежность пользователя к определенным ролям с помощью метода РольДоступна(), который не оставляет следов отказов в журнале регистрации:
// Более безопасный способ проверки прав через доступность роли
Если РольДоступна("ПолныеПрава") Или РольДоступна("ДоступКЗарплате") Тогда
ЭлементыФормы.ПанельЗарплата.Видимость = Истина;
Иначе
ЭлементыФормы.ПанельЗарплата.Видимость = Ложь;
КонецЕсли;
Если технический шум мешает анализу реальных угроз безопасности, вы можете программно или интерактивно настроить политику логирования. С помощью метода платформы УстановитьИспользованиеСобытияЖурналаРегистрации() можно гибко управлять тем, какие именно события отказа в доступе должны фиксироваться в базе данных, исключая избыточные проверки интерфейса.
Используя данные рекомендации, мы сможем не только успокоить руководство и службу безопасности подробным техническим обоснованием, но и значительно повысить читаемость журнала регистрации, сделав его реальным инструментом контроля безопасности, а не источником ложной тревоги.