🔒 修复分享列表接口的目录遍历漏洞
- 在 /api/share/:code/list 增加路径规范化与范围校验 - 使用 path.posix.normalize 处理 subPath,阻断 ../ 遍历攻击 - 调用 isPathWithinShare 验证请求路径在分享范围内 - 统一使用安全的 requestedPath 进行存储访问和直链生成 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2902,6 +2902,20 @@ app.post('/api/share/:code/list', shareRateLimitMiddleware, async (req, res) =>
|
||||
});
|
||||
}
|
||||
|
||||
// 构造安全的请求路径,防止越权遍历
|
||||
const baseSharePath = (share.share_path || '/').replace(/\\/g, '/');
|
||||
const requestedPath = subPath
|
||||
? path.posix.normalize(`${baseSharePath}/${subPath}`)
|
||||
: baseSharePath;
|
||||
|
||||
// 校验请求路径是否在分享范围内
|
||||
if (!isPathWithinShare(requestedPath, share)) {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
message: '无权访问该路径'
|
||||
});
|
||||
}
|
||||
|
||||
// 使用统一存储接口,根据分享的storage_type选择存储后端
|
||||
const { StorageInterface } = require('./storage');
|
||||
const storageType = share.storage_type || 'sftp';
|
||||
@@ -2957,14 +2971,13 @@ app.post('/api/share/:code/list', shareRateLimitMiddleware, async (req, res) =>
|
||||
}
|
||||
// 如果是目录分享(分享所有文件)
|
||||
else {
|
||||
const fullPath = subPath ? `${share.share_path}/${subPath}`.replace('//', '/') : share.share_path;
|
||||
const list = await storage.list(fullPath);
|
||||
const list = await storage.list(requestedPath);
|
||||
|
||||
formattedList = list.map(item => {
|
||||
// 构建完整的文件路径用于下载
|
||||
let httpDownloadUrl = null;
|
||||
if (storageType === 'sftp' && sanitizedShareHttpBase && item.type !== 'd') {
|
||||
const normalizedPath = fullPath.startsWith('/') ? fullPath : `/${fullPath}`;
|
||||
const normalizedPath = requestedPath.startsWith('/') ? requestedPath : `/${requestedPath}`;
|
||||
const filePath = normalizedPath === '/' ? `/${item.name}` : `${normalizedPath}/${item.name}`;
|
||||
httpDownloadUrl = buildHttpDownloadUrl(sanitizedShareHttpBase, filePath);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user