
Пассивный сканер Linux-хостов, который классифицирует подверженность уязвимости CVE-2026-31431 по версии ядра, журналу изменений дистрибутива, статусу модуля и доступности AF_ALG, с выводом в JSON для интеграции с SIEM.
Авторы/Участники: Patrick Doyle (Автор/Сопровождающий), Effie Renard (Соавтор), Kimberly-Lee Banks (Соавтор), Chris F. (Поддержка/Ревью кода)
Раскрытие ИИ: Claude Code использовался для написания тестовых файлов, тестовых данных и проверки безопасности кода. Все правки были вручную проверены одним из участников.
Один статически слинкованный Go-бинарник, который классифицирует подверженность Linux-хоста уязвимости CVE-2026-31431.
Инструмент является пассивным. Он не эксплуатирует ошибку. Механизм-проба (см. заявление о безопасности ниже) выполняет ровно два системных вызова и никогда не затрагивает уязвимый путь выполнения кода.
| Сигнал | Источник | Флаг |
|---|
| Версия ядра против исправления в апстриме | uname(2) | --kernel-version |
| Упоминание CVE в журнале изменений дистрибутива | apt/rpm/apk или файл changelog.Debian.gz на диске | --changelog |
Статус модуля algif_aead | /proc/modules, modprobe.d, /lib/modules | --module |
| Доступность уязвимой поверхности | socket(AF_ALG) + bind(authencesn(...)) | --mechanism |
| Вкомпилирован в vmlinux | /boot/config-$(uname -r) или /proc/config.gz | (часть --module) |
Если флаги проверок не указаны, выполняются все четыре.
| Режим | Триггер | Сценарий использования |
|---|---|---|
| Стилизованный (по умолчанию) | TTY stdout, без --format, без переменной окружения NO_COLOR | Интерактивные сессии в оболочке |
| Обычный текст | stdout не TTY, ИЛИ --format=text, ИЛИ NO_COLOR=1, ИЛИ --no-color | Скрипты оболочки, конвейеры |
| JSON | --format=json | Syslog/SIEM, скрипты оболочки |
| Тихий | --quiet | Только код выхода (автоматизация/скрипты) |
Принудительный стилизованный вывод при конвейере: cvecheck --pretty | tee report.txt.
Принудительный обычный текст в TTY: cvecheck --no-color или NO_COLOR=1 cvecheck.
Проба выполняет ровно два системных вызова: socket(AF_ALG, SOCK_SEQPACKET, 0) и bind(fd, &SockaddrALG{Type:"aead", Name:"authencesn(hmac(sha256), cbc(aes))"}). Затем следует close(fd). Она не выполняет setsockopt для ключа, не выполняет accept, не выполняет sendmsg, не выполняет splice и не создаёт конвейеры. Уязвимый путь выполнения кода требует sendmsg криптографических данных в сочетании с splice из файлового дескриптора, поддерживаемого page-cache; ни одна из этих операций не выполняется, поэтому ошибка не может сработать.
Успешная проба означает, что поверхность доступна. Содержит ли ядро ошибку, определяется сигналами версии ядра и журнала изменений.
Побочный эффект: успешный bind автоматически загружает algif_aead через автозагрузчик модулей ядра. Проверка модуля выполняется до механизм-пробы, поэтому отчёт о состоянии загрузки формируется до пробы. Чтобы полностью подавить автозагрузку, сначала добавьте algif_aead в чёрный список.
| Код | Значение |
|---|---|
0 | PATCHED / NOT_VULNERABLE / MITIGATED / LIKELY_NOT_EXPLOITABLE |
2 | VULNERABLE или MECHANISM_REACHABLE (частичное сканирование, версия ядра не проверялась) |
3 | INCONCLUSIVE (недостаточно сигналов) |
| Дистрибутив | Определение | Пакет ядра | Примечания |
|---|---|---|---|
| Ubuntu / Debian / Mint / Pop!_OS | apt | linux-image-$(uname -r) | Чтение журнала изменений с диска в первую очередь позволяет избежать хрупкости сети apt changelog для подписанных ядер |
| RHEL / CentOS / Rocky / Alma / Fedora / Amazon Linux | rpm | kernel | Поставляется со встроенным algif_aead (CONFIG_..._AEAD=y); митигация через чёрный список неэффективна |
| Oracle Linux | rpm | kernel или kernel-uek | UEK определяется по подстроке uek в uname -r |
| openSUSE / SLES | rpm | kernel-default | |
| Alpine | apk | linux-lts / linux-virt / и т.д. | Вариант выбирается по суффиксу релиза |
| Arch / CachyOS / Manjaro / Endeavour / Gentoo | нет | н/д | Rolling/source: полагается на проверку версии ядра |
Автоматически определяет вашу архитектуру, загружает нужный бинарник в $(pwd) и проверяет его SHA-256 по опубликованному SHA256SUMS:
curl -fsSL https://copyfail.pcdoyle.dev/install.sh | sh
Скрипт завершается с ненулевым кодом при несовпадении контрольной суммы и удаляет повреждённый файл.
Выберите бинарник для архитектуры вашего хоста:
| Архитектура | Бинарник |
|---|---|
Intel/AMD 64-bit (x86_64) | cvecheck-linux-x86_64 |
ARM 64-bit (aarch64) | cvecheck-linux-arm64 |
Intel/AMD 32-bit (i?86) | cvecheck-linux-x86 |
Проверьте перед запуском:
curl -LO https://github.com/pcdoyle/copy-fail-cve-2026-31431/releases/latest/download/cvecheck-linux-x86_64
curl -LO https://github.com/pcdoyle/copy-fail-cve-2026-31431/releases/latest/download/SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS
chmod +x cvecheck-linux-x86_64
make build # bin/cvecheck-linux-{x86_64,arm64,x86}
# SCP(SFTP) на сервер:
scp ./bin/cvecheck-linux-x86_64 host:/tmp/ # Менее 4 МБ, статический, без зависимости от glibc
# SSH:
ssh <host>
# Запуск бинарника:
/tmp/cvecheck-linux-x86_64 # Удобный для человека стилизованный вывод.
/tmp/cvecheck-linux-x86_64 --format=json # Удобный для скриптов, Syslog и SIEM
/tmp/cvecheck-linux-x86_64 --format=text # Удобный для скриптов и конвейеров
ssh <host> /tmp/cvecheck-linux-x86_64 # При прямом запуске по умолчанию --format=text
ssh <host> /tmp/cvecheck-linux-x86_64 --format=json # Удобный для Syslog/SIEM
Смонтируйте корень хоста в доступное для чтения место и передайте --root:
docker run --rm -v /:/host:ro alpine /tmp/cvecheck --root /<host-path>
--root управляет всеми поисками на диске (/etc/os-release, modprobe.d, /lib/modules, /boot/config-*, файлы журналов изменений). Проверки версии ядра и механизм-проба по-прежнему обращаются к работающему ядру через uname(2) и socket(AF_ALG, ...).
Разрешается в следующем порядке (первое совпадение выигрывает):
PATCHED: Журнал изменений дистрибутива ссылается на ID CVE.NOT_VULNERABLE: Работающее ядро >= исправленной версии в апстриме.MITIGATED: algif_aead в чёрном списке и не загружен и не вкомпилирован в vmlinux.LIKELY_NOT_EXPLOITABLE: AF_ALG недоступен и модуль отсутствует на диске.MECHANISM_REACHABLE: Поверхность доступна, но версия ядра не проверялась.VULNERABLE: Ядро в уязвимом диапазоне и механизм доступен.INCONCLUSIVE: Ни одно из вышеперечисленных не совпало.Если --mechanism запускается вместе с --kernel-version и оба сигнализируют о проблеме, результатом будет VULNERABLE с подсказкой по устранению.
algif_aead в чёрный список до обновления ядра.
echo 'blacklist algif_aead' | sudo tee /etc/modprobe.d/cve-2026-31431.conf
sudo rmmod algif_aead 2>/dev/null
CONFIG_CRYPTO_USER_API_AEAD=y помещает символ внутрь vmlinux. Только обновление ядра (или live-патч в стиле kpatch) устраняет подверженность. Инструмент это определяет.| Симптом | Причина | Исправление |
|---|---|---|
changelog: error="apt: exit status 100 ... Changelog unavailable for linux-signed-amd64" | Подписанное ядро Debian/Ubuntu; зеркало apt не предоставляет журнал изменений исходного пакета | Ошибка появляется только когда файл на диске отсутствует в дополнение к недоступности зеркала; установите apt-doc или дождитесь зеркала. |
module: ... config_src="" | Нет читаемой конфигурации ядра (нет /boot/config-*, нет /proc/config.gz, /boot доступен только root) | Запустите от root или примите, что BuiltIn не может быть определён. Вердикт всё равно может быть вынесен по другим сигналам. |
mechanism: error="EAFNOSUPPORT" | Ядро собрано без CONFIG_CRYPTO_USER_API, поэтому хост не уязвим через AF_ALG | Вердикт будет LIKELY_NOT_EXPLOITABLE. |