2016-12-22 18 views
6

Tôi hiện đang điều tra một số cơ chế bảo mật liên quan đến pathTraversal và gặp phải một hành vi kỳ lạ của java.io.File.getCanonicalPath(). Tôi nghĩ CanonicalPath sẽ luôn đại diện cho con đường duy nhất thực sự của tập tin trừu tượng nằm bên dưới. Tuy nhiên, nếu tên tập tin bao gồm một trong hai dấu chấm theo sau là một không gian thì CanonicalPath dường như không đại diện cho đường dẫn chính xác nữa.Tệp Java canonicalPath với tailing '..' dẫn đến hành vi không nhất quán

Dưới đây là ví dụ:

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()+ "'"); 
} 

điều khiển Output:

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:/ 

Như bạn có thể thấy mặc dù canonicalPath của canonFile rõ ràng chỉ ra vị trí của nó trong C: \ git \, nhưng danh sách .listFiles tất cả các tệp trong C :.

Điều này chỉ xảy ra nếu tôi sử dụng hàm tạo tệp (String, String) mới. Nếu tôi thay đổi dòng thứ ba thành File concatFile = new File (root.getCanonicalPath() + relative); sau đó đầu ra là như mong đợi:

ConcatFileAbsolute: 'C:\git.. \.. ' 
ConcatFileCanonical: 'C:\git\' 
- The following output then lists files under C:\git\ 

Tôi không biết liệu hành vi này có giống nhau trên các hệ thống giống như Unix hay không.

Ai đó có thể làm rõ hành vi này? Đây có phải là mục đích không?

Cảm ơn bạn đã trả trước!

+0

Nếu bạn muốn thêm một cái gì đó cho câu hỏi của bạn, chỉnh sửa câu hỏi, mã trong các nhận xét phần lớn là không đọc được. – pvg

Trả lời

3

Xin chúc mừng! Bạn tìm thấy một lỗi có thể (hoặc tính năng?) Của WinAPI.

Cụ thể hơn, câu hỏi của bạn có thể được giảm xuống một dòng mã:

Tại sao new File("c:\\temp\\.. ").getCanonicalPath() lợi nhuận c:\temp\ thay vì c:\?

Câu trả lời ngắn gọn: vì không gian đuôi sau .. (vâng, bạn đã đề cập ở trên).

Long trả lời: nếu chúng ta sẽ nhìn vào bên trong thực hiện Java của lớp cơ bản, chúng ta sẽ thấy rằng cho Windows nó là WinNTFileSystem lớp, nơi mẹ đẻ phương pháp canonicalize0("c:\\temp\\.. ") trả về giá trị gãy này. Tại sao? Để kiểm tra nó, tôi đã viết mã VBS đơn giản để kiểm tra Win API:

Dim folderName 
folderName = "c:\temp\.. " 

Dim fso 
Set fso = CreateObject("Scripting.FileSystemObject") 

Dim fullpath 
fullpath = fso.GetAbsolutePathName(folderName) 

WScript.Echo "fullpath: " & fullpath 

Nó cung cấp cho chính xác cùng một kết quả:

fullpath: C:\temp 
+0

Có loại báo cáo lỗi nào về cuộc gọi đó không? '..' trông giống như một tên tệp, API có thể chỉ quyết định quăng nó như một tên không hợp lệ. Dù bằng cách nào không trả về 'c: \ 'thì dường như không hoàn toàn không hợp lý. – pvg

+0

Cảm ơn bạn rất nhiều. Điều này giải thích nó ít nhất là đến cấp độ hệ điều hành! Tôi đã tra cứu việc thực thi java.io.File (construtor cũng như getCanonicalPath) và bạn đã đúng. Việc thực hiện cụ thể hóa việc chuẩn hóa và giải quyết fs dường như là vấn đề. – guitarlum

Các vấn đề liên quan