在某些情况下,文件名可能会导致严重问题。对于在具有本地不受信任用户的计算机上运行的安全程序来说,这尤其是一个问题,但这不仅限于这种情况。远程用户可能能够诱骗程序创建不良的文件名(程序应该阻止这种情况,但并非所有程序都这样做),或者远程用户可能已经部分渗透到系统,并尝试使用此技巧来渗透系统的其余部分。
通常,您不希望将 ``..''(上级目录)作为来自不受信任用户的合法值包含在内,但这取决于具体情况。您可能还希望仅列出您允许的字符,并禁止任何与列表不匹配的文件名。如果您要从外部用户获取数据并将其转换为文件名,则最好禁止任何目录更改,例如,通过不将 ``/'' 包含在合法字符集中。
通常,您不应该支持“globbing”,即使用 ``*``、``?``、``[''(匹配 ``]'')以及可能的 ``{''(匹配 ``}'')扩展文件名。例如,命令 ``ls *.png`` 对 ``*.png`` 执行 glob 操作以列出所有 PNG 文件。例如,C fopen(3) 命令不执行 globbing,但命令 shell 默认执行 globbing,而在 C 中,您可以使用(例如)glob(3) 请求 globbing。如果您不需要 globbing,只需尽可能使用不执行 globbing 的调用(例如,fopen(3))和/或禁用它们(例如,转义 shell 中的 globbing 字符)。如果您想允许 globbing,请格外小心。Globbing 可能很有用,但复杂的 glob 可能需要大量的计算时间。例如,在某些 ftp 服务器上,执行其中一些请求很容易导致整个机器的拒绝服务
ftp> ls */../*/../*/../*/../*/../*/../*/../*/../*/../*/../*/../*/../* |
类 Unix 系统通常禁止在文件名中包含 NIL 字符(因为这标记名称的结尾)和 '/' 字符(因为这是目录分隔符)。但是,它们通常允许其他任何字符,这是一个问题;很容易编写出会被巧妙创建的文件名破坏的程序。
尤其可能导致问题的文件名包括
带有前导破折号 (-) 的文件名。如果传递给其他程序,这可能会导致其他程序将名称误解为选项设置。理想情况下,类 Unix 系统不应允许这些文件名;它们是不需要的,并且会造成许多不必要的安全问题。不幸的是,目前开发人员必须处理它们。因此,每当使用文件名调用另一个程序时,请在文件名参数之前插入 ``--``(以停止选项处理,如果程序支持此常用请求)或修改文件名(例如,在文件名之前插入 ``./`` 以防止破折号成为前导字符)。
带有控制字符的文件名。这尤其包括换行符和回车符(它们在 shell 脚本中经常被误认为是参数分隔符,或者可以将日志条目拆分为多个条目)以及 ESCAPE 字符(它可能会干扰终端模拟器,导致它们执行用户控制之外的不必要操作)。理想情况下,类 Unix 系统也不应允许这些文件名;它们是不需要的,并且会造成许多不必要的安全问题。
带有空格的文件名;这些有时会使 shell 误认为是多个参数,而其他参数会导致问题。由于其他操作系统允许文件名中包含空格(包括 Windows 和 MacOS),为了互操作性,这可能总是被允许的。请小心处理它们,例如,在 shell 中,在调用另一个程序时,在所有文件名参数周围使用双引号。您可能至少想禁止前导和尾随空格;这些不如在其他位置出现时那么明显,并且可能会使人类用户感到困惑。
无效的字符编码。例如,程序可能认为文件名是 UTF-8 编码的,但它可能具有无效的过长 UTF-8 编码。有关更多信息,请参阅第 5.9.2 节。我希望看到就文件名使用的字符编码(例如,UTF-8)达成一致,然后让操作系统强制执行编码(以便只允许合法的编码),但这目前尚未发生。
其他对内部数据格式特殊的字符,例如 ``<``、``;``、引号字符、反斜杠等等。