icsharpcode / SharpZipLib

#ziplib is a Zip, GZip, Tar and BZip2 library written entirely in C# for the .NET platform.
http://icsharpcode.github.io/SharpZipLib/
MIT License
3.73k stars 976 forks source link

InvalidNameException(Parent traversal in paths is not allowed) is thrown when trying to extract directory archive with RootPath #758

Closed 6opuc closed 1 year ago

6opuc commented 2 years ago

Steps to reproduce

  1. Create archive from /some/directory using SharpZipLib: recursive, set RootPath to /some/directory
  2. Extact this archive using SharpZipLib

Expected behavior

Archive should be extracted

Actual behavior

InvalidNameException(Parent traversal in paths is not allowed)

Version of SharpZipLib

1.3.3

Obtained from (only keep the relevant lines)

Example

using System.Text;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;

var directory = $"/tmp/{Guid.NewGuid()}";
Directory.CreateDirectory(directory);
File.WriteAllText($"{directory}/1.txt", "1");

var archiveFilePath = $"/tmp/{Guid.NewGuid()}.tar.gz";

using (var archiveStream = new GZipOutputStream(File.Create(archiveFilePath)))
{
    using (TarArchive tarArchive = TarArchive.CreateOutputTarArchive(archiveStream, Encoding.UTF8))
    {
        tarArchive.RootPath = directory;
        // this is workaround for another issue: tarArchive.RootPath is ignored otherwise
        while (tarArchive.RootPath.StartsWith("/", StringComparison.Ordinal))
        {
            tarArchive.RootPath = tarArchive.RootPath.Substring(1);
        }
        var entry = TarEntry.CreateEntryFromFile(directory);
        // ExtractContents fails without this line of code below:  Parent traversal in paths is not allowed
        //entry.Name += "./";
        tarArchive.WriteEntry(entry, true);
    }
}

using (var archiveStream = File.OpenRead(archiveFilePath))
{
    using (var gzipStream = new GZipInputStream(archiveStream))
    {
        using (var tarArchive = TarArchive.CreateInputTarArchive(gzipStream, Encoding.UTF8))
        {
            tarArchive.ExtractContents($"/tmp/{Guid.NewGuid()}");
        }
    }
}

Console.WriteLine("Done");
piksel commented 1 year ago

If you want to allow path traversal, you need to explicitly allow it using ExtractContents(String, Boolean).

To log the actual internal file paths of the tar archive (on either extract and/or create), use:

tarArchive.ProgressMessageEvent += (archive, entry, message) => {
    Console.WriteLine($"{entry.Name}: {message}");
}
piksel commented 1 year ago

I think the core of this issue was what #582 fixed. The sample above works as expected in v1.4+: https://dotnetfiddle.net/TDSoGn