handle symlinks
This commit is contained in:
parent
1e733b6d6d
commit
7bb71f07ca
60
build-all.go
60
build-all.go
|
@ -133,7 +133,8 @@ func main() {
|
||||||
if nil != err {
|
if nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
err = unzip(z, s.Size(), outdir, npath)
|
strip := 1
|
||||||
|
err = unzip(z, s.Size(), outdir, strip)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -142,7 +143,8 @@ func main() {
|
||||||
if nil != err {
|
if nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
err = untar(tgz, outdir, npath)
|
strip := 1
|
||||||
|
err = untar(tgz, outdir, strip)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -163,16 +165,16 @@ func main() {
|
||||||
if nil != err {
|
if nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if err := unzip(z, s.Size(), outdir, "telebit.js"); nil != err {
|
strip := 1
|
||||||
|
if err := unzip(z, s.Size(), outdir, strip); nil != err {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Done.\n")
|
fmt.Printf("Done.\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func untar(tgz io.Reader, outdir string, strip string) error {
|
func untar(tgz io.Reader, outdir string, strip int) error {
|
||||||
t, err := gzip.NewReader(tgz)
|
t, err := gzip.NewReader(tgz)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return err
|
return err
|
||||||
|
@ -188,15 +190,20 @@ func untar(tgz io.Reader, outdir string, strip string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fpath := header.Name
|
fpath := stripPrefix(header.Name, strip)
|
||||||
fpath = filepath.Join(outdir, strings.Trim(strings.Trim(strings.TrimPrefix(fpath, strip), `/`), `\`))
|
fpath = filepath.Join(outdir, fpath)
|
||||||
|
|
||||||
switch header.Typeflag {
|
switch header.Typeflag {
|
||||||
case tar.TypeLink:
|
case tar.TypeLink:
|
||||||
// ignore hard links
|
// ignore hard links
|
||||||
case tar.TypeSymlink:
|
case tar.TypeSymlink:
|
||||||
// we don't really expect these (or support them)
|
// Note: the link itself is always a file, even when it represents a directory
|
||||||
fmt.Printf("[debug] symlink? %s\n", fpath)
|
lpath := filepath.Join(filepath.Dir(fpath), header.Linkname)
|
||||||
|
if !strings.HasPrefix(lpath+string(os.PathSeparator), outdir+string(os.PathSeparator)) {
|
||||||
|
return fmt.Errorf("Malicious link path: %s", header.Linkname)
|
||||||
|
}
|
||||||
|
if err := os.Symlink(header.Linkname, fpath); nil != err {
|
||||||
|
return err
|
||||||
|
}
|
||||||
case tar.TypeDir:
|
case tar.TypeDir:
|
||||||
// gonna use the same perms as were set previously here
|
// gonna use the same perms as were set previously here
|
||||||
// should be fine (i.e. we want 755 for execs on *nix)
|
// should be fine (i.e. we want 755 for execs on *nix)
|
||||||
|
@ -227,7 +234,7 @@ func untar(tgz io.Reader, outdir string, strip string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func unzip(z io.ReaderAt, size int64, outdir string, strip string) error {
|
func unzip(z io.ReaderAt, size int64, outdir string, strip int) error {
|
||||||
zr, err := zip.NewReader(z, size)
|
zr, err := zip.NewReader(z, size)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return err
|
return err
|
||||||
|
@ -235,8 +242,9 @@ func unzip(z io.ReaderAt, size int64, outdir string, strip string) error {
|
||||||
|
|
||||||
for i := range zr.File {
|
for i := range zr.File {
|
||||||
f := zr.File[i]
|
f := zr.File[i]
|
||||||
fpath := filepath.Join(outdir, strings.Trim(strings.Trim(strings.TrimPrefix(f.Name, strip), `/`), `\`))
|
|
||||||
|
|
||||||
|
fpath := stripPrefix(f.Name, strip)
|
||||||
|
fpath = filepath.Join(outdir, fpath)
|
||||||
out, err := safeOpen(f.FileInfo(), f.Mode(), fpath, outdir)
|
out, err := safeOpen(f.FileInfo(), f.Mode(), fpath, outdir)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return err
|
return err
|
||||||
|
@ -271,15 +279,37 @@ func unzip(z io.ReaderAt, size int64, outdir string, strip string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stripPrefix(fpath string, strip int) string {
|
||||||
|
// /foo/bar/baz/ => foo/bar/baz
|
||||||
|
// strip 1 => bar/baz
|
||||||
|
fpath = strings.Trim(filepath.ToSlash(fpath), "/")
|
||||||
|
parts := []string{}
|
||||||
|
if "" != fpath {
|
||||||
|
parts = strings.Split(fpath, "/")
|
||||||
|
}
|
||||||
|
if strip > 0 {
|
||||||
|
n := len(parts)
|
||||||
|
if strip > n {
|
||||||
|
strip = n
|
||||||
|
}
|
||||||
|
if 0 != len(parts) {
|
||||||
|
parts = parts[strip:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(parts, "/")
|
||||||
|
}
|
||||||
|
|
||||||
// given the path return a file, tell that it's a directory, or error out
|
// given the path return a file, tell that it's a directory, or error out
|
||||||
func safeOpen(fi os.FileInfo, fm os.FileMode, fpath string, outdir string) (io.WriteCloser, error) {
|
func safeOpen(fi os.FileInfo, fm os.FileMode, fpath string, outdir string) (io.WriteCloser, error) {
|
||||||
// Keep it clean
|
// Keep it clean
|
||||||
// https://github.com/snyk/zip-slip-vulnerability
|
// https://github.com/snyk/zip-slip-vulnerability
|
||||||
cleanpath, _ := filepath.Abs(filepath.Clean(fpath))
|
cleanpath, _ := filepath.Abs(filepath.Clean(fpath))
|
||||||
cleandest, _ := filepath.Abs(filepath.Clean(outdir))
|
cleandest, _ := filepath.Abs(filepath.Clean(outdir))
|
||||||
//fmt.Println(cleandest)
|
|
||||||
//fmt.Println(cleanpath + string(os.PathSeparator))
|
// foo/ foo => foo// foo/
|
||||||
if !strings.HasPrefix(cleanpath, cleandest) {
|
// foo/ foo/bar.md => foo// foo/bar.md/
|
||||||
|
if !strings.HasPrefix(cleanpath+string(os.PathSeparator), cleandest+string(os.PathSeparator)) {
|
||||||
return nil, fmt.Errorf("Malicious file path: %s", fpath)
|
return nil, fmt.Errorf("Malicious file path: %s", fpath)
|
||||||
}
|
}
|
||||||
fpath = cleanpath
|
fpath = cleanpath
|
||||||
|
|
Loading…
Reference in New Issue