已关闭
security: fix path traversal in GetFile and PostFiles APIs #196
gcw_Nt0RibX4创建于 9月6日关闭于 9月10日
security: fix path traversal in GetFile and PostFiles APIs #196
已关闭
共 1 个文件变更+21-4
| @@ -9,6 +9,7 @@ import ( | |||
| 9 | "os" | 9 | "os" |
| 10 | "os/exec" | 10 | "os/exec" |
| 11 | "path/filepath" | 11 | "path/filepath" |
| 12 | + "strings" | ||
| 12 | 13 | ||
| 13 | pb "github.com/openeuler/Conch/api/go_proto" | 14 | pb "github.com/openeuler/Conch/api/go_proto" |
| 14 | "github.com/openeuler/Conch/pkg/ulog" | 15 | "github.com/openeuler/Conch/pkg/ulog" |
| @@ -215,6 +216,15 @@ func (s *AgentServer) PostFiles(ctx context.Context, req *pb.PostFilesRequest) ( | |||
| 215 | }, nil | 216 | }, nil |
| 216 | } | 217 | } |
| 217 | 218 | ||
| 219 | + if filepath.IsAbs(cleanedFilepath) || strings.Contains(cleanedFilepath, "..") { | ||
| 220 | + errMsg := "invalid filepath: only relative paths within working directory are allowed" | ||
| 221 | + ulog.Error("PostFiles", ulog.F("message", errMsg), ulog.F("filepath", file.Filepath)) | ||
| 222 | + return &pb.PostFilesResponse{ | ||
| 223 | + UploadedCount: uploadedCount, | ||
| 224 | + Error: errMsg, | ||
| 225 | + }, nil | ||
| 226 | + } | ||
| 227 | + | ||
| 218 | // Create parent directories if needed | 228 | // Create parent directories if needed |
| 219 | targetDir := filepath.Dir(cleanedFilepath) | 229 | targetDir := filepath.Dir(cleanedFilepath) |
| 220 | if err := os.MkdirAll(targetDir, DirPerm); err != nil { | 230 | if err := os.MkdirAll(targetDir, DirPerm); err != nil { |
| @@ -256,21 +266,28 @@ func (s *AgentServer) GetFile(ctx context.Context, req *pb.GetFileRequest) (*pb. | |||
| 256 | return &pb.GetFileResponse{Error: errMsg}, nil | 266 | return &pb.GetFileResponse{Error: errMsg}, nil |
| 257 | } | 267 | } |
| 258 | 268 | ||
| 259 | - content, err := os.ReadFile(req.Filepath) | 269 | + cleanedFilepath := filepath.Clean(req.Filepath) |
| 270 | + if filepath.IsAbs(cleanedFilepath) || strings.Contains(cleanedFilepath, "..") { | ||
| 271 | + errMsg := "invalid filepath: only relative paths within working directory are allowed" | ||
| 272 | + ulog.Warn("GetFile", ulog.F("message", errMsg), ulog.F("filepath", req.Filepath)) | ||
| 273 | + return &pb.GetFileResponse{Error: errMsg}, nil | ||
| 274 | + } | ||
| 275 | + | ||
| 276 | + content, err := os.ReadFile(cleanedFilepath) | ||
| 260 | if err != nil { | 277 | if err != nil { |
| 261 | var errMsg string | 278 | var errMsg string |
| 262 | if os.IsNotExist(err) { | 279 | if os.IsNotExist(err) { |
| 263 | - errMsg = "file not found: " + req.Filepath | 280 | + errMsg = "file not found: " + cleanedFilepath |
| 264 | ulog.Warn("GetFile", ulog.F("message", errMsg)) | 281 | ulog.Warn("GetFile", ulog.F("message", errMsg)) |
| 265 | } else { | 282 | } else { |
| 266 | - errMsg = "failed to read file " + req.Filepath + ": " + err.Error() | 283 | + errMsg = "failed to read file " + cleanedFilepath + ": " + err.Error() |
| 267 | ulog.Warn("GetFile", ulog.F("message", errMsg)) | 284 | ulog.Warn("GetFile", ulog.F("message", errMsg)) |
| 268 | } | 285 | } |
| 269 | return &pb.GetFileResponse{Error: errMsg}, nil | 286 | return &pb.GetFileResponse{Error: errMsg}, nil |
| 270 | } | 287 | } |
| 271 | 288 | ||
| 272 | ulog.Info("Successfully read file", | 289 | ulog.Info("Successfully read file", |
| 273 | - ulog.F("file", req.Filepath), | 290 | + ulog.F("file", cleanedFilepath), |
| 274 | ulog.F("size", len(content))) | 291 | ulog.F("size", len(content))) |
| 275 | return &pb.GetFileResponse{Content: content}, nil | 292 | return &pb.GetFileResponse{Content: content}, nil |
| 276 | } | 293 | } |