flawopen.com/Teardowns/cve-2022-31150-undici-crlf-injection
CVE-2022-31150: CRLF-инъекция в Undici
CVE-2022-31150 позволяла недоверенным CR/LF попасть в сериализацию запросов Undici. Здесь описаны исправление и обновление.
HTTP-запрос похож на бланк с фиксированными границами строк: в каждой строке одно поле. Если без проверки скопировать текст, скрытый перевод строки может превратить остаток в новое поле. Исправление Undici проверяет значения заголовков, метод и путь до записи.
Ключевые понятия и термины
Undici- Библиотека HTTP/1.1 для Node.js; Node.js также включает версию Undici для встроенного fetch.
CRLF-инъекция- Недоверенные байты возврата каретки и перевода строки попадают в поле протокола и могут изменить границы строк.
HTTP-токен- Ограниченный набор символов для элементов протокола, например имен заголовков и методов.
Цель запроса- Путь и параметры HTTP-запроса; управляющие символы не должны менять его структуру.
Связи со стандартами
- Ссылка CWE для слабого места, описанного в этом руководстве: CWE-93
Анализ первопричины
До исправления Undici мог сериализовать значения заголовков с недоверенными данными и недопустимыми управляющими символами. CR/LF разделяют строки; их прием может внедрить или повредить строки заголовков. Патч проверяет имена как HTTP-токены, отклоняет недопустимые символы в значениях, проверяет токен метода и запрещает управляющие символы в пути. GitHub Advisory указывает версии пакета ниже 5.8.0, а описание NVD — ниже 5.7.1. Оба источника называют 5.8.0 исправленной версией. Это инъекция в запрос HTTP-клиента; SSRF или утечка учетных данных не являются автоматическим следствием и зависят от приложения и сетевого пути.
Пошаговый сценарий атаки
1. Недоверенное значение
Данные приложения попадают в заголовок, метод или путь Undici.
2. Нет проверки
В уязвимых версиях недопустимые управляющие символы могли попасть в сборку запроса.
3. Граница протокола
HTTP-сериализация использует границы строк; прием символов может внедрить или повредить поля.
4. Исправление и ограничение
Undici 5.8.0 проверяет байты заголовков, токены метода и символы пути до сериализации; последствия зависят от контекста.
Исходный код: Уязвимый vs Защищённый вариант
// Важный участок сериализации в lib/core/request.js до a29a151
function serializeRequest(request, method, path, headers) {
request.method = method;
request.path = path;
for (const [key, value] of Object.entries(headers)) {
// Перед сериализацией символы протокола не проверяются.
request.headers += `${key}: ${value}\r\n`;
}
}
// Усиленный шаблон проверки из upstream-парсера запросов
const token = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
const invalidFieldValue = /[^\t\x20-\x7e\x80-\xff]/;
const invalidPath = /[^\u0021-\u00ff]/;
function validateRequestTarget(method, path) {
if (!token.test(method)) throw new InvalidArgumentError('invalid request method');
if (invalidPath.test(path)) throw new InvalidArgumentError('invalid request path');
}
function processHeader(request, key, value) {
if (!token.test(key)) throw new InvalidArgumentError('invalid header key');
if (invalidFieldValue.test(value)) throw new InvalidArgumentError(`invalid ${key} header`);
request.headers += `${key}: ${value}\r\n`;
}
Чек-лист по защите системы для инженеров
- ✓Обновите npm-зависимость undici до версии 5.8.0 или новее; для встроенного fetch проверьте версию Undici в поддерживаемом Node.js и установите обновление Node.js.
- ✓Отклоняйте недопустимые управляющие символы в недоверенных значениях заголовков; не удаляйте их незаметно, продолжая обработку неоднозначного ввода.
- ✓Используйте структурированные API запросов Undici, а не собирайте необработанный текст HTTP.
- ✓Добавьте тесты имен и значений заголовков, методов и путей с управляющими символами; проверяйте отказ до отправки запроса.
- ✓Если приложение принимает адреса назначения от пользователя, отдельно задайте список разрешенных направлений и сетевую политику исходящего трафика; это дополнительная защита, а не исправление CVE.
- ✓Проверьте lockfile и транзитивные зависимости на оставшиеся уязвимые копии Undici.