Вопрос

Добрый день.

Я занимаюсь аудитами защищенности веб-приложений. В одном из проектов наш заказчик использовал bpm'online. В его конфигурации было выявлено ряд уязвимостей к SQL-инъекции.

Типичный пример уязвимого кода (имена метода и переменных изменены; значение параметра email контролируется пользователем):

using Terrasoft.Core.DB
…
 
private Guid GetUserId(string email)
{
    var select = new Select(Connection)
        .Column("Id")
        .From("Users")
        .Where("Email")
        .IsEqual(Column.Const(email)) as Select;
    return select.ExecuteScalar<Guid>();
}

Данный код использует метод Column.Const для передачи параметра, полученного от пользователя в SQL-запрос. Этот метод осуществляет конкатенацию этого параметра с запросом, не фильтруя специальные символы.

Это позволяет пользователю, контролирующему передаваемый в метод Column.Const параметр, выполнить атаку типа SQL-инъекция. То есть получить доступ ко всей информации в базе данных.

Мы порекомендовали нашему Заказчику использовать Column.Parameter вместо Column.Const в данном случае.

Документация Террасофт не сообщала (на момент публикации) об опасности некорректного примененеия метода Column.Const. В документации на Академии даже содержались некорректные примеры использования.

Я связался с поддержкой Террасофт и изложил проблему. Их позиция - ответственность лежит на разработчиках, но документацию они обещали поправить (и уже частично поправили).

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

Рекомендую вообще не использовать Column.Const, заменить на Column.Parameter, либо делать это крайне осторожно, будучи абсолютно уверенным что в настоящий момент, или при будущих изменениях значение параметра не будет контролироваться пользователем.

Для отслеживания данной проблемы зарегистрирован идентификатор: CVE-2019-15301.

У меня такой же вопрос

1 комментарий

Вообще, в самом Column.Const нет ничего криминального, правильное его использование упомянуто тут в начале статьи:

new Insert(UserConnection)
.Into("Table")
.Values()
    .Set("Column1", Column.Const(1))
    .Set("Column2", Column.Const(1))
    .Set("Column3", Column.Const(1))
.Values()
    .Set("Column1", Column.Const(2))
    .Set("Column2", Column.Const(2))
    .Set("Column3", Column.Const(2))
.Values()
    .Set("Column1", Column.Const(3))
    .Set("Column2", Column.Const(3))
    .Set("Column3", Column.Const(3))
.Execute();

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

Если ещё остались статьи с неправильным применением, нажмите кнопку внизу их и оставьте замечание со ссылкой на эту тему.

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

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

Создана преднастроенная страница.

При открытии два обязательных поля

Проблема. Обязательность первого поля не работает. Система позволяет сохранить данные с незаполненным полемИзображение удалено.

В конфигурации страницы добавлен признак обязательности

Так же на атрибут повешен признак isRequired: true

Однако это не дает ровным счетом ничего

Так же, ни последующая валидация при сохранении, ни правила не помогли

Если кто сталкивался с подобным, подскажите как выходили из ситуации

Спасибо

 

У меня такой же вопрос

4 комментария

Попробуйте для установки обязательности поля использовать бизнес-правила. 

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

Алла Савельева, Пробовал бизнес-правила. Не помогло.
Спасибо

Дубов Андрей Владимирович,

Приведите пример Вашего кода

Без изучения кода карточки сложно сказать.

Как обходной вариант, на уровне БП проверять значение, если пусто, показывать сообщение и карточку повторно, пока не заполнит правильно.

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

Доброго дня.

Необходима интеграция с корзиной сайта, откуда заказы валятся на Magento 1.

Настроено API: есть URL-адрес для подключения с Magento, user и login.

Не понятна сама настройка веб-сервиса в bpm'online. Сталкивался ли кто-то с данной интеграцией, либо может кто-то теоретически понимает это?

У меня такой же вопрос

2 комментария

Дополнение. Подключение посредством SOAP.

Добрый день!

Не уверен, что есть какой-то готовый коннектор (по крайней мере на маркете я ничего не нашёл), но в любом случае, можно запилить свою интеграцию через свой SOAP сервис. Правда для этого нужны компетенции и в bpm и в api magento.

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

Добрый день.

Подскажите, пожалуйста, наилучший способ массового перевода пользователей на авторизацию через AD.

 

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

Можно ли это сделать скриптом через БД или сделать ре-импорт с неким ключом?

У меня такой же вопрос

3 комментария

Nastol Eugene,

Про настройку bpm с AD понятно, вопрос был, как массово перевести пользователей на авторизацию AD

Разве что разрабатывать логику на уровне конфигурации, используя код из упомянутых здесь схем библиотек для LDAP. Проще вручную открыть и выбрать по каждому. Тем более, что названия пользователей и групп в bpm'online и в AD могут и не совпадать.

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

При добавлении зависимости следующим образом:

"RoundPropertyPriceWithDiscount": {
    dependencies: [
        {
             columns: ["PropertyPriceWithDiscount"],
             methodName: "roundPropertyPriceWithDiscount"
        }
    ]
}

и обработки методом:

roundPropertyPriceWithDiscount: function() {
	this.roundDoubleValue("PropertyPriceWithDiscount");
},
roundDoubleValue: function(propertyName) {
	var value = this.get(propertyName);
	var rounded = Math.round(value);
 
	if (rounded != value) {
		this.set(propertyName, rounded);
	}
},

