Skip to content

Commit 6959d80

Browse files
committed
C#: ZipSlip - Update help, compile and test samples.
1 parent d6c58d6 commit 6959d80

File tree

8 files changed

+68
-26
lines changed

8 files changed

+68
-26
lines changed

csharp/ql/src/Security Features/CWE-022/ZipSlip.qhelp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
<overview>
66
<p>Extracting files from a malicious zip archive without validating that the destination file path
77
is within the destination directory can cause files outside the destination directory to be
8-
overwritten, due to the possible presence of directory traversal elements ("..") in archive
9-
paths.</p>
8+
overwritten, due to the possible presence of directory traversal elements (<code>..</code>) in
9+
archive paths.</p>
1010

1111
<p>Zip archives contain archive entries representing each file in the archive. These entries
1212
include a file path for the entry, but these file paths are not restricted and may contain
13-
unexpected special elements such as the directory traversal element (".."). If these file paths are
14-
use to determine an output file to write the contents of the archive item to, then the file may be
15-
written to an unexpected location. This can result in sensitive information being revealed or
16-
deleted, or an attacker being able to influence behavior by modifying unexpected files.</p>
13+
unexpected special elements such as the directory traversal element (<code>..</code>). If these
14+
file paths are used to determine an output file to write the contents of the archive item to, then
15+
the file may be written to an unexpected location. This can result in sensitive information being
16+
revealed or deleted, or an attacker being able to influence behavior by modifying unexpected
17+
files.</p>
1718

1819
<p>For example, if a zip file contains a file entry <code>..\sneaky-file</code>, and the zip file
1920
is extracted to the directory <code>c:\output</code>, then naively combining the paths would result
@@ -50,7 +51,7 @@ the result is within the destination directory. If provided with a zip file cont
5051
path like <code>..\sneaky-file</code>, then this file would be written outside of the destination
5152
directory.</p>
5253

53-
<sample src="ZipSlipBroken.cs" />
54+
<sample src="ZipSlipBad.cs" />
5455

5556
<p>In order to fix this vulnerability, we need to make three changes. Firstly, we need to resolve any
5657
directory traversal or other special characters in the path by using <code>Path.GetFullPath</code>.
@@ -59,7 +60,7 @@ Secondly, we need to identify the destination output directory, again using
5960
the resolved output starts with the resolved destination directory, and throw and exception if this
6061
is not the case.</p>
6162

62-
<sample src="ZipSlipFixed.cs" />
63+
<sample src="ZipSlipGood.cs" />
6364

6465
</example>
6566
<references>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System.IO;
2+
using System.IO.Compression;
3+
4+
class Bad
5+
{
6+
public static void WriteToDirectory(ZipArchiveEntry entry,
7+
string destDirectory)
8+
{
9+
string destFileName = Path.Combine(destDirectory, entry.FullName);
10+
entry.ExtractToFile(destFileName);
11+
}
12+
}

csharp/ql/src/Security Features/CWE-022/ZipSlipBroken.cs

Lines changed: 0 additions & 7 deletions
This file was deleted.

csharp/ql/src/Security Features/CWE-022/ZipSlipFixed.cs

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.IO;
2+
using System.IO.Compression;
3+
4+
class Good
5+
{
6+
public static void WriteToDirectory(ZipArchiveEntry entry,
7+
string destDirectory)
8+
{
9+
string destFileName = Path.GetFullPath(Path.Combine(destDirectory, entry.FullName));
10+
string fullDestDirPath = Path.GetFullPath(destDirectory + Path.DirectorySeparatorChar);
11+
if (!destFileName.StartsWith(fullDestDirPath)) {
12+
throw new System.InvalidOperationException("Entry is outside of the target dir: " +
13+
destFileName);
14+
}
15+
entry.ExtractToFile(destFileName);
16+
}
17+
}

csharp/ql/test/query-tests/Security Features/CWE-022/ZipSlip/ZipSlip.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
| ZipSlip.cs:68:71:68:82 | access to local variable destFilePath | Unsanitized zip archive $@ which may contain '..' used in a file system operation. | ZipSlip.cs:54:72:54:85 | access to property FullName | item path |
55
| ZipSlip.cs:75:57:75:68 | access to local variable destFilePath | Unsanitized zip archive $@ which may contain '..' used in a file system operation. | ZipSlip.cs:54:72:54:85 | access to property FullName | item path |
66
| ZipSlip.cs:83:58:83:69 | access to local variable destFilePath | Unsanitized zip archive $@ which may contain '..' used in a file system operation. | ZipSlip.cs:54:72:54:85 | access to property FullName | item path |
7+
| ZipSlipBad.cs:10:29:10:40 | access to local variable destFileName | Unsanitized zip archive $@ which may contain '..' used in a file system operation. | ZipSlipBad.cs:9:59:9:72 | access to property FullName | item path |
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System.IO;
2+
using System.IO.Compression;
3+
4+
class Bad
5+
{
6+
public static void WriteToDirectory(ZipArchiveEntry entry,
7+
string destDirectory)
8+
{
9+
string destFileName = Path.Combine(destDirectory, entry.FullName);
10+
entry.ExtractToFile(destFileName);
11+
}
12+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.IO;
2+
using System.IO.Compression;
3+
4+
class Good
5+
{
6+
public static void WriteToDirectory(ZipArchiveEntry entry,
7+
string destDirectory)
8+
{
9+
string destFileName = Path.GetFullPath(Path.Combine(destDirectory, entry.FullName));
10+
string fullDestDirPath = Path.GetFullPath(destDirectory + Path.DirectorySeparatorChar);
11+
if (!destFileName.StartsWith(fullDestDirPath)) {
12+
throw new System.InvalidOperationException("Entry is outside of the target dir: " +
13+
destFileName);
14+
}
15+
entry.ExtractToFile(destFileName);
16+
}
17+
}

0 commit comments

Comments
 (0)