
Исследование патч-диффов для опубликованных проблем urllib3: закреплённые релизы, оригинальные офлайн-стенды, поведение до/после и безопасные контрольные примеры.
Создано и поддерживается Серхио Родригесом (SSH-PuR66). Стенды для экспериментов и анализ выполнены мной; опубликованные уязвимости, код urllib3 и исправления в upstream сохраняют исходную атрибуцию.
Метод исследования автора · Стенд для редиректов · Исследование фрейминга чанков
Редирект меняет пункт назначения, при этом три чувствительных заголовка остаются прикреплёнными. Парсер фрейминга принимает входные данные, которые отклоняет следующий релиз. Afterimage превращает опубликованные исправления протоколов в небольшие, поддающиеся проверке эксперименты «до/после».
Я построил стенды и контрольные случаи вокруг закреплённых, немодифицированных релизов urllib3. Каждый результат фиксирует хеш пакета, зафиксированное поведение, границу фикстуры и атрибуцию upstream.
| Исследование | Сравниваемые релизы | Записанный корпус | Проверить |
|---|---|---|---|
| Граница заголовков при редиректе · CVE-2026-44431 | urllib3 2.6.3 / 2.7.0 | 12 случаев, включая затронутое поведение и безопасные контроли | Результаты · Стенд |
| Фрейминг чанков · CVE-2026-97689 | urllib3 2.7.0 / 2.8.0 | 32 ограниченных офлайн-случая | Метод и результаты |
Тип исследования: независимое воспроизведение опубликованных проблем. Измеряемая граница: обработка аргументов библиотекой и поведение фрейминга в памяти. Эксплуатируемость на уровне приложения и исчерпание ресурсов остаются за пределами этих результатов фикстур.
Открыть опубликованное исследование
CVE-2026-44431 · urllib3 2.6.3 → 2.7.0 · воспроизведено 27 сентября 2026
Запрос несёт три чувствительных заголовка к одному источнику. Редирект меняет пункт назначения. Несёт ли их следующий запрос?
Этот независимый регрессионный тест запускает реальную реализацию редиректа из двух точных релизов urllib3. Версия 2.6.3 сохраняет все три заголовка через затронутый низкоуровневый API. Версия 2.7.0 удаляет их. Безопасный заголовок сохраняется, а обычные запросы по-прежнему работают.
| Фикстура | urllib3 2.6.3 | urllib3 2.7.0 |
|---|---|---|
| Низкоуровневый кросс-доменный редирект | 3 чувствительных заголовка сохранены | 0 сохранено |
| Тот же случай с именами в нижнем регистре | 3 сохранено | 0 сохранено |
| Контроль высокоуровневого API | 0 сохранено | 0 сохранено |
| Прямой ответ 200 | 3 сохранено, как и задумано | 3 сохранено, как и задумано |
| Редирект явно отключён | Один вызов; возвращён 302 | Один вызов; возвращён 302 |
| Пользовательский набор удаления добавляет безопасный маркер | Все 4 заголовка сохранены | Все 4 удалены |
12/12 ожиданий сценариев пройдено. Каждый сценарий также проверяет статус ответа, количество транспортных вызовов, исходный набор заголовков, результат для безопасного заголовка и то, что заголовки вызывающей стороны не были изменены. Уязвимый исход — это ожидаемый базовый результат, а не пройденная проверка безопасности.
Машиночитаемые результаты включают зафиксированные аргументы, точные хеши wheel-файлов, среду выполнения, хеши исходников тестов, атрибуцию и время воспроизведения.
Уведомление upstream, опубликованное 7 мая 2026, выявляет проблему раскрытия информации в проксируемом низкоуровневом пути редиректа urllib3. В нём указаны затронутые версии >=1.23, <2.7.0. Вызов ProxyManager.connection_from_url(...).urlopen(..., assert_same_host=False) мог переносить настроенные чувствительные заголовки в перенаправленный запрос к другому источнику. Высокоуровневый API менеджера уже удалял их.
Исправление upstream применяет Retry.remove_headers_on_redirect перед рекурсивным низкоуровневым запросом. Наш случай с заголовками в нижнем регистре следует вниманию регрессионного теста upstream к регистру имён заголовков. Случай с пользовательским удалением проверяет, что правило соблюдает настроенный набор, а не только три имени по умолчанию.
В рекомендации christos-cantina-security указан как сообщивший, illia-v — как координатор, а sethmlarson — как проверяющий исправление. Вклад Sergio Rodriguez здесь — независимый офлайн-стенд и анализ до/после. Это воспроизведение опубликованного ими CVE.
Используйте Python 3.10 или новее. Установка через pip или виртуальное окружение не требуется: каждая версия импортируется напрямую из своего pure-Python wheel в отдельном изолированном подпроцессе.
Из корня репозитория портфолио:
python -B ./labs/cve-replay/run_replay.py --fetch
python -B ./labs/cve-replay/run_replay.py
Первая команда загружает два точных wheel-файла в игнорируемый каталог .cache/wheels/ лаборатории и проверяет их хэши SHA-256 по манифесту. Вторая команда использует этот кэш без загрузки. Для автономной копии исходников запустите python -B run_replay.py --fetch, затем ту же команду без --fetch. --cache принимает другой локальный каталог кэша.
HTTPConnectionPool._make_request заменяется на транспорт с двумя ответами: 302 с фиксированным location, затем 200. Фикстура фиксирует аргументы, достигающие этой границы. Разбор urllib3, политика повторов, фильтрация заголовков и рекурсивная обработка редиректов выполняются без изменений из выбранного wheel-файла.
Все адреса назначения — фиксированные зарезервированные имена .invalid; все значения заголовков начинаются с DUMMY. Создание сокетов и функции DNS немедленно вызывают исключение. Проверка поддержки IPv6 при импорте библиотеки блокируется и фиксируется отдельно; сценарии воспроизведения не пытаются выполнять сетевые операции. Нет ни слушающего сервера, ни реальной цели.
Это проверяет обработку аргументов при редиректах. Это не измеряет сквозной прокси-трафик. Версия 2.7.0 — первое исправление для этой конкретной CVE; это историческое сравнение не является рекомендацией выбрать её вместо более новых поддерживаемых релизов.
Скрипты фикстур и анализ — оригинальная работа в рамках портфолио. urllib3 — upstream-проект, распространяемый под лицензией MIT; его код и релизные wheel-файлы не распространяются в исходном архиве портфолио. Они загружаются отдельно с PyPI и импортируются без изменений для эксперимента.