Skip to content
This repository has been archived by the owner on Nov 19, 2024. It is now read-only.

Commit

Permalink
fix: prevent extraction of archived files outside target path
Browse files Browse the repository at this point in the history
  • Loading branch information
aviadatsnyk committed Apr 16, 2018
1 parent 26cf5bb commit e8249d1
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 10 deletions.
5 changes: 4 additions & 1 deletion cmd/archiver/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ func main() {
}
err = ff.Make(filename, os.Args[3:])
case "open":
dest := ""
dest, err := os.Getwd()
if err != nil {
fatal(err)
}
if len(os.Args) == 4 {
dest = os.Args[3]
} else if len(os.Args) > 4 {
Expand Down
14 changes: 11 additions & 3 deletions rar.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,16 @@ func (rarFormat) Read(input io.Reader, destination string) error {
return err
}

// to avoid zip slip (writing outside of the destination), we
// resolve the target path, and make sure it's nested in
// the intended destination, or bail otherwise.
destpath := filepath.Join(destination, header.Name)
if !strings.HasPrefix(destpath, destination) {
return fmt.Errorf("%s: illegal file path", header.Name)
}

if header.IsDir {
err = mkdir(filepath.Join(destination, header.Name))
err = mkdir(destpath)
if err != nil {
return err
}
Expand All @@ -82,12 +90,12 @@ func (rarFormat) Read(input io.Reader, destination string) error {

// if files come before their containing folders, then we must
// create their folders before writing the file
err = mkdir(filepath.Dir(filepath.Join(destination, header.Name)))
err = mkdir(filepath.Dir(destpath))
if err != nil {
return err
}

err = writeNewFile(filepath.Join(destination, header.Name), rr, header.Mode())
err = writeNewFile(destpath, rr, header.Mode())
if err != nil {
return err
}
Expand Down
16 changes: 12 additions & 4 deletions tar.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,15 +219,23 @@ func untar(tr *tar.Reader, destination string) error {

// untarFile untars a single file from tr with header header into destination.
func untarFile(tr *tar.Reader, header *tar.Header, destination string) error {
// to avoid zip slip (writing outside of the destination), we resolve
// the target path, and make sure it's nested in the intended
// destination, or bail otherwise.
destpath := filepath.Join(destination, header.Name)
if !strings.HasPrefix(destpath, destination) {
return fmt.Errorf("%s: illegal file path", header.Name)
}

switch header.Typeflag {
case tar.TypeDir:
return mkdir(filepath.Join(destination, header.Name))
return mkdir(destpath)
case tar.TypeReg, tar.TypeRegA, tar.TypeChar, tar.TypeBlock, tar.TypeFifo:
return writeNewFile(filepath.Join(destination, header.Name), tr, header.FileInfo().Mode())
return writeNewFile(destpath, tr, header.FileInfo().Mode())
case tar.TypeSymlink:
return writeNewSymbolicLink(filepath.Join(destination, header.Name), header.Linkname)
return writeNewSymbolicLink(destpath, header.Linkname)
case tar.TypeLink:
return writeNewHardLink(filepath.Join(destination, header.Name), filepath.Join(destination, header.Linkname))
return writeNewHardLink(destpath, filepath.Join(destination, header.Linkname))
default:
return fmt.Errorf("%s: unknown type flag: %c", header.Name, header.Typeflag)
}
Expand Down
11 changes: 9 additions & 2 deletions zip.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,15 @@ func unzipAll(r *zip.Reader, destination string) error {
}

func unzipFile(zf *zip.File, destination string) error {
// to avoid zip slip (writing outside of the destination), we resolve
// the target path, and make sure it's nested in the intended
// destination, or bail otherwise.
destpath := filepath.Join(destination, zf.Name)
if !strings.HasPrefix(destpath, destination) {
return fmt.Errorf("%s: illegal file path", zf.Name)
}
if strings.HasSuffix(zf.Name, "/") {
return mkdir(filepath.Join(destination, zf.Name))
return mkdir(destpath)
}

rc, err := zf.Open()
Expand All @@ -197,7 +204,7 @@ func unzipFile(zf *zip.File, destination string) error {
}
defer rc.Close()

return writeNewFile(filepath.Join(destination, zf.Name), rc, zf.FileInfo().Mode())
return writeNewFile(destpath, rc, zf.FileInfo().Mode())
}

// compressedFormats is a (non-exhaustive) set of lowercased
Expand Down

0 comments on commit e8249d1

Please sign in to comment.