происходит зацикливание. Кейс:

вводим в поле 5,56 - запускается метод, записывающий в поле 6,00, далее запускается еще раз (очевидно), проверяет что значение в поле равно его округленному значению (6,00 == 6,00) и значение в поле НЕ ПЕРЕЗАПИСЫВАЕТ. И вот далее идет ТРЕТИЙ запуск, в котором this.get() возвращает старое значение поля - 5,56. Ну и, естественно, это бесконечный цикл. Каким образом работает сей механизм? Если мне не изменяет память - в прошлых версиях такого не было.

7.13.1.769_SalesEnterprise_Softkey_MSSQL_ENU

 

UPD: Подписка на изменение поля вручную решает вопрос

this.on("change:PropertyPriceWithDiscount", this.roundPropertyPriceWithDiscount, this);

 

У меня такой же вопрос

2 комментария

Добрый день!

Если я правильно понял Ваш бизнес-кейс, то вы его неправильно реализовали. Если при изменении одного поля нужно взять значение этого поля, округлить его и записать в другое поле, то вам нужно делать this.set("RoundPropertyPriceWithDiscount", value);

Тёскин Дмитрий Валерьевич,

Нет, я все правильно написал. Округление значения в том же самом поле. 

RoundPropertyPriceWithDiscount это просто название атрибута

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

Всем доброго дня. Версия 7.13.4.

На портал (в рабочее место портала) были добавлены разделы.

Они открываются под портальным пользователем. Там всё хорошо.

Но требуется, чтобы они были видны и под пользователем Сотрудника. В том же виде, что и на портале. Как это сделать?

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

У меня такой же вопрос

3 комментария

Добрый день!

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

Тёскин Дмитрий Валерьевич пишет:

Тёскин Дмитрий Валерьевич пишет:
Добрый день!Если я не ошибаюсь, разделы портала отличаются от обычных и их нельзя добавлять в рабочие места обычных сотрудников (и наоборот)

А как же "Обращения" и "База знаний"? 

Владимир, это полностью разные разделы. Общие у них только объекты, а страницы свои: PortalCaseSection, PortalCasePage, PortalCaseSectionActionsDashboard, PortalKnowledgeBaseSection, PortalKnowledgeBasePage и др.

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

Добрый день.

На главной странице портала, есть грид с обращениями.

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

Как это можно реализовать?

У меня такой же вопрос

1 комментарий

Главная страница портала — по сути, та же страница-панель итогов. Самодельные виджеты в неё должны добавляться аналогичным образом. Только нужно учитывать ограничения прав на все объекты для портальных пользователей, если доступ не разрешён специально.

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

Добрый день.

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

И новом процессе начать создание массового инцидента.

Вопрос можно ли из процесса закрыть процесс запущенный ранее.

Как это реализовать?

У меня такой же вопрос

1 комментарий

Можно в скриптаске

Тема неоднократно обсуждалось, посмотрите например этот пост

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

Привет. 
Есть пакет Module_1 со своими схемами после этого был создан пакет Module_2 где уже были добавлены свои схемы. В ходе разработки была необходимость в схеме объекта Module_1 использовать объекты Module_2 поэтому поэтому первый был унаследован от второго. Все шло хорошо до момента когда пришла необходимость уже в пакете Module_2 использовать схемы Module_1. 

Как правильно выйти из этой ситуации?
Есть конечно идея каким-то образом проследить все связи Module_1 от Module_2, правда не очень понятно как делать это не вручную, и создать новый пакет Module_3 куда поместить замещенные схемы из Module_1 которые зависимы от Module_2 и построить эти зависимости заново(переделать тот же функционал) после этого перестроить иерархию как она должна быть, т.е. Module_3 -> Module_2 -> Module_1 или Module_2 -> Module_1 если каким-то образом переместить схемы с первого во второй(которые зависят).
*Сейчас при попытке удалить зависимость "грубо" Module_1 от Module_2 мы получаем то что на скрине без подсказок какие именно связи схем не дают удалить.

**Создавать(замещать) схемы которые должны зависеть от первого пакета в третьем т.е. выносить из второго не есть хорошо. 

У меня такой же вопрос

1 комментарий

Вопрос закрыт.

Пошел по пути:

1. Устранение связей с Entity (которые ссылаются на схемы Module_2) в Entity схемах в Module_1.

2. Удаление зависимости от пакета Module_2 в Module_1 и создание обратной(Module_2 от Module_1).

3. Создание замещенных Entity в Module_2(которые были изменены) и восстановления связей.

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

Добрый день!

Столкнулись с ситуацией, когда у Контакта несколько средств связи и поиск производиться только по последнему добавленному:

 

Есть ли пути решения данной ситуации?

У меня такой же вопрос

5 комментариев

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

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

Или же явно ищите по детали средств связи контакта, настроив в разделе соответствующий расширенный фильтр.

Искала через глобальный поиск:

Да, через глобальный должно найти, если он настроен.

Результаты будут примерно в таком виде:

list_of_search_results.png

Поиск настроен, ищем через него. На изображении ниже отображается подобным образом поиск, если система ничего не нашла.

Это не глобальный поиск, а стандартный фильтр по значению поля.

Войдите или зарегистрируйтесь, чтобы комментировать