CVE-2026-4747 — FreeBSD kgssapi.ko RPCSEC_GSS Tràn bộ đệm ngăn xếp
Tóm tắt
Advisory: FreeBSD-SA-26:08.rpcsec_gss CVE: CVE-2026-4747 Ảnh hưởng: FreeBSD 13.5 (<p11), 14.3 (<p10), 14.4 (<p1), 15.0 (<p5) Thử nghiệm trên: FreeBSD 14.4-RELEASE amd64 (GENERIC kernel, không có KASLR) Bề mặt tấn công: NFS server với kgssapi.ko được tải (cổng 2049/TCP)
1. Lỗ hổng
Nguyên nhân gốc rễ
Lỗ hổng xảy ra trong hàm svc_rpc_gss_validate() ở tệp sys/rpc/rpcsec_gss/svc_rpcsec_gss.c khi hàm này xây dựng một header RPC vào một bộ đệm ngăn xếp 128 byte (rpchdr[]), mà không kiểm tra rằng oa_length vừa với vùng trống này.
static bool_t svc_rpc_gss_validate(struct svc_rpc_gss_client *client, struct rpc_msg *msg, gss_qop_t *qop, rpc_gss_proc_t gcproc)
{
int32_t rpchdr[128 / sizeof(int32_t)]; // 128 bytes on stack
int32_t *buf;
memset(rpchdr, 0, sizeof(rpchdr));
// Write 8 fixed-size RPC header fields (32 bytes total)
buf = rpchdr;
//...
if (oa->oa_length) {
// BUG: No bounds check on oa_length!
memcpy((caddr_t)buf, oa->oa_base, oa->oa_length);
//...
}
}
Cách khắc phục (14.4-RELEASE-p1)
Bản vá thêm một lần kiểm tra kích thước trước khi sao chép:
oa = &msg->rm_call.cb_cred;
if (oa->oa_length > sizeof(rpchdr) - 8 * BYTES_PER_XDR_UNIT) {
rpc_gss_log_debug("auth length %d exceeds maximum", oa->oa_length);
client->cl_state = CLIENT_STALE;
return (FALSE);
}
2. Thiết lập mục tiêu
Yêu cầu
Máy ảo mục tiêu:
- FreeBSD 14.4-RELEASE amd64
- NFS server bật với
kgssapi.ko - MIT Kerberos KDC
Máy chủ tấn công (Linux):
- Python 3 với module
gssapi - MIT Kerberos client
- Truy cập mạng tới NFS port (2049/TCP) và KDC port (88/TCP)
3. Khai thác
Chiến lược tổng quan
Exploitation đạt được thực thi mã kernel từ xa qua cuộc tấn công tràn ngăn xếp nhiều vòng.
Sắp đặt ngăn xếp
Xác định bằng cách gửi một mẫu De Bruijn:
Credential body byte → Stack target
[0..35] → GSS header
[152..159] → saved RBX
[200..207] → RETURN ADDRESS
ROP Gadgets
Tìm thấy qua ROPgadget:
| Gadget | Địa chỉ | Mục đích |
|---|---|---|
pop rdi; ret | K+0x1adcda | Set first argument register |
mov [rdi], rax; ret | 0xffffffff80e3457c | 8-byte arbitrary kernel write |
4. Shellcode
Tổng quan
Shellcode chạy ở chế độ kernel, tạo một process mới thực thi lệnh reverse shell:
Bytes 0–12: mov rax, 0xffffffff8198bf00
Bytes 67–78: mov rax, kthread_exit; call rax
Chức năng Entry và Worker
kproc_create() cho phép chuyển shellcode sang userland, thực thi /bin/sh.
5. Thách thức gặp phải
Độ lệch thanh ghi
Ban đầu sai lệch, xác định qua mẫu De Bruijn.
Không tương thích token GSS MIT ↔ Heimdal
Khắc phục bằng cấu hình chuẩn trong /etc/krb5.conf.
6. Tóm tắt khai thác
Khai thác yêu cầu 15 round, mỗi round thực hiện tràn bộ đệm ngăn xếp để tiến tới shellcode hoàn chỉnh.
Attacker (host) → FreeBSD Target (port 2049)
───────────────────────────────────────
Reverse shell (nc) ←───────────────────