gui*_*lum 6 java nio canonical-link
我正在调查一些与pathTraversal相关的安全机制,并遇到了java.io.File.getCanonicalPath()的奇怪行为.我认为CanonicalPath将始终代表抽象底层文件的真正唯一路径.但是,如果文件名包含两个点后跟一个空格,则CanonicalPath似乎不再代表正确的路径.
这是一个例子:
File root = new File("c:/git/");
String relative = ".. /.. \\";
File concatFile = new File (root.getCanonicalPath(), relative);
System.out.println("ConcatFileAbsolute: '" + concatFile.getAbsolutePath() + "'");
System.out.println("ConcatFileCanonical: '" + concatFile.getCanonicalPath() + "'");
File canonFile = new File(concatFile.getCanonicalPath());
System.out.println("\ncanonFileCanonical: '" + canonFile.getCanonicalPath() + "'");
System.out.println("canonFileAbsolute: '" + canonFile.getAbsolutePath() + "'");
System.out.println("canonFileName: '" + canonFile.getName() + "'\n");
for (File file : canonFile.listFiles()) {
System.out.println("canon: '" + file.getCanonicalPath() + "' - absolute: '" + file.getAbsolutePath()+ "'");
}
Run Code Online (Sandbox Code Playgroud)
控制台输出:
ConcatFileAbsolute: 'C:\git\.. \.. '
ConcatFileCanonical: 'C:\git\.. \'
canonFileCanonical: 'C:\git\'
canonFileAbsolute: 'C:\git\.. '
canonFileName: '.. '
canon: 'C:\git\.. \$Recycle.Bin' - absolute: 'C:\git\.. \$Recycle.Bin'
canon: 'C:\git\.. \.m2' - absolute: 'C:\git\.. \.m2'
canon: 'C:\git\.. \boot' - absolute: 'C:\git\.. \boot'
...other content of C:/
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,尽管canonFile的canonicalPath清楚地表明了它在C:\ git \中的位置,但.listFiles列出了C:中的所有文件.
只有在我使用新的File(String,String)构造函数时才会发生这种情况.如果我将第三行更改为File concatFile = new File(root.getCanonicalPath()+ relative); 然后输出符合预期:
ConcatFileAbsolute: 'C:\git.. \.. '
ConcatFileCanonical: 'C:\git\'
- The following output then lists files under C:\git\
Run Code Online (Sandbox Code Playgroud)
我不知道在unix类系统上这种行为是否类似.
有人可以澄清这种行为吗?这是有意的吗?
先谢谢!
恭喜!您发现了 WinAPI 的一个可能的错误(或功能?)。
更具体地说,您的问题可以简化为一行代码:
为什么new File("c:\\temp\\.. ").getCanonicalPath()返回c:\temp\而不是c:\?
简短的回答:因为后面有尾部空间..(是的,你在上面提到过)。
长答案:如果我们查看底层类的 Java 实现,我们会发现对于 Windows 来说它是WinNTFileSystem类,其中本机方法canonicalize0("c:\\temp\\.. ")返回这个损坏的值。为什么?为了测试它,我编写了简单的 VBS 代码来测试 Win API:
Dim folderName
folderName = "c:\temp\.. "
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Dim fullpath
fullpath = fso.GetAbsolutePathName(folderName)
WScript.Echo "fullpath: " & fullpath
Run Code Online (Sandbox Code Playgroud)
它给出了完全相同的结果:
fullpath: C:\temp
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
115 次 |
| 最近记录: |