Модуль даёт другим модулям заготовки для синхронизаций, и самые опасные места у него общие с ними: кто может запускать агенты и импорт, что ложится в каталоги импорта, что уходит в SQL и в лог. Ниже — что держит модуль и что остаётся проекту.
Модуль даёт другим модулям заготовки для синхронизаций, и самые опасные места у него общие с ними: кто может запускать агенты и импорт, что ложится в каталоги импорта, что уходит в SQL и в лог. Ниже — что держит модуль и что остаётся проекту.
\Shef\InSync\Main\Access::canManage() — одно правило на весь модуль:
Модуль импорта — тот, чей агент или класс импорта: права на shef.demosync
открывают его импорт, но не агенты main. Трогать из интерфейса модуля можно
только агенты импорта — наследники \Shef\InSync\Agents\AAgent: право «W» на
sale или crm не открывает их штатные агенты, это остаётся администратору
в списке агентов ядра. Для страницы статистики и перехода
к таблице импорта — права на shef.insync.
Проверяется и на показ, и в действии: адрес ajax-действия виден в коде
страницы и вызывается напрямую. До 2.0.0 все действия модуля стояли на
Actions\Normal — это умолчания ядра, вход на портал и csrf, — и любой
вошедший сотрудник:
Сторожит tests/access_test.php.
Каталог импорта — \Shef\InSync\Main\Constants::getImportDir(). По
умолчанию он на уровень выше корня сайта:
Внутри: <код>/ — файлы на импорт, copy/<код>/ — архив, problem/<код>/ —
файлы с проблемой (Sync\FromFile\AFileProcess::getImportFolder(),
getDoneFolder(), getProblemFolder()).
В выгрузках — цены, клиенты, заказы. Вне корня сайта веб-сервер их не отдаёт,
настраивать для этого ничего не нужно. До 2.0.0 каталог был /upload/import,
под корнем сайта, а имена архива — из кода импорта и даты с точностью до
минуты: перебором за срок хранения выгрузку скачивал кто угодно.
Проект задаёт каталог в /bitrix/.settings_extra.php:
return [
'shef.insync' => [
'value' => [
'importDir' => '/var/data/import',
],
'readonly' => true,
],
];
Принимается только абсолютный путь. Относительный зависел бы от текущего каталога процесса: агент из cron искал бы файлы не там, куда их положила страница загрузки. Что-то кроме абсолютного пути — каталог по умолчанию. Каталог обязан быть вне корня сайта — модуль это не проверяет, это решение проекта.
Модуль-импорт, которому нужен свой путь, по-прежнему может переопределить
getImportFolder() и соседей.
Каталоги создаются сами при первом импорте — если пользователь PHP может
писать в родителя. На BitrixVM /home/bitrix принадлежит bitrix, всё
работает из коробки. В другом окружении создайте каталог заранее:
sudo mkdir /var/www/sh_import && sudo chown www-data: /var/www/sh_import
Если в PHP задан open_basedir, каталог импорта должен в него входить.
Внешний обмен (1С, FTP, rsync), который кладёт файлы, пишет теперь сюда, а
не в /upload/import/<код>/: пользователю обмена нужен доступ на запись в
<каталог импорта>/<код>/.
Старый /upload/import модуль не трогает: в нём ваши данные, и он
по-прежнему открыт веб-серверу. Перенесите нужное, перенастройте обмены на
новый каталог и удалите старый:
mkdir -p /home/bitrix/sh_import
cp -a /home/bitrix/www/upload/import/. /home/bitrix/sh_import/
# перенастроить обмены на /home/bitrix/sh_import/<код>/
rm -r /home/bitrix/www/upload/import
ShefInSyncImportFromFileComponent::prepareUploadName(): только имя без
пути, без скрытых файлов и исполняемых расширений (.php, .phtml,
.phar, .htaccess, .html, .svg, .js и прочие, плюс список ядра
HasScriptExtension()), и если импорт объявил getImportFileAccept() с
расширениями — только с ними. До 2.0.0 имя от браузера шло в путь как есть;done_<код>_<дата>_<16 случайных символов>.<расш> — вторая линия на случай, если проект задаст свой каталог
под корнем сайта.Sync\Model\SyncCollection собирает запросы к таблице импорта сам. Значения —
код импорта, дата загрузки — экранируются через SqlHelper::forSql()
(SyncCollection::buildWhere()). До 2.0.0 код импорта вставлялся в запрос как
есть, а в clear() он приходит параметром ajax-запроса компонента статистики:
SQL-инъекция для любого вошедшего. Сторожит tests/synccollection_test.php.
Ядро исполняет строку агента из b_agent как PHP-код.
Agents\Entity::prepareNameForDb() экранирует параметры var_export():
кавычка в значении не ломает агент и не становится кодом. Параметры — только
строки и числа. Сторожит tests/agents_test.php.
Всё, что приходит из данных — строки файла, ответы API, имена агентов из
b_agent, код импорта в гриде, — экранируется перед выводом. Описания
импорта и агента (getProcessDescription(), Entity::getDescription())
выводятся как разметка: их пишет разработчик класса, а не пользователь.
Api\AConnector при ошибке пишет в лог отправленный запрос. Заголовки с
authorization, token, key, secret, password, cookie, session в
имени уходят туда маской (Api\Headers::mask()). Параметры запроса пишутся
как есть — не кладите секреты в параметры, передавайте их заголовком.
Сами логи — модуля shef.problems, вне корня сайта, см. его security.md.
Разбор идёт через XMLReader без LIBXML_NOENT: внешние сущности не
раскрываются (XXE). Сторожит tests/vendor_test.php.
← Опции настроек модуля | ↑ Содержание