http-csrf-protection

Globalнужен перезапуск

Защита веб-монитора от запросов, подделанных чужой страницей
в конфигурации это строкаhttp-csrf-protection trueвнутри блока Global
Почему чужая вкладка не может остановить ваш узел

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

Защита делает две вещи. Во-первых, запрещает менять состояние запросом GET — а именно GET умеет отправить любая картинка или ссылка на чужой странице. Во-вторых, требует, чтобы POST нёс либо ключ API, либо признак сессии, полученный предыдущим запросом к монитору.

Включена по умолчанию (true) и в обычной работе не мешает. Мешает она старым приложениям, которые привыкли менять состояние узла обычной ссылкой.

Ключ защиту не проходит, а заменяет. Запрос с правильным http-api-key принимается без признака сессии — так и задумано: у программы браузера нет, подделать её запрос со стороны нельзя.

Главная ловушка — выключить защиту ради одного старого приложения. Выключается она на весь узел и для всех, включая браузер администратора с открытой вкладкой монитора. Правильный обход — научить приложение ходить с ключом: тогда защиту можно оставить включённой.
Что делает Хаб. Не пишет — оставляет включённой. Хаб ходит на монитор с ключом, значит защита ему не мешает вовсе: браузера у него нет, а ключ и есть разрешённый способ.
Рекомендуемые значения

Выключать почти никогда не нужно:

Значение Когда
true (умолчание) всегда
false старое приложение меняет состояние через GET и переписать его нельзя

Перед выключением стоит попробовать ключ: приложение с ключом работает при включённой защите.

Умолчание true, запрет изменяющих GET и требование ключа либо признака сессии у POST — из руководства (§ 3.3.1.58.4). Объяснение самой атаки и совет пробовать ключ вместо выключения — наши.
Пример в конфигурации
# выключать — только под конкретное приложение и с записанным поводом
http-mgmt-port 1000
http-csrf-protection false   # приложение X меняет состояние через GET
Комментарий с поводом обязателен: строка ослабляет защиту всего узла ради одного клиента, и через год причину никто не вспомнит.
жёлтым — — имена директив, голубым — блоки. Так же они подсвечены и в тексте карточки.
▲

Типичные ошибки и проблемы

что делают не так и чем это кончается2 ошибки▶

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

наш опыт

Чем чреватоЗащита снимается со всего узла и со всех клиентов, включая браузер администратора. Ради одного приложения открывается вся поверхность.
Как заметитьВ конфигурации false, а ключ API при этом объявлен.
Как правильноНаучить приложение слать ключ заголовком и вернуть true.

Считают защиту заменой ограничению по адресу

§ 3.3.1.58.4

Чем чреватоОна защищает от подделанного запроса, а не от прямого. Тот, кто дотянулся до порта и есть в списке доступа, ходит на монитор свободно.
Как заметитьЗащита включена, а список http-access широкий.
Как правильноСужать список адресов; защита от подделки — другой рубеж, не замена этому.
Совместимость
PowerMTA 6.0
описана в руководстве этой версии · платформа: любая
С какой версии директива доступна, вендор указывает не для всех — здесь пометки нет. Имя встречается и в издании руководства 5.0.
Справочные данные
Синтаксис
http-csrf-protection <boolean>
Значения
yes | no | true | false
Умолчание
true § 3.3.1.58.4
Применение
нужен перезапуск сервиса
Очередь
уже поставленное в очередь не затронет
Где писать
Global
Сколько раз
один раз в блоке
Всё здесь — из руководства, с разделом.
Наследование
Наследования нет: строка пишется в корне файла, раздел Global, и действует на весь управляющий интерфейс. Выборочно — для одного адреса или одного приложения — защиту не выключить.
Как проверить на узле
Проверяем тем, что защита и запрещает, — изменяющим запросом GET без ключа, с разрешённого адреса:
curl -s -o /dev/null -w '%{http_code}\n' 'http://NODE:1000/command?command=show+version'
Отказ означает, что защита работает. Успех при отсутствии ключа — что она выключена. Тот же запрос с заголовком X-API-Key должен проходить в обоих случаях.
В Хабе
Цена ошибки
обратимо: вредит, пока стоит
Сценарии
Безопасность узла