2012-04-18 53 views
6

Có cách nào trong Java để ghi ra một tệp tạm thời một cách an toàn không? Theo như tôi có thể nói, cách duy nhất để tạo một tệp tạm thời (createTempFile) không thực sự mở nó cùng một lúc, do đó, có một điều kiện chủng tộc giữa tệp mở & ghi tệp. Tui bỏ lỡ điều gì vậy? Tôi không thể tìm thấy mã nguồn C đằng sau createFileExclusively (String) trong UnixFileSystem.java, nhưng tôi nghi ngờ nó có thể thực sự làm bất cứ điều gì kể từ khi mở tệp xảy ra trong mã Java sau khi tệp tạm thời được tạo (trừ khi nó cố gắng làm điều gì đó với khóa tệp?).java tương đương với mkstemp

Vấn đề

giữa khi các tập tin tạm thời được tạo & bạn mở nó, một kẻ tấn công độc hại có thể bỏ liên kết mà tập tin tạm thời & đặt thứ độc hại đó. Ví dụ, kẻ tấn công có thể tạo một đường ống có tên để đọc dữ liệu nhạy cảm. Hoặc tương tự nếu bạn cuối cùng sao chép tệp bằng cách đọc tệp, thì tên được đặt tên chỉ có thể bỏ qua mọi thứ được viết & cung cấp nội dung độc hại để đọc.

Tôi nhớ đọc rất nhiều ví dụ về các cuộc tấn công tệp tạm thời trong 10 năm qua khai thác điều kiện cuộc đua giữa khi tên xuất hiện trong không gian tên và khi tệp thực sự được mở. Hy vọng rằng một yếu tố giảm thiểu là Java đặt umask một cách chính xác vì vậy một người dùng ít đặc quyền không thể đọc/ghi vào tập tin và thường là thư mục/tmp hạn chế quyền truy cập để bạn không thể thực hiện một cuộc tấn công unlink.

Tất nhiên nếu bạn chuyển thư mục tùy chỉnh cho tệp tạm thời thuộc sở hữu của người dùng ít đặc quyền bị xâm nhập, người dùng có thể thực hiện một cuộc tấn công hủy liên kết với bạn. Địa ngục, với inotify, nó thậm chí có thể dễ dàng hơn để khai thác các điều kiện chủng tộc hơn chỉ là một vòng lặp brute force mà hiện một danh sách thư mục.

+3

Bạn có thể giải thích điều kiện chủng tộc nào tồn tại không? –

+0

Mọi cập nhật về điều này (như trong cách giải quyết hoặc thủ thuật Java7)? –

+0

@Mr_and_Mrs_D Tôi vừa thêm câu trả lời thực tế. – OrangeDog

Trả lời

0

Hãy nhớ rằng trên nhiều hệ thống, chỉ vì một tệp không có tên không có nghĩa là nó không thể truy cập được. Ví dụ, trên Linux mô tả tập tin mở có sẵn trong /proc/<pid>/fd/<fdno>. Vì vậy, bạn nên đảm bảo rằng việc sử dụng tệp tạm thời của bạn là an toàn ngay cả khi ai đó biết/có tham chiếu đến tệp đang mở.

Bạn có thể nhận được câu trả lời hữu ích hơn nếu bạn chỉ định chính xác các lớp tấn công bạn đang cố gắng ngăn chặn.

+0

Nhưng điều đó thường đòi hỏi đặc quyền nâng cao, vì vậy bạn không quan tâm; nếu kẻ tấn công có quyền truy cập vào không gian bộ nhớ của bạn (mà về bản chất là những gì có thể truy cập vào fds của bạn), thì không có gì bạn có thể làm. Họ có thể truy cập/proc//maps và thậm chí họ có thể đọc/ghi bộ nhớ của bạn qua/proc//mem. – Vitali

0

Bảo mật chống lại người dùng thông thường khác? Có, trên bất kỳ hệ thống đa người dùng hoạt động đúng cách nào.

Bảo mật chống lại userid của riêng bạn hoặc superuser? Số

1

http://kurt.seifried.org/2012/03/14/creating-temporary-files-securely/

Java

sử dụng java.io.File.createTempFile() - một số thông tin thú vị tại http://www.veracode.com/blog/2009/01/how-boring-flaws-become-interesting/

cho các thư mục có một bài viết hữu ích tại How to create a temporary directory/folder in Java?

Java 7

cho tệp sử dụng java.io.File.createTempFile()

cho thư mục sử dụng createTempDirectory()

http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html

+0

đọc các ý kiến ​​khác tôi đăng về lý do tại sao createTempFile không đủ tốt so với tiêu chuẩn "vàng" của mkstemp (điều kiện chủng tộc mkstemp tránh hiện diện trong createTempFile). Nhưng có, tôi không nghĩ rằng có một cách tốt hơn được xây dựng trong Java để tạo ra một tập tin trong không gian tên & mở nó trong 1 lệnh. – Vitali

+0

@Vitali - Tôi tin rằng sử dụng java.nio.file.Files (lưu ý rằng nó không phải là cùng một lớp đường dẫn như đã đề cập ở trên) phương thức createTempFile và createTempDirectory làm những gì bạn muốn, bởi vì bạn có thể chỉ định tham số File Attribute bao gồm các tùy chọn nguyên tử cụ thể , bao gồm các quyền được đặt khi tạo thư mục/tệp (tương tự như cách mkstemp xử lý mọi thứ). Tham khảo: https://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#createTempFile | https://docs.oracle.com/javase/7/docs/api/java/nio/file/attribute/FileAttribute.html –

+0

Điều quan trọng mà mkstemp hiện nó mở tập tin (để bạn biết bạn đã mở tập tin mới được tạo ra và không phải thay thế). Không có giải pháp Java nào làm được điều đó. – OrangeDog

0

Kể từ Java 7 chúng tôi có OpenOption.

Một đối tượng định cấu hình cách mở hoặc tạo tệp.

Đối tượng thuộc loại này được sử dụng bằng các phương pháp như newOutputStream, newByteChannel, FileChannel.openAsynchronousFileChannel.open khi mở hoặc tạo tệp.

Sở thích cụ thể là StandardOpenOptions.CREATE_NEW.

Tạo tệp mới, không thành công nếu tệp đã tồn tại. Kiểm tra sự tồn tại của tệp và tạo tệp nếu nó không tồn tại là nguyên tử đối với các hoạt động hệ thống tệp khác.

Vì vậy, bạn có thể làm một cái gì đó như thế này:

FileChannel mkstemp() { 
    Path path = Files.createTempFile(null, null); 
    Files.delete(path); 
    return FileChannel.open(path, WRITE, CREATE_NEW); 
} 

Thực hiện cùng một mẫu hành vi là trái như tập thể dục cho người đọc.

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