如何在 Java webapp 中检查空字节注入

信息安全 文件系统 注射
2021-08-21 18:24:31

看起来在 Java 应用程序中可以进行空字节注入。请参阅:Java 文件名中是否可以进行空字节注入?

那么如何防范呢?检查文件名的所有字节是否为 0(零)字节?

3个回答

正确的。如果您允许不受信任的输入影响文件名的任何部分,那么您应该应用适当的输入验证来保护自己免受攻击。您不仅需要保护自己免受空字节注入,还需要保护自己免受路径遍历和其他攻击。

我的建议是应用以下检查:

  • 确保文件名不是""(空字符串)、"."(当前目录)或".."(父目录)。

  • 确保不受信任的输入不包含任何斜杠,因为它们可用于分隔目录,因此可能会启用路径遍历攻击。为了便携和安全,我建议您检查它是否不包含File.separatorChar(目录分隔符) 或'/'('/'在 Windows 上也可用作分隔符,即使它不是) 的任何实例File.separatorChar

  • 确保路径不包含任何'\0'字符(NUL 字节),因为它们可用于安装空字节注入攻击。

  • 使用File.isFile().检查文件名是否对应于普通文件此处的目的是确保该文件不对应于特定于平台的特殊文件。

    例如,在 Windows 上,文件名PRN被保留并被特殊处理:它指的是打印机。此外,PRN全局解释:如果您访问文件\Foo\Bar\PRN,Windows 将其解释为引用打印机(并且通常PRN在每个目录中都是特殊的)。有一系列这样的Windows 保留文件您要确保攻击者没有欺骗您打开这些保留文件之一。

    请注意,File.isFile()在存在并发更新的情况下,在打开文件之前进行检查并不是原子操作。因此,如果系统上有其他进程可能同时修改文件系统并且可能受到不受信任的输入的影响,则此检查可能还不够:您可能希望显式检查路径的最后一个组件是否与任何 Windows 保留文件名。这是我知道的 Windows 保留文件名列表:CON、AUX、COM1、COM2、COM3、COM4、LPT1、LPT2、LPT3、PRN、NULL。(我怀疑这个列表可能不完整。)

如果您想查看包含此类检查的单独项目中的一些代码,尽管目的略有不同,这里有一个示例

控制应用程序的每个输入。通常最好将好的输入列入白名单,然后将坏的输入列入黑名单。(您很容易忘记列入黑名单的内容,或者发现未列入黑名单的新攻击。)所以我建议对照一些应该涵盖所有内容的正则表达式检查它可能的输入。

Java 7 更新 40(2013 年 9 月左右发布)中修复了文件名中的空字节注入。所以,它现在已经修复了一段时间,但它是一个十多年的问题,它是 Java 中的一个 NASTY 漏洞。

此处记录了该修复:JDK-8014846:java.io 中的文件和其他类无法正确处理嵌入的空值