Web应用程序中的许多功能通常都需要处理用户以文件或目录名提交的输入。一般情况下,这些输入会传递给接受文件路径的API(例如,用于检索本地文件系统中的文件)。应用程序将在它对用户请求的响应中处理该API调用的结果。如果用户提交的输入未经过正确确认,这种行为就可能导致各种安全漏洞,其中最常见的是文件路径遍历漏洞和文件包含漏洞。
如果应用程序使用用户可控制的数据、以危险的方式访问位于应用程序服务器或其他后端文件系统中的文件和目录,就会出现路径遍历漏洞。通过提交专门设计的输入,攻击者就可以在被访问的文件系统中读取或者写入任意内容。这种漏洞往往使攻击者能够从服务器上读取敏感信息或者重写敏感文件,并最终在服务器上执行任何命令。
在下面的示例中,应用程序使用一个动态页面向客户端返回静态图像。被请求图像的名称在查询字符串参数中指定:
当服务器处理这个请求时,它执行以下操作。
(1)从查询字符串中提取filename参数值。
(2)将这个值附加在C:\filestore\之后。
(3)用这个名称打开文件。
(4)读取文件的内容并将其返回给客户端。
漏洞之所以会发生,是因为攻击者可以将路径遍历序列(path traversal sequence)放入文件名内,从第(2)步指定的图像目录向上回溯,从而访问服务器上的任何文件。众所周知,路径遍历序列表示为“点—点—斜线”(..\),一个典型的攻击如下:
如果应用程序把filename参数的值附加到图像目录名称之后,就得到以下路径:
这两个遍历序列立即从图像目录回溯到C:驱动器根目录下,因此前面的路径等同于以下路径:
因此,服务器不会返回图像文件,而是返回默认的Windows配置文件。
注解
在旧版Windows IIS Web服务器中,默认情况下,应用程序将在本地系统权限下运行,因而能够访问本地文件系统上的任何可读文件。在较新的版本中,和许多其他Web服务器一样,服务器进程默认以权限较低的用户账户运行。因此,在探查路径遍历漏洞时,最好是请求一个可由任何类型的用户读取的默认文件,如c:\windows\win.ini。
在这个简单的示例中,应用程序并未实施防御,阻止路径遍历攻击。然而,由于这些攻击早已广为人知,应用程序通常会针对它们实施各种防御,大多数情况下是采取输入确认过滤。在后文中会讲到,这些过滤往往并不可靠,可被技术熟练的攻击者轻易避开。