fix: enhance path sanitization in backup and log services to prevent directory traversal

This commit is contained in:
Wikid82
2025-11-20 23:07:48 -05:00
parent 6d03575ea6
commit 39f6cf9155
3 changed files with 26 additions and 4 deletions

View File

@@ -160,20 +160,21 @@ func (s *BackupService) addDirToZip(w *zip.Writer, srcDir, zipBase string) error
// DeleteBackup removes a backup file
func (s *BackupService) DeleteBackup(filename string) error {
// Basic sanitization to prevent directory traversal
clean := filepath.Base(filename)
clean := filepath.Base(filepath.Clean(filename))
return os.Remove(filepath.Join(s.BackupDir, clean))
}
// GetBackupPath returns the full path to a backup file (for downloading)
func (s *BackupService) GetBackupPath(filename string) string {
clean := filepath.Base(filename)
clean := filepath.Base(filepath.Clean(filename))
return filepath.Join(s.BackupDir, clean)
}
// RestoreBackup restores the database and caddy data from a zip archive
func (s *BackupService) RestoreBackup(filename string) error {
// 1. Verify backup exists
srcPath := filepath.Join(s.BackupDir, filename)
clean := filepath.Base(filepath.Clean(filename))
srcPath := filepath.Join(s.BackupDir, clean)
if _, err := os.Stat(srcPath); err != nil {
return err
}

View File

@@ -103,3 +103,24 @@ func TestBackupService_Restore_ZipSlip(t *testing.T) {
assert.Error(t, err)
assert.Contains(t, err.Error(), "illegal file path")
}
func TestBackupService_PathTraversal(t *testing.T) {
tmpDir := t.TempDir()
service := &BackupService{
DataDir: filepath.Join(tmpDir, "data"),
BackupDir: filepath.Join(tmpDir, "backups"),
}
os.MkdirAll(service.BackupDir, 0755)
// Test GetBackupPath with traversal
// Should resolve to .../backups/passwd, NOT .../etc/passwd
path := service.GetBackupPath("../../etc/passwd")
expected := filepath.Join(service.BackupDir, "passwd")
assert.Equal(t, expected, path)
// Test DeleteBackup with traversal
// Should try to delete .../backups/passwd, fail because it doesn't exist
err := service.DeleteBackup("../../etc/passwd")
assert.Error(t, err)
assert.True(t, os.IsNotExist(err))
}

View File

@@ -59,7 +59,7 @@ func (s *LogService) ListLogs() ([]LogFile, error) {
// GetLogPath returns the absolute path to a log file if it exists and is valid
func (s *LogService) GetLogPath(filename string) (string, error) {
clean := filepath.Base(filename)
clean := filepath.Base(filepath.Clean(filename))
path := filepath.Join(s.LogDir, clean)
// Verify file exists