mirror of
https://github.com/vmware-tanzu/velero.git
synced 2026-04-28 11:27:00 +00:00
Add more check for file extraction from tarball.
Signed-off-by: Xun Jiang <xun.jiang@broadcom.com>
This commit is contained in:
1
changelogs/unreleased/9614-blackpiglet
Normal file
1
changelogs/unreleased/9614-blackpiglet
Normal file
@@ -0,0 +1 @@
|
||||
Add check for file extraction from tarball.
|
||||
@@ -19,8 +19,10 @@ package archive
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
@@ -84,7 +86,15 @@ func (e *Extractor) readBackup(tarRdr *tar.Reader) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
target := filepath.Join(dir, header.Name) //nolint:gosec // Internal usage. No need to check.
|
||||
target := filepath.Join(dir, header.Name)
|
||||
relPath, err := filepath.Rel(filepath.Clean(dir), filepath.Clean(target))
|
||||
if err != nil {
|
||||
e.log.Infof("error validating extraction target %q: %v", header.Name, err)
|
||||
return "", err
|
||||
}
|
||||
if relPath == ".." || strings.HasPrefix(relPath, ".."+string(filepath.Separator)) {
|
||||
return "", fmt.Errorf("invalid archive path %q: escapes target directory", header.Name)
|
||||
}
|
||||
|
||||
switch header.Typeflag {
|
||||
case tar.TypeDir:
|
||||
|
||||
@@ -18,6 +18,7 @@ package archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"os"
|
||||
@@ -87,6 +88,31 @@ func TestUnzipAndExtractBackup(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnzipAndExtractBackupRejectsPathTraversal(t *testing.T) {
|
||||
ext := NewExtractor(test.NewLogger(), test.NewFakeFileSystem())
|
||||
|
||||
var buf bytes.Buffer
|
||||
gzw := gzip.NewWriter(&buf)
|
||||
tw := tar.NewWriter(gzw)
|
||||
|
||||
err := tw.WriteHeader(&tar.Header{
|
||||
Name: "../escape.txt",
|
||||
Mode: 0600,
|
||||
Typeflag: tar.TypeReg,
|
||||
Size: int64(len("data")),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = tw.Write([]byte("data"))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, tw.Close())
|
||||
require.NoError(t, gzw.Close())
|
||||
|
||||
_, err = ext.UnzipAndExtractBackup(&buf)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "invalid archive path")
|
||||
}
|
||||
|
||||
func createArchive(files []string, fs filesystem.Interface) (string, error) {
|
||||
outName := "output.tar.gz"
|
||||
out, err := fs.Create(outName)
|
||||
|
||||
Reference in New Issue
Block a user