2012-04-18 160 views
6

Java有什么方法可以安全地写出临时文件吗?java等价于mkstemp

据我所知,创建临时文件(createTempFile)的唯一方法并不是实际同时打开它,因此在文件打开&文件写入之间存在争用条件。我错过了什么吗?我找不到UnixFileSystem.java中的createFileExclusively(String)背后的C源代码,但是我怀疑它是否真的可以做任何事情,因为在临时文件创建后文件打开发生在Java代码中(除非它试图用文件锁?)。

问题

创建临时文件时之间&你打开它,恶意攻击者可以解除连接的临时文件&把恶意的东西在那里。例如,攻击者可以创建一个命名管道来读取敏感数据。或者类似地,如果您最终通过阅读文件来复制文件,那么命名管道可能会忽略写入的所有内容&提供要读取的恶意内容。

我记得在过去10多年中,有很多临时文件攻击的例子,它们利用名称出现在名称空间和文件实际打开之间的竞争条件。

希望缓解因素是Java正确设置了umask,因此权限较低的用户无法读取/写入文件,通常/ tmp目录会正确限制权限,因此您无法执行取消链接攻击。

当然,如果您传递一个自定义目录用于被权限较低的特权用户拥有的临时文件,那么用户可以对您执行一个取消链接攻击。地狱,与inotify,它可能更容易利用竞争条件,而不仅仅是一个强制循环,目录列表。

+3

你能解释什么样的竞争条件存在吗? – 2012-04-18 01:20:28

+0

对此的任何更新(如在解决方法或Java7技巧中)? – 2013-11-08 12:33:14

+0

@Mr_and_Mrs_D我刚刚添加了一个实际答案。 – OrangeDog 2016-08-02 11:19:25

回答

0

请记住,在很多系统上,仅仅因为文件没有名称并不意味着它无法访问。例如,在Linux上,打开的文件描述符可在/proc/<pid>/fd/<fdno>中找到。所以你应该确保你的临时文件的使用是安全的,即使有人知道/有一个对打开文件的引用。

如果您确切指定您尝试阻止哪些类别的攻击,则可能会得到更有用的答案。

+0

但是,这通常需要提升特权,所以你不关心;如果攻击者有权查看你的内存空间(这基本上是可以访问你的内存空间的),那么你就无能为力了。他们可以访问/ proc//maps,他们甚至可以通过/ proc//mem读取/写入原始内存。 – Vitali 2012-05-05 02:33:29

0

安全针对其他普通用户的?是的,在任何功能正常的多用户系统上。

针对您自己的用户名或超级用户安全吗?第

1

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

的Java

使用java.io.File.createTempFile() - 在http://www.veracode.com/blog/2009/01/how-boring-flaws-become-interesting/

一些有趣的信息对目录有在How to create a temporary directory/folder in Java?

Java的一个有用的帖子7

用于文件使用java.io.File。createTempFile()

对目录使用createTempDirectory()

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

+0

读取的其他意见我张贴了关于为什么createTempFile不够好,比mkstemp的“金”标准(竞争条件mkstemp避免出现在createTempFile)。但是,是的,我认为没有更好的方法嵌入到Java中以在名称空间中创建文件并使用1命令打开它。 – Vitali 2012-10-25 05:44:07

+0

@Vitali - 我相信使用java.nio.file.Files(注意,如上面提到的它是不一样的类路径)方法,你想要什么createTempFile和createTempDirectory做,因为你可以指定一个文件属性参数,包括特定的原子选项包括在创建目录/文件时要设置的权限(这应该与mkstemp处理内容类似)。 参考文献: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 – 2015-12-03 00:11:50

+0

是mkstemp它打开的文件(让你知道你打开新创建的文件最关键的事情,而不是替代品)。这些Java解决方案都没有这样做。 – OrangeDog 2016-08-02 11:01:56

0

由于Java 7中,我们有OpenOption

用于配置如何打开或创建文件的对象。这种类型的

对象由诸如newOutputStreamnewByteChannelFileChannel.open,和AsynchronousFileChannel.open打开或创建文件时方法中。

特别感兴趣的是StandardOpenOptions.CREATE_NEW

创建一个新的文件,如果失败的文件已经存在。如果文件不存在,则检查文件的存在和文件的创建与其他文件系统操作有关。

所以,你可以做这样的事情:

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

实现同一模板的行为是留给读者做练习。