
QEMU 11.1.2 — высокий уровень — локальная/удалённая — OOB — переполнение кучи в short IPv4 L4 в COLO filter-rewriter
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · qemu-colo-l4-oob
QEMU v11.1.2 (4fc49f46dc95d4a27de2509e7fceb2931e91faeb) — фильтр-переписыватель COLO
Класс: OOB (переполнение кучи при ЧТЕНИИ/ЗАПИСИ). Доступ: локальный (гость) / удалённый (пир COLO).
parse_packet_early принимает IPv4, как только L2 плюс ip_hl*4 помещаются в буфер. Минимальный заголовок L4 никогда не требуется. Затем fill_connection_key читает четыре байта по адресу transport_header без проверки оставшейся длины. filter-rewriter копирует кадр через g_malloc0(size), и после того как SYN перевёл соединение в состояние TCPS_SYN_RECEIVED, ACK с conn->offset != 0 записывает th_ack / th_seq за пределами этого блока, если захваченная длина заканчивается на заголовке транспортного уровня.
COLO не включён по умолчанию. Он активен, когда настроен -object filter-rewriter (и colo-compare). TX/RX гостя на этом переписывателе входит в модель безопасности виртуализации. Пир COLO на primary_in / secondary_in — это сетевой протокол, также недоверенный.
34-байтного кадра IPv4/TCP достаточно для ASan heap-buffer-overflow READ в filter-rewriter.
| ID | CVE пока нет |
| CWE | CWE-125 / CWE-787 |
| CVSS | Высокий: 8.2 CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H |
| Продукт | QEMU |
| Затронуто | v11.1.2 (4fc49f46), переписыватель/сравнение COLO включены |
| Аутентификация | гость на netdev переписывателя COLO или пир сравнения COLO |
| Лицензия | GNU Affero GPL v3.0 |
| Лаборатория | сокеты loopback 127.0.0.1:18770 / 18771 |
Кто: недоверенный гость на сетевом интерфейсе с включённым COLO или враждебный пир сравнения COLO. От гостя к хосту / от пира к хосту. Куча в пространстве пользователя QEMU.
| Метод | Точка срабатывания | Привилегия |
|---|---|---|
| Короткий IPv4/TCP ACK после SYN с полным заголовком (34-байтный кадр, длина заканчивается на заголовке транспортного уровня) | filter-rewriter handle_primary_tcp_pkt / fill_connection_key | ASan heap-buffer-overflow READ в filter-rewriter. Управляемый TCP с полным заголовком оставляет QEMU живым. |
| Тот же отсутствующий минимум L4 | parse_packet_early net/colo.c:43-98 | Пакет классифицируется как TCP без заголовка L4 в буфере. |
После SYN, при conn->offset != 0, переписыватель сохраняет th_ack / th_seq в net/filter-rewriter.c:112-114 и :216-218. Опции IP (ip_hl > 5) смещают эту запись на следующий блок кучи. ЗАПИСЬ в кучу хоста, инициируемая гостем.
colo-compare fill_pkt_tcp_info задаёт header_size из th_off<<2 без проверки относительно pkt->size. payload_size уходит в отрицательное значение. colo_compare_packet_payload выполняет memcmp на десятки килобайт за пределами обоих выделенных пакетов. Падение плюс ЧТЕНИЕ кучи хоста.
Аварийное завершение QEMU под ASan при ЧТЕНИИ в переписывателе. Без ASan это живой OOB кучи в процессе гипервизора.
net_fill_rstate отклоняет packet_len > NET_BUFSIZE).Лаборатория не демонстрирует контроль RIP или получение оболочки на хосте из гостя. Класс — OOB кучи процесса QEMU на netdev с включённым COLO.
Я читал net/colo.c в поисках минимальной длины, включающей L4. Минимальная длина — Ethernet плюс VLAN плюс vnet_hdr. ip_hl берётся из короткого хвоста. Затем fill_connection_key доверяет transport_header. filter-rewriter всегда загружает th_flags по смещению 13 в struct tcp_hdr.
Неверные пути: трактовка длины TAP как границы COLO (другой путь); отправка переполнения как первого пакета (rewriter нужен SYN первым, чтобы conn->offset был активен); underflow th_off в colo-compare как основное свидетельство (сначала сработало READ в rewriter).
cd lab
./run.sh
Цель — только loopback-сокеты 127.0.0.1:18770 (filter-rewriter netdev) и 18771 (colo-compare). Pin клонируется из github.com/qemu/QEMU тега v11.1.2 / 4fc49f46. ASan. COLO proxy включён на этапе configure. Только witness.
SUCCESS qemu-colo-l4-oob asan=heap-buffer-overflow access=READ sink=filter-rewriter control=alive QEMU-COLO-L4-OOB-WITNESS
Воспроизведение: python3 qemu-colo-l4-oob-Abraxas-Labs.py.
parse_packet_early должен требовать полный заголовок L4 (TCP 20, UDP 8, SCTP 12, AH 8) после IP-заголовка и отклонять пакет, когда size заканчивается на transport_header или раньше. fill_connection_key и записи th_* в rewriter должны проверять оставшуюся длину. colo-compare должен отклонять th_off<<2, который не помещается в pkt->size, до вычисления payload_size.
4fc49f46dc95d4a27de2509e7fceb2931e91faebparse_packet_early · filter-rewriterGNU Affero GPL v3.0. См. LICENSE. Только для лабораторной среды с loopback. Без гарантий.