使用o3模型发现Linux内核SMB远程零日漏洞CVE-2025-37899

本文详细介绍了如何利用OpenAI的o3模型在Linux内核的ksmbd模块中发现一个远程释放后使用漏洞。该漏洞存在于SMB会话注销处理程序中,涉及并发连接场景下的对象管理问题,展示了AI在漏洞研究中的实际应用价值。

使用o3发现Linux内核SMB实现中的远程零日漏洞CVE-2025-37899

在本文中,我将展示如何使用OpenAI的o3模型在Linux内核中发现一个零日漏洞。我仅使用o3 API就找到了这个漏洞——没有复杂的脚手架,没有智能体框架,也没有工具使用。

最近我一直在审计ksmbd中的漏洞。ksmbd是"一个在内核空间实现SMB3协议的Linux内核服务器,用于通过网络共享文件"。我启动这个项目本是为了从LLM相关的工具开发中休息一下,但在o3发布后,我忍不住使用在ksmbd中找到的漏洞作为o3能力的快速基准测试。

使用CVE-2025-37778基准测试o3

CVE-2025-37778是一个释放后使用漏洞。该问题发生在处理来自远程客户端的"会话设置"请求时的Kerberos认证路径中。

根本原因如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
static int krb5_authenticate(struct ksmbd_work *work,
                 struct smb2_sess_setup_req *req,
                 struct smb2_sess_setup_rsp *rsp)
{
...
    if (sess->state == SMB2_SESSION_VALID)
        ksmbd_free_user(sess->user);
        
    retval = ksmbd_krb5_authenticate(sess, in_blob, in_len,
                    out_blob, &out_len);
    if (retval) {
        ksmbd_debug(SMB, "krb5 authentication failed\n");
        return -EINVAL;
    }
...

如果krb5_authenticate检测到会话状态为SMB2_SESSION_VALID,则会释放sess->user。这里的假设似乎是之后ksmbd_krb5_authenticate会将其重新初始化为新的有效值,或者在krb5_authenticate返回-EINVAL后,sess->user不会在其他地方使用。事实证明,这个假设是错误的。

实验设置

为了评估o3的性能,我采用了以下方法:

  • 给LLM提供"会话设置"命令处理程序的代码,包括它调用的所有函数的代码,最多3层调用深度
  • 包括所有从网络读取数据、解析传入请求、选择要运行的命令处理程序以及在处理程序完成后拆除连接的代码
  • 最终代码量约为3.3k LoC(约27k tokens)

提示设置:

  • 我告诉LLM寻找释放后使用漏洞
  • 提供了ksmbd的高级概述、其架构和威胁模型
  • 强烈引导它不要报告误报,宁愿不报告任何错误也不要报告误报

基准测试结果

o3在100次运行中的8次找到了Kerberos认证漏洞。在另外66次运行中,o3得出结论认为代码中没有错误(假阴性),其余28份报告是误报。

相比之下,Claude Sonnet 3.7在100次运行中找到了3次,而Claude Sonnet 3.5在100次运行中一次也没有找到。

o3发现零日漏洞(CVE-2025-37899)

在确认o3可以在给定会话设置命令处理程序代码的情况下找到Kerberos认证漏洞后,我想看看如果给它所有命令处理程序的代码,它是否还能找到漏洞。这是一个更难的问题,因为命令处理程序都在smb2pdu.c中,约有9k LoC。

将所有处理程序的代码与连接设置和拆除代码以及命令处理程序分发例程结合起来,最终达到约12k LoC(约100k输入tokens),和之前一样,我运行了100次实验。

o3在这个更大输入tokens数量的情况下,在100次运行中的1次找到了Kerberos认证漏洞,性能明显下降,但仍然找到了。更有趣的是,在其他运行的输出中,我找到了一个类似但新颖的漏洞报告,这是我之前不知道的。这个漏洞也是由于释放了sess->user,但这次是在会话注销处理程序中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
int smb2_session_logoff(struct ksmbd_work *work)
{
    struct ksmbd_conn *conn = work->conn;
    struct ksmbd_session *sess = work->sess;
        
    ...
        
    ksmbd_close_session_fds(work);
    ksmbd_conn_wait_idle(conn);
        
    ...
        
    down_write(&conn->session_lock);
    sess->state = SMB2_SESSION_EXPIRED;
    up_write(&conn->session_lock);
    
    if (sess->user) {
        ksmbd_free_user(sess->user);
        sess->user = NULL;
    }
    ...

o3的漏洞描述

简短描述: 当一个ksmbd工作线程仍在执行使用sess->user的请求时,另一个处理相同会话的SMB2 LOGOFF的线程释放了该结构。没有同步保护指针,因此第一个线程解引用了已释放的内存——这是一个经典的释放后使用,会导致内核内存损坏和内核上下文中的任意代码执行。

受影响代码路径:

  1. 第二个传输绑定到现有会话(SMB 3.0或更高版本,conn->binding == true
  2. 工作线程A(在连接C2上运行)接收任何正常请求(例如WRITE)
  3. 在工作线程A完成之前,工作线程B(在第一个连接C1上运行)处理相同会话的SMB2 LOGOFF并执行smb2_session_logoff()
  4. 工作线程B不等待仍在使用会话的其他连接;它只等待在其自己连接上运行的请求
  5. 工作线程A继续执行(例如在smb2_open()smb2_write()内部)并解引用sess->user

结论

LLMs存在于程序分析技术能力空间中的一个点,比我们见过的任何东西都更接近人类。考虑到创造力、灵活性和通用性等属性,LLMs更类似于人类代码审计员,而不是符号执行、抽象解释或模糊测试。

自GPT-4以来,LLMs在漏洞研究中的潜力已有暗示,但真实问题上的结果从未完全达到希望或炒作的程度。随着o3的出现,这种情况已经改变,我们有了一个在代码推理、问答、编程和问题解决方面表现足够好的模型,可以真正增强人类在漏洞研究方面的表现。

o3并非完美无缺。远非如此。它仍然有很大机会产生荒谬的结果并让你感到沮丧。不同的是,这是第一次获得正确结果的机会足够高,值得你花时间和精力尝试在真实问题上使用它。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计