
Правила обнаружения, YARA-сигнатуры, правила auditd/Wazuh и шаблоны событий MISP для уязвимости локального повышения привилегий ядра Linux CVE-2026-31431 (Copy Fail). Включает индикаторы компрометации, шаги по смягчению и анализ эксплойта.
Опубликовано: 2026-04-30
CVSSv3: 7.8 (High)
Тип: Локальное повышение привилегий (LPE)
Подсистема: Криптографический шаблон algif_aead / authencesn в ядре Linux
Затрагивает: Ядра Linux 4.14 – 6.18.21 (практически все дистрибутивы с 2017 года)
Ссылки:
CVE-2026-31431 — это логическая ошибка, появившаяся в ядре 4.14 (2017) на стыке трёх независимых изменений:
authencesn (добавлен в 2011 году для поддержки ESN в IPsec) записывает 4 байта временных данных за границу своего выходного буфера.AF_ALG получил поддержку AEAD в 2015 году, что позволило пользовательскому пространству передавать данные через splice() из странично-кешированных файлов.algif_aead.c был оптимизирован для работы «на месте» (req->src == req->dst), помещая живые страницы кэша страниц в доступный для записи scatterlist.Результат: непривилегированный пользователь может записать ровно 4 контролируемых байта в копию кэша страниц ядра любого читаемого файла — включая setuid-бинарники и /etc/passwd — не затрагивая файл на диске. Рабочий PoC — это скрипт Python размером 732 байта. Никакого состояния гонки. Никаких привязок к дистрибутиву. Надёжно работает на Ubuntu, RHEL, Amazon Linux и SUSE.
Attacker opens AF_ALG socket (family 38, type 5) └─ Binds to "authencesn(hmac(sha256),cbc(aes))" └─ Sets SOL_ALG (279) options including key and authsize └─ Accepts a connection socket
Attacker opens target file (e.g., /etc/passwd) read-only └─ Uses splice() to feed page-cache pages into the AEAD socket's RX buffer └─ Sends crafted AAD via sendmsg() — bytes 4–7 of AAD = attacker-controlled write value
authencesn performs in-place decryption: └─ scatterwalk_map_and_copy writes seqno_lo into the chained page-cache page └─ recvmsg() returns an error (HMAC fails — expected), but the write already happened
Page-cache now contains attacker-modified copy of the file └─ Kernel executes from page-cache, not disk └─ On-disk file is UNCHANGED — file integrity tools see nothing
PoC нацелен на `/etc/passwd`: он находит смещение поля UID текущего пользователя и перезаписывает его на `0000`, затем вызывает `su` для получения root-оболочки.
---
## Ограничения обнаружения
> **Прочитайте этот раздел перед развертыванием любых правил ниже.**
Эта эксплойт имеет два свойства, которые значительно ограничивают возможности обнаружения:
**1. Запись идет в кэш страниц, а не в файловую систему.**
Любой инструмент обнаружения, который отслеживает события файловой системы — `inotify`, `fanotify`, AIDE, Tripwire, auditd path watches — **не** заметит изменения. Файл на диске никогда не записывается. Это означает, что флаги `-p w` (write) в auditd path watches для `/usr/bin/su` или `/etc/passwd` не перехватят фактическую запись эксплойта.
**2. Механизм использует легитимные интерфейсы ядра.**
Сокеты `AF_ALG`, `splice()` и `authencesn` имеют легитимное применение (IPsec, самотестирование ядра, ввод-вывод в стиле sendfile). Обнаружение должно сосредотачиваться на *комбинации* этих примитивов, а не на каждом по отдельности, и следует ожидать ложных срабатываний в системах, работающих с IPsec или выполняющих криптотестирование ядра.
**Что обнаружение МОЖЕТ выявить:**
- Системный вызов `socket(AF_ALG, SOCK_SEQPACKET, 0)`
- Системный вызов `splice()`, коррелирующий с вышеуказанным, особенно при доступе к setuid-бинарникам
- Сам скрипт PoC (через YARA)
- Конкретная строка алгоритма `authencesn(hmac(sha256),cbc(aes))` в памяти процесса или файлах скриптов
**Что обнаружение НЕ МОЖЕТ выявить:**
- Фактическая запись в page-cache (в памяти, без событий файловой системы)
- Использование измененной записи page-cache после эксплуатации (выглядит как обычный вызов `su` или `passwd`)
- Варианты, избегающие Python или конкретную строку алгоритма
---
## Немедленное смягчение
Перед развертыванием правил обнаружения примените это смягчение на любом незапатченном хосте:```bash
# Disable algif_aead kernel module — blocks the exploit primitive entirely
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif-aead.conf
sudo rmmod algif_aead 2>/dev/null || true
Проверьте, что смягчение активно используя официальный детектор:```bash
python3 test_cve_2026_31431.py
> **Примечание:** Команда `rmmod` завершится ошибкой, если модуль в данный момент не загружен; это допустимо. Конфигурация `modprobe.d` предотвращает будущие загрузки. Данная мера смягчения не влияет на стандартные рабочие нагрузки TLS, SSH или шифрования файловой системы — она затрагивает только IPsec с расширенными порядковыми номерами с использованием шаблона `authencesn`, что редко встречается за пределами выделенных VPN-шлюзов.
---
## Правило YARA
Сохраните как `cve_2026_31431.yar`
> **Область сканирования:** Это правило предназначено для сканирования файлов скриптов Python на диске или извлеченных из дампов памяти. Оно будет соответствовать известному PoC и близким вариантам. Оно НЕ будет обнаруживать активность эксплойта на уровне системных вызовов — используйте для этого правила auditd/Wazuh.```yara
rule CVE_2026_31431_CopyFail_PoC_HighConfidence {
meta:
description = "High-confidence match: CVE-2026-31431 Copy Fail PoC or close variant"
author = "Detection Engineering"
reference = "https://xint.io/blog/copy-fail-linux-distributions"
cve = "CVE-2026-31431"
date = "2026-04-30"
severity = "High"
cvss = "7.8"
strings:
// Algorithm string unique to this exploit path — very high fidelity
$alg_full = "authencesn(hmac(sha256),cbc(aes))" ascii
// Specific socket call signature from PoC: AF_ALG=38, SOCK_SEQPACKET=5
$socket_call = "socket(38,5,0)" ascii
// SOL_ALG socket option (decimal 279)
$solalg = "setsockopt(279" ascii
// Hex key/iv payload written via setsockopt in PoC
$key_payload = "0800010000000010" ascii
// splice() usage in context of AEAD operations
$splice = "splice(" ascii
// Target indicators from PoC (page-cache corruption targets)
$target_passwd = "/etc/passwd" ascii
$target_su = "/usr/bin/su" ascii
// AF_ALG aead bind strings
$aead_bind = "\"aead\"" ascii
condition:
// High-confidence: unique algorithm string alone is sufficient
$alg_full
or
// Medium-confidence: socket primitive + option number
($socket_call and $solalg)
or
// Medium-confidence: splice into AEAD socket targeting a setuid path
($aead_bind and $splice and ($target_passwd or $target_su))
or
// PoC hex payload present alongside splice
($key_payload and $splice)
}