From 0cbdef20f1d5654ab5b93a6ce1ff8a917d3b905b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nils=20m=C3=A5s=C3=A9n?= Date: Wed, 7 Oct 2020 19:21:20 +0200 Subject: [PATCH] PR #519: Restrict path traversal on TarArchive extraction --- src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs b/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs index 562480a3c..7bc770d17 100644 --- a/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs +++ b/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs @@ -1,6 +1,8 @@ using System; using System.IO; +using System.Numerics; using System.Text; +using ICSharpCode.SharpZipLib.Core; namespace ICSharpCode.SharpZipLib.Tar { @@ -594,13 +596,25 @@ public void ListContents() /// /// The destination directory into which to extract. /// - public void ExtractContents(string destinationDirectory) + public void ExtractContents(string destinationDirectory) + => ExtractContents(destinationDirectory, false); + + /// + /// Perform the "extract" command and extract the contents of the archive. + /// + /// + /// The destination directory into which to extract. + /// + /// Allow parent directory traversal in file paths (e.g. ../file) + public void ExtractContents(string destinationDirectory, bool allowParentTraversal) { if (isDisposed) { throw new ObjectDisposedException("TarArchive"); } + var fullDistDir = Path.GetFullPath(destinationDirectory); + while (true) { TarEntry entry = tarIn.GetNextEntry(); @@ -613,7 +627,7 @@ public void ExtractContents(string destinationDirectory) if (entry.TarHeader.TypeFlag == TarHeader.LF_LINK || entry.TarHeader.TypeFlag == TarHeader.LF_SYMLINK) continue; - ExtractEntry(destinationDirectory, entry); + ExtractEntry(fullDistDir, entry, allowParentTraversal); } } @@ -627,7 +641,8 @@ public void ExtractContents(string destinationDirectory) /// /// The TarEntry returned by tarIn.GetNextEntry(). /// - private void ExtractEntry(string destDir, TarEntry entry) + /// Allow parent directory traversal in file paths (e.g. ../file) + private void ExtractEntry(string destDir, TarEntry entry, bool allowParentTraversal) { OnProgressMessageEvent(entry, null); @@ -644,6 +659,11 @@ private void ExtractEntry(string destDir, TarEntry entry) string destFile = Path.Combine(destDir, name); + if (!allowParentTraversal && !Path.GetFullPath(destFile).StartsWith(destDir, StringComparison.InvariantCultureIgnoreCase)) + { + throw new InvalidNameException("Parent traversal in paths is not allowed"); + } + if (entry.IsDirectory) { EnsureDirectoryExists(destFile);