flawopen.com/Teardowns/cve-2024-33066-qualcomm-wlan-log-redirection
CVE-2024-33066: уязвимость перенаправления WLAN-логов
CVE-2024-33066 повреждает память, если WLAN Resource Manager Qualcomm перенаправляет журнал по выбранному пути. Исправлена в октябре 2024 года.
Представьте стойку регистрации в отеле, куда любой может позвонить и сказать: «Отныне отправляйте копии книги гостей вот по этому адресу». Администратор переписывает продиктованное на маленькую карточку, даже если текст вылезает за её край прямо на стойку, а затем отправляет копии туда, куда написано, в том числе в сейф управляющего. Исправление — принимать только короткую метку, обозначающую ящик в архиве.
Ключевые понятия и термины
WLAN Resource Manager- Компонент Wi-Fi, названный в бюллетене Qualcomm о
CVE-2024-33066. Он работает на сетевых платформах Qualcomm, которые используются в маршрутизаторах, mesh-системах и точках доступа. Чипсеты IPQ / QCN- Семейства сетевых Wi-Fi-систем на кристалле от Qualcomm. В список затронутых входят IPQ5332, IPQ8074A, IPQ9574, QCN9000 и платформы Immersive Home, а не чипы для телефонов.
CWE-20- Некорректная проверка входных данных: программа доверяет вводу, не проверяя, обладает ли он свойствами, на которые опирается код, например максимальной длиной или допустимым каталогом.
Открытие относительно каталога- Открытие файла через
openat()относительно дескриптора каталога и по простому имени без '/', чтобы результат не мог оказаться за пределами этого каталога. Вектор CVSS 3.1- AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H: доступна по сети, низкая сложность, не нужны привилегии и действия пользователя, высокое влияние на все три свойства (оценка 9.8).
Связи со стандартами
- Ссылка CWE для слабого места, описанного в этом руководстве: CWE-20
Анализ первопричины
В бюллетене Qualcomm сказано лишь, что в WLAN Resource Manager происходило повреждение памяти "while redirecting log file to any file location with any file name" (CWE-20). Место назначения из запроса на перенаправление журнала использовалось без проверки его длины и того, куда оно указывает. Код ниже моделирует этот пробел в проверке ввода; он иллюстративный и не является исходным кодом Qualcomm.
Пошаговый сценарий атаки
1. Приходит запрос на перенаправление журнала
WLAN Resource Manager принимает запрос отправлять вывод журнала в другое место. Вектор CVSS (AV:N/PR:N/UI:N) оценивает уязвимость как доступную по сети без привилегий и без участия пользователя.
2. Принимается любое место и любое имя
Согласно описанию Qualcomm, перенаправление работало в любое место и с любым именем файла: запрошенное место назначения не проверялось ни по длине, ни по тому, куда оно указывает.
3. Непроверенный ввод повреждает память
В модели ниже имя длиннее фиксированного буфера пути переполняет его (strcpy), а для записи можно открыть любой путь, включая файлы конфигурации. Qualcomm не сообщила, какой из этих случаев был в её коде.
4. Последствия и статус
CVSS 3.1 оценивает влияние на конфиденциальность, целостность и доступность как высокое (9.8). Qualcomm передала исправление производителям в бюллетене за октябрь 2024 года; по оценке CISA, известных случаев эксплуатации нет.
Исходный код: Уязвимый vs Защищённый вариант
Иллюстративная модель класса уязвимостей, а не код Qualcomm. Защищённый обработчик ограничивает ввод через strnlen до его использования, принимает только короткое имя из фиксированного набора символов (без '/' и без ведущей '.') и открывает его через openat() относительно каталога журналов, выбранного при запуске, с флагом O_NOFOLLOW, чтобы подложенная символическая ссылка не перенаправила запись. Вызывающая сторона может выбрать имя файла, но не его место, а слишком длинный ввод отклоняется, а не копируется.
#include <fcntl.h>
#include <string.h>
#define LOG_PATH_MAX 64
struct rm_log_cfg {
char path[LOG_PATH_MAX];
int fd;
};
/* Обрабатывает запрос на перенаправление журнала; `requested` берётся из тела запроса. */
int rm_set_log_destination(struct rm_log_cfg *cfg, const char *requested)
{
strcpy(cfg->path, requested); /* нет проверки длины: длинный ввод выходит за границы path[] */
cfg->fd = open(cfg->path, O_WRONLY | O_CREAT | O_APPEND, 0644); /* любое расположение */
return cfg->fd < 0 ? -1 : 0;
}
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#define LOG_NAME_MAX 32
struct rm_log_cfg {
int dir_fd; /* фиксированный каталог журналов, открываемый один раз при запуске */
char name[LOG_NAME_MAX];
int fd;
};
static int valid_log_name(const char *name, size_t len)
{
if (len == 0 || len >= LOG_NAME_MAX || name[0] == '.')
return 0;
for (size_t i = 0; i < len; i++) {
char c = name[i];
int ok = (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
c == '-' || c == '_' || c == '.';
if (!ok)
return 0; /* отклоняет '/', поэтому имя не может выйти за пределы dir_fd */
}
return 1;
}
int rm_set_log_destination(struct rm_log_cfg *cfg, const char *requested)
{
size_t len = strnlen(requested, LOG_NAME_MAX);
if (!valid_log_name(requested, len))
return -EINVAL;
int fd = openat(cfg->dir_fd, requested,
O_WRONLY | O_CREAT | O_APPEND | O_NOFOLLOW | O_CLOEXEC, 0600);
if (fd < 0)
return -errno;
memcpy(cfg->name, requested, len + 1);
if (cfg->fd >= 0)
close(cfg->fd);
cfg->fd = fd;
return 0;
}
Чек-лист по защите системы для инженеров
- ✓В CI вызывайте rm_set_log_destination с именем из 64 символов, '../etc/passwd', '/tmp/x', '.hidden' и именем, содержащим '/', и проверяйте, что каждый вызов возвращает -EINVAL и не создаёт файл.
- ✓Проваливайте CI при новых вызовах strcpy или sprintf, записывающих поля запроса в буферы фиксированного размера (например, правилом semgrep или clang-tidy); требуйте явной границы, как у strnlen или snprintf.
- ✓Разрешайте каждый выходной файл, который может выбрать вызывающая сторона, через
openat()относительно дескриптора каталога, открытого при запуске, и передавайте O_NOFOLLOW, чтобы никакое имя не вышло за пределы этого каталога. - ✓Составьте перечень маршрутизаторов и точек доступа на чипсетах IPQ/QCN, убедитесь, что их прошивка содержит исправление Qualcomm за октябрь 2024 года, и держите интерфейсы управления и диагностики в административной сети.