如何确保所有写入的文件都位于给定路径下方(防止目录访问)

发布于 2024-12-10 12:19:59 字数 702 浏览 0 评论 0原文

我们有一个 C# 应用程序,它将文件写入可配置的位置。文件集(和相对路径)是在运行时确定的。

我们希望确保它不能在配置的位置之外写入文件。

例如,配置的位置可能是 c:\Stuff\Export,程序在 C:\Stuff\Important 下写入任何内容都会出错。

实际上,我认为我们可以通过两种方式实现这一点: 1)断言没有任何相对路径(要写入的文件)指定“父目录”(通常为“../”) - System.Path 没有指定“父目录”路径组件(就像它用于路径分隔一样)即系统.Path.PathSeparator)。我觉得检查字符串中的“../”有点笨拙。

2) 断言生成的所有最终绝对路径(通过将输出位置与文件相对路径组合)都相对于输出位置下方的ie。但我不太确定该怎么做。

Example usage:
Output directory: c:\Stuff\Export
Output path 1: "foo\bar\important.xls"
Output path 2: "foo\boo\something.csv"
Output path 3: "../../io.sys"

Expected final files
1. c:\Stuff\Export\foo\bar\important.xls
2. c:\Stuff\Export\foo\boo\something.csv
3. Should throw exception

We have a C# application which will write files to a configurable location. The set of files (and relative paths) is determined at runtime.

We want to ensure that it cannot write files outside the configured location.

For example, the configured location might be c:\Stuff\Export, it would be an error for the program to write anything under C:\Stuff\Important

Really, I think we can achieve this in two ways:
1) Assert none of the relative paths (files to be written) specify 'Parent directory' (typically "../") - System.Path doesn't specify a "parent directory" path component though (like it has for path separation i.e. System.Path.PathSeparator). I feel a bit cludgey checking for "../" in the string.

2) Assert that all of the final absolute paths that are generated (by combining the output location with the file relative path) are relative to i.e. underneath the output location. I'm not exactly sure how to go about this though.

Example usage:
Output directory: c:\Stuff\Export
Output path 1: "foo\bar\important.xls"
Output path 2: "foo\boo\something.csv"
Output path 3: "../../io.sys"

Expected final files
1. c:\Stuff\Export\foo\bar\important.xls
2. c:\Stuff\Export\foo\boo\something.csv
3. Should throw exception

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

狼性发作 2024-12-17 12:19:59

如果您创建 DirectoryInfo 两个路径上的实例,其 FullName 属性应返回完全限定的规范路径。因此,如果您只是对要比较的两侧执行此操作,则可以执行以下操作:

if (chosenDirectory.FullName != configuredDirectory.FullName)
{
    throw new InvalidOperationException(
        String.Format("Invalid path {0}.", chosenDirectory));
}

由于 FullName 只是一个字符串,因此您可以在路径上进行常规字符串比较,例如:

if (!chosenDirectory.FullName.StartsWith(configuredDirectory.FullName,
    StringComparison.InvariantCultureIgnoreCase))
{
    throw new InvalidOperationException(
        String.Format("Invalid path {0}.", chosenDirectory));
}

您还可以使用父级 属性并比较其 FullName到所选目录,如果您不想在配置的目录中允许子目录:

if (!chosenDirectory.Parent.FullName.Equals(configuredDirectory.FullName,
    StringComparison.InvariantCultureIgnoreCase))
{
    throw new InvalidOperationException(
        String.Format("Invalid path {0}.", chosenDirectory));
}

If you create a DirectoryInfo instance on the two paths, its FullName property should return the fully qualified, canonical path. So if you just do that for both of the sides you want to compare, you can do this:

if (chosenDirectory.FullName != configuredDirectory.FullName)
{
    throw new InvalidOperationException(
        String.Format("Invalid path {0}.", chosenDirectory));
}

Since FullName is just a string, you can do regular string comparison on the paths, like:

if (!chosenDirectory.FullName.StartsWith(configuredDirectory.FullName,
    StringComparison.InvariantCultureIgnoreCase))
{
    throw new InvalidOperationException(
        String.Format("Invalid path {0}.", chosenDirectory));
}

You can also use the Parent property and compare its FullName to the chosen directory, if you don't want to allow sub-directories within the configured directory:

if (!chosenDirectory.Parent.FullName.Equals(configuredDirectory.FullName,
    StringComparison.InvariantCultureIgnoreCase))
{
    throw new InvalidOperationException(
        String.Format("Invalid path {0}.", chosenDirectory));
}
著墨染雨君画夕 2024-12-17 12:19:59

这是一个快速解决方案:

string chroot = @"C:\root\child";
string requestedPath = @"..\";
string path = Path.GetFullPath(Path.Combine(chroot, requestedPath));
if (!path.StartsWith(chroot, StringComparison.Ordinal))
    throw new Exception("Oops, caught ya!");

编辑:
如果您想知道给定路径是否是有效目录:Directory.Exists(path)

Here's a quick solution:

string chroot = @"C:\root\child";
string requestedPath = @"..\";
string path = Path.GetFullPath(Path.Combine(chroot, requestedPath));
if (!path.StartsWith(chroot, StringComparison.Ordinal))
    throw new Exception("Oops, caught ya!");

edit:
If you want to know if the given path is a valid directory: Directory.Exists(path)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文