漏洞描述
Linux内核RxRPC子系统的rxgk模块里,rxgk_verify_response() 对 auth_len 做了一次方向写反的边界检查,超大RESPONSE认证器被悄悄放行。脏数据随后流入rxgk_decrypt_skb(),这个函数在做AEAD原地解密时根本没检查COW保护,直接把结果写回了只读页缓存页面。
整条链路的核心问题在于解密发生在HMAC校验之前,就算校验失败,页缓存里的数据已经被改写了。攻击者通过精心构造的交错SGL,把目标SUID文件的页缓存替换成192字节ELF shellcode,随后执行该文件即可拿到root shell。
影响版本
启用 CONFIG_RXGK 的内核才会触发。Fedora各版本、Arch Linux、openSUSE Tumbleweed 默认开启,需要先升级再继续用。使用主线内核PPA或ELRepo kernel-ml的系统同样注意。Debian Stable、RHEL 8/9、Ubuntu LTS 默认不启用 RxGK,通常不受影响。
快速自查
zcat /proc/config.gz | grep CONFIG_RXGK
uname -r
输出 CONFIG_RXGK=y 且内核版本早于 6.8.12 就赶紧更新。
漏洞详情
POC的核心思路分三步。第一步,攻击者随机生成密钥K,注册进内核keyring,让rxrpc kworker 能查询到这张"合法"的server secret
snprintf(desc, sizeof(desc), "%u:6:%u:%u", SVC_ID, KVNO, ENCTYPE);
key_serial_t k = key_add("rxrpc_s", desc, SERVER_SECRET, KEY_LEN, kr);
第二步,通过pipe+vmsplice/splice构造交错SGL,让skb的frag 页面在匿名页和目标文件页之间交替排列
vmsplice(pfd[1], &user_buf, 1, 0); /* 匿名页 → skb frag */
splice(tfd, &off, pfd[1], NULL, 16, 0); /* 文件页 → skb frag */
splice(pfd[0], NULL, udp, NULL, total, 0); /* pipe → UDP socket */
skb_to_sgvec() 把这个交错SGL直接喂给AEAD解密,解密输出就地覆盖在文件页上。HMAC校验失败会abort连接,但页缓存早已被污染。
第三步,192字节ELF payload分两批写入目标文件的页缓存,payload 内容是一段x86_64shellcode,先调setuid(0) 再 execve("/bin/sh")。污染完成后直接执行该SUID程序
execl(target, target, (char *)NULL);
POC可在以下仓库获取
- Delphos-Labs/disclosures · DirtyCBC
- v12-security/pocs · dirtydecrypt