09-不要完全相信输入和环境
38.8 不要完全相信输入和环境
特权程序应该避免完全信任输入和它们所运行的环境。
不要信任环境列表
set-user-ID和set-group-ID程序不应该假设环境变量的值是可靠的,特别是PATH和IFS两个变量。
PATH确定了shell(和system() and popen())以及execlp()和execvp()在何处搜索程序。恶意用户可以改变PATH的值以欺骗set-user-ID程序使它在使用其中一个函数时会导致在拥有权限的情况下执行任意一个程序。在使用这些函数时应该将PATH值设置为一个可信的目录列表(更好的做法是在执行程序时指定绝对路径名)。但正如之前已经提过的,在执行shell或使用前面提到的函数之前最好先删除权限。
IFS指定了shell解释器用来分隔命令行中的单词的分隔符。应该将这个变量设置为任意一个空字符串,表示shell只会把空白字符当成单词分隔符。一些shell在启动的时候总是会这样设置IFS的值。(27.6节描述了老式Bourne shell中与IFS相关的一个漏洞。)
在某些情况中,特别是在执行其他程序或调用可能会受到环境变量设置影响的库时,最安全的方式是删除整个环境列表(参见6.7节),然后使用已知的安全值来还原所选中的环境变量。
防御性地处理不可信用户的输入
特权程序应该在根据来自不可信源的输入采取动作之前小心地验证这些输入。这种验证包括校验数字是否位于接受范围之内、字符串的长度是否位于接受范围之内以及是否由允许的字符构成等。需要采取此类验证措施的输入包括用户创建的文件、命令行参数、交互式输入、CGI输入、电子邮件消息、环境变量、不可信用户能够访问的进程间通信通道(FIFO、共享内存等)以及网络包。
避免对进程的运行时环境进行可靠性假设
set-user-ID程序应该避免假设其初始的运行环境是可靠的。如标准输入、输出或错误可能会被关闭。(这些描述符可能是在执行这个set-user-ID程序的程序中被关闭的。)这样,当打开一个文件时可能会无意中复用描述符1(假设),从而导致程序认为正在往标准输出中输出数据,但实际上是在往一个由其打开的文件中写入数据。
还有很多情况需要考虑。如一个进程可能会耗光各种资源限制,如能够创建的进程数限制、CPU时间资源限制或文件大小资源限制,从而导致各种系统调用会失败或各种信号的生成。恶意用户可能会故意攻击系统使得资源耗尽以便破坏程序。