21.7 测试基于输入的漏洞

许多重要的漏洞由无法预测的用户输入触发,并可能出现在应用程序的任何位置。用一组攻击字符串模糊测试每个请求的每一个参数,是在应用程序中探查这种漏洞的有效方法。

img628

图21-8 测试基于输入的漏洞

21.7.1 模糊测试所有请求参数

(1)检查应用程序解析过程中获得的结果,确定所有提交由服务器端应用程序处理的参数的特殊客户端请求。相关参数分别位于URL查询字符串、请求主体及HTTP cookie中。它们还包括所有给应用程序行为造成影响的用户提交的数据,如Referer或User-Agent消息头。

(2)要对这些参数进行模糊测试,可以使用自己的脚本,或者现成的模糊测试工具。例如,如果使用Burp Intruder,可轮流在工具中加载每一个请求。一个简单的方法是在Burp Proxy中拦截一个请求,然后选择“发送至Intruder”操作;或者在Burp Proxy历史记录中单击一个请求,再选择 这个选项。使用这个选项将在Burp Intruder中配置请求的内容、正确的目标主机和端口,然后Burp Intruder自动将所有请求参数的值标记为有效载荷位置,准备进行模糊测试。

(3)使用“有效载荷”选项卡,配置一组适当的攻击有效载荷,在应用程序中探查漏洞。可以手动输入有效载荷,从一个文件中加载它们,或者选择一个预先设定的有效载荷列表。模糊测试应用程序中的第一个请求参数往往需要发布数目庞大的请求,并在结果中查找反常现象。如果设定的攻击字符串过多,这样反而达不到预期的目标,甚至生成无数的输入,以致很难对其进行分析。因此,较为明智的做法是,测试一系列可在特定的专门设计的输入的反常响应中轻易确定的常见漏洞,以及出现在应用程序的所有位置而非某些特殊功能中的漏洞。可以使用以下一组有效载荷测试一些常见的漏洞。

img007 SQL注入

img629a

img007 XSS 与消息头注入

img629b

img007 OS 命令注入

img629c

img007 路径遍历

img629d

img007 脚本注入

img629e

img007 文件包含

img629f

(4)前面所有的有效载荷均以字面量形式显示,?、;、&、+ 空格与=字符因为在HTTP请求中有特殊含义,需要进行URL编码。默认情况下,Burp Intruder会对这些字符进行必要的编码,因 此,必须确保该选项没有被禁用。(如果想要在定制后将所有选项恢复到它们的默认值,可从Burp菜单中选择“恢复默认值”选项。)

(5)在Burp Intruder的Grep功能中,配置一组合适的字符串,标记响应中的一些常见的错误消息。例如:

img630

请注意,其中的字符串111111用于测试成功的脚本注入攻击;21.7.1节第3步中的有效载荷要求将这个值写入服务器的响应中。

(6)同时,选择“有效载荷Grep”选项,标记包含有效载荷自身的响应,该响应表示可能存在XSS或消息头注入漏洞。

(7)在通过第一个文件包含有效载荷指定的主机上建立一个Web服务器或netcat监听器,监控服务器由于远程文件包含攻击而发出的连接尝试。

(8)实施并完成攻击后,在结果中查找表示存在漏洞的反常响应。检查HTTP状态码、响应长度、响应时间、其中是否出现配置的表达式以及是否出现有效载荷本身。可以单击结果表的每一个列标题,对列中的值进行分类(按下Shift键的同时单击鼠标可对结果进行反向排序),这样做可迅速确定所有不同于其他结果的反常响应。

(9)参考本章后文对每一类问题的详细描述,对模糊测试结果表明可能存在的每一个潜在的漏洞进行确认,同时考虑如何成功地利用这些漏洞。

(10)一旦配置Burp Intruder对某个请求进行模糊测试后,就可以迅速地对应用程序中的其他请求进行相同的测试。在Burp Proxy中选定目标请求,再选择“发送至Intruder”选项,就可以立即使用现有的测试选项在Intruder中进行测试。这样,就可以同时在单独的窗口中进行大量测试,在测试完成后手动检查测试结果。

(11)如果在解析应用程序的过程中确定了带外输入通道,可通过它们向应用程序提交用户可控制的输入。渗透测试员应当通过提交各种旨在触发常见的Web应用程序漏洞的专门设计的数据,对这些输入通道进行类似的模糊漏洞。根据输入通道的特点,可能需要建立一个定制脚本或其他工具。

(12)除了手动对应用程序请求进行模糊测试外,如果拥有一个自动化Web应用程序漏洞扫描 器,还应当运行该扫描器,对目标应用程序进行自动测试,并比较两方面的测试结果。

21.7.2 测试SQL注入

(1)如果发现21.7.1节第3步中列出的SQL攻击字符串导致任何反常响应,那么应该手动探查,观察应用程序如何处理相关参数,确定其中是否存在SQL注入漏洞。

(2)如果提交上述字符串返回错误消息,分析这些消息的意义。可以根据9.2.13节提供的信息了解错误消息在常用数据库平台中的含义。

(3)如果在请求中提交一个单引号导致错误或出现其他反常行为,可尝试提交两个单引号;如果这种输入使错误或异常行为消失,应用程序可能易于受到SQL注入。

(4)设法使用常用的SQL字符串连接符函数构建一个等同于良性输入的字符串。如果提交这个字符串得到与提交原始的良性输入相同的响应,那么应用程序可能易于受到攻击。例如,如果原始输入为表达式FOO,可以使用下面的输入测试:

img631a

同样,应对在HTTP请求中具有特殊意义的字符(如+和空格)进行URL编码。

(5)如果原始输入为数字字符,尝试使用一个其结果等于原始值的数学表达式。例如,如果原始值为2,尝试提交1+1或3-1。如果应用程序做出相同的响应,表示它易于受到攻击;如果数字表达式的值对应用程序的行为造成系统性的影响,那么应用程序就特别容易受到攻击。

(6)如果前面的测试取得成功,可以通过使用针对SQL的数学表达式构造一个特殊的值,进一步确定SQL注入漏洞是否存在。如果可以通过这种方式系统性地控制应用程序的逻辑,那么几乎可以肯定应用程序易于受到SQL注入攻击。例如,下面两个表达式的结果都等于2:

img631b

(7)如果使用waitfor命令进行的模糊漏洞测试导致应用程序在进行响应时出现反常的时间延迟,那么所使用的数据库为MS-SQL,且应用程序易于受到SQL注入攻击。手动重复测试,在waitfor参数中指定不同的值,确定响应时间是否随着这个值而发生系统性的变化。请注意,可以在几个SQL查询中插入攻击有效载荷;这时观察到的时间延迟为指定值的固定倍数。

(8)如果应用程序易于受到SQL注入攻击,渗透测试员要考虑可以实施哪些攻击,以及如何利用它们实现自己的目的。请参考第9章了解实施以下攻击的详细步骤。

img002 修改WHERE子句中的条件,改变应用程序的逻辑(例如,注入or 1=1--避开登录)。

img002 使用UNION操作符注入任意一个SELECT查询,将它的结果与应用程序的原始查询的结果组合在一起。

img002 使用针对数据库的SQL语法“指纹标识”数据库类型。

img002 如果使用的数据库为MS-SQL,且应用程序在响应中返回ODBC错误消息,利用这些信息枚举数据库结构,获取任意数据。

img002 如果无法获得一个任意输入的查询的结果,可以使用以下攻击技巧提取数据。

img006 获取数字格式的字符串数据,一次一个字节。

img006 使用带外通道。

img006 如果能够根据任意一个条件引发不同的应用程序响应,可使用Absinthe提取任意数据,一次一比特。

img006 如果能够根据一个任意的条件触发时间延迟,利用它们获取数据,一次一比特。

img002 如果应用程序阻止实施特殊攻击所需的某些字符或表达式,尝试使用第9章描述的各种技巧避开输入过滤。

img002 如有可能,利用漏洞或强大的数据库函数,将攻击范围扩大到数据库与基础服务器中。

21.7.3 测试XSS和其他响应注入

1.确定反射型请求参数

(1)单击“有效载荷Grep”列,分类模糊漏洞测试的结果,确定任何与21.7.1节第3步中列出的XSS有效载荷相匹配的字符串。这些是在应用程序响应中按原样返回的XSS测试字符串。

(2)对于上述每一个字符串,检查应用程序的响应,查找用户提交的输入的位置。如果该字符串出现在响应主体中,应测试应用程序中是否存在XSS漏洞。如果它出现在HTTP消息头中,应测试应用程序中是否存在消息头注入漏洞。如果它被用在302响应的Location消息头中,或者用于以某种方式指定重定向,应测试应用程序中是否存在重定向漏洞。请注意,同一个输入可能会被复制到响应中的几个位置,因此应用程序中可能存在几种类型的反射型漏洞。

2.测试反射型XSS

(1)对于在响应主体中出现的所有请求参数,检查它周围的HTML代码,确定是否可以提交专门设计的输入,从而执行任意JavaScript脚本。例如,通过注入<script>标签,注入一段现有代码,或在一个标签属性中插入精心设计的值,执行任意JavaScript脚本。

(2)将第12章讲述的攻破签名过滤器的各种方法作为参考,了解如何利用专门设计的输入执行任意JavaScript脚本。

(3)尝试向应用程序提交各种可能的输入,监控它的响应,确定应用程序是否对输入进行任何过滤或净化。如果攻击字符串被原样返回,使用浏览器确认成功执行了任意JavaScript脚本(例如,通过生成一个警报对话框)。

(4)如果发现应用程序阻止需要使用的某些字符串或表达式,或者对某些字符进行URL编码,尝试使用第12章描述的各种技巧避开过滤。

(5)如果在一个POST请求中发现了XSS漏洞,仍然可以通过一个包含表单的恶意Web站点,由必要的请求参数和一段脚本自动提交该表单,对这个漏洞加以利用。但是,如果可以通过GET请求利用漏洞,就可以使用大量的攻击传送机制。尝试在GET请求中提交相同的参数,看攻击是否仍然取得成功。可以使用Burp Proxy的“改变请求命令”(Change Request Method)操作转换请求类型。

3.测试HTTP消息头注入

(1)对于在响应消息头中出现的每一个请求参数,确认应用程序是否接受URL编码的回车(%0d)与换行(%0a)符,以及它们是否按原样在响应中返回。请注意,在服务器的响应中寻找的是换行符本身,而不是它们的URL编码形式。

(2)如果在提交专门设计的输入后,服务器的响应消息头新增了一行,那么应用程序易受HTTP消息头注入攻击。如第13章所述,攻击者可以利用这种漏洞实施各种攻击。

(3)如果服务器的响应中仅返回两个换行符中的一个,根据实际情况,仍可以设计出有效的攻击方法。

(4)如果发现应用程序阻止包含换行符的输入,或者净化出现在响应中的这些字符,尝试使用下面的输入测试过滤的效率:

img633a

4.测试任意重定向

(1)如果反射型输入用于指定某类重定向的目标,测试是否可以提交专门设计的输入,生成指向一个外部Web站点的任意重定向。如果可以,渗透测试员就可以利用这种行为提高钓鱼攻击的可信度。

(2)如果应用程序以参数值的形式传送绝对URL,那么修改URL中的域名,测试应用程序是否重定向到不同的域。

(3)如果参数中包含一个相对URL,将这个URL修改成指向另一个域的绝对URL,并测试应用程序是否重定向到这个域。

(4)如果应用程序为防止外部重定向,在进行重定向前对参数进行某种形式的确认,通常仍然可以轻易避开这种确认。尝试使用第13章描述的各种攻击测试过滤的效率。

5.测试保存型攻击

(1)如果应用程序保存用户提交的输入,并随后在屏幕上显示这些输入,那么,在模糊测试整个应用程序后,可能会发现攻击字符串在本身并未包含这些字符串的请求的响应中返回。留意这种情况,确定被保存数据的原始进入点。

(2)有时,只有完成一个多阶段过程,用户提交的数据才被成功保存。如果在应用程序解析过程中确定这种功能,那么手动完成相关过程,并在被保存的数据中查找XSS漏洞。

(3)如果拥有足够的访问权限,应仔细审查可在更高权限的用户会话中显示低权限用户的数据管理功能。管理功能中存在的任何保存型XSS漏洞往往会直接导致权限提升。

(4)测试用户提交的数据被保存且向该用户显示的每一种情况。测试这些情况,从中查找上述XSS和其他响应注入漏洞。

(5)如果发现一个漏洞将一名用户提交的输入显示给其他用户,渗透测试员要确定可用于实现目标的最佳攻击有效载荷,如会话劫持或请求伪造。如果被保存的数据仅向提交该数据的用户显示,那么设法找出办法,链接已经发现的所有漏洞(如不完善的访问控制),从而在其他用户 的会话中注入一个攻击。

(6)如果应用程序允许文件上传与下载,应始终探查这种功能是否易于受到保存型XSS攻击。如果应用程序允许HTML. JAR或文本文件,且并不确认或净化它们的内容,那么几乎可以肯定它们易于受到攻击。如果它允许JPEG文件且并不确认其中是否包含有效的图像,那么它可能易于受到针对Internet Explorer 用户的攻击。测试应用程序如何处理它支持的每种文件类型,并弄清浏览器如何处理包含HTML而非正常内容的响应。

(7)在一名用户提交的数据被显示给其他用户的每一个位置,如果应用程序实施的过滤阻止发动保存型XSS攻击,确定应用程序的行为是否使它易于受到本站点请求伪造攻击。

21.7.4 测试OS命令注入

(1)如果在21.7.1节第3步中列出的任何命令注入攻击字符串导致应用程序在做出响应时出现反常的时间延迟,那么应用程序易于受到OS命令注入攻击。手动重复进行测试,在-i或-n参数中指定不同的值,确定响应时间是否随着这个值而发生系统性的变化。

(2)使用所发现的任何一个可成功实施攻击的注入字符串,尝试注入另一个更加有用的命令(如ls或dir),确定是否能够将命令结果返回到浏览器上。

(3)如果不能直接获得命令执行结果,还可以采用其他方法。

img002 可以尝试打开一条通向自己计算机的带外通道。尝试使用TFTP上传工具至服务器,使用telnet或netcat建立一个通向自己计算机的反向shell,并使用mail命令通过SMTP发送命令结果。

img002 可以将命令结果重定向到Web根目录下的一个文件,然后使用自己的浏览器直接获取结果。例如:

img634a

(4)一旦找到注入命令的方法并能够获得命令执行结果,就应当确定自己的权限(通过使用whoami或类似命令,或者尝试向一个受保护的目录写入一个无害文件)。然后就可以设法提升自己的权限,进而秘密访问应用程序中的敏感数据,或者通过被攻破的服务器测试其他主机。

(5)如果知道自己的输入被提交给某个OS命令,但提交前面列出的攻击字符串无法成功实施攻击,那么观察是否可以使用<或>字符将一个文件的内容指向命令的输入,或者将命令的输出指向一个文件。可以使用这种方法读取或写入任意文件的内容。如果知道或能够猜测出被执行的命令,尝试注入与该命令有关的命令行参数,以有利的方式修改它的行为(例如,指定Web根目录中的输入文件)。

(6)如果发现应用程序对实施命令注入所需的某些字符进行转义,可尝试在这些字符串中插入转义字符。如果应用程序并不对转义字符本身进行转义,就可以利用这种行为避开应用程序的防御机制。如果发现空白符被阻止或净化,就可以使用$IFS替代在UNIX平台中出现的空格。

21.7.5 测试路径遍历

(1)对于执行的每次模糊测试,检查在21.7.1节第3步中列出的路径遍历攻击字符串生成的结果。可以在Burp Intruder中单击有效载荷列的顶部,按有效载荷对结果表进行分类,从而将这些字符串生成的结果分组。如果收到一个不常见的错误消息,或者长度不正常的响应,手动检查响应,确定其中是否包含特定文件的内容或其他表示执行了反常文件操作的证据。

(2)在解析应用程序的受攻击面的过程中,应该已经注意到了一些专用的功能,使用它们可根据用户提交的输入读取和写入文件。除了对所有参数进行模糊测试外,还应极其仔细地手动测试这项功能,确定所有路径遍历漏洞。

(3)如果某个参数中包含一个文件名、文件名的一部分或一个目录,修改这个参数的值,并在其中插入任意一个子目录和一个遍历序列。例如,如果应用程序提交参数:

img635a

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

img635b

如果两种情况下应用程序的行为完全相同,那么它易于受到攻击,渗透测试员应该继续以下步骤。如果在上述两种情况下应用程序的行为有所不同,那么应用程序可能阻止、删除或净化遍历序列,致使文件路径失效。尝试使用第10章描述的编码与其他攻击避开过滤。

(4)如果前面在基础目录中使用遍历序列的测试取得成功,尝试使用其他序列上溯到基础目录,并访问服务器操作系统中的已知文件。如果这些尝试失败,应用程序可能在许可文件访问前实施了各种过滤或检查,应当进行深入分析,了解应用程序实施的控制以及是否可以避开这些控制。

(5)应用程序可能会检查被请求的文件扩展名,只允许用户访问特殊类型的文件。尝试使用空字节或换行符攻击,并在后面连接已知的、应用程序接受的文件扩展名,设法避开过滤。例如:

img635c

(6)应用程序可能会检查用户提交的文件路径是否以一个特定的文件名或词根开头。尝试将遍历序列附加在一个已知应用程序接受的词根后面,避开过滤。例如:

img635d

(7)如果这些攻击无法取得成功,尝试组合使用几种测试技巧,首先对基础目录进行全面的测试,了解应用程序实施的过滤以及它如何处理无法预料的输入。

(8)如果能够读取服务器上的任意文件,尝试获取以下任何一个文件,进而扩大攻击范围。

img002 操作系统与应用程序的密码文件。

img002 服务器与应用程序配置文件,发现其他漏洞或优化另一次攻击。

img002 可能含有数据库证书的包含文件。

img002 应用程序使用的数据源,如MySQL数据库文件或XML文件。

img002 服务器可执行页面的源代码,以执行搜索漏洞的代码审查。

img002 可能包含用户名和会话令牌的应用程序日志文件等。

(9)如果能够写入服务器上的任意文件,分析是否可以实施以下攻击,进而扩大攻击范围。

img002 在用户的启动文件夹中创建脚本。

img002 当用户下一次连接时,修改in.ftpd等文件执行任意命令。

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

21.7.6 测试脚本注入

(1)对于执行的每一次模糊测试,在测试结果中搜索字符串111111本身(即它前面没有其他测试字符串)。在Burp Intruder中,按住Shift键的同时单击111111 Grep字符串标题,对所有包含这个字符串的结果进行分类,即可迅速确定这些字符串。确定的任何结果都可能易于受到脚本命令注入攻击。

(2)检查使用脚本注入字符串的所有测试,确定所有包含脚本错误消息的测试;这些错误消息表示输入被执行,但造成一个错误,因而可能需要对测试进行优化,以成功实施脚本注入。

(3)如果应用程序似乎易于受到攻击,通过注入其他专门针对应用程序所使用的脚本平台的命令,确认漏洞是否存在。例如,可以使用类似于模糊测试OS命令注入时使用的攻击有效载荷:

img636a

21.7.7 测试文件包含

(1)如果在模糊测试时收到任何由目标应用程序的基础架构提出的HTTP连接,那么几乎可以肯定应用程序易于受到远程文件包含攻击。以单线程的方式在有限的时间内重复相关测试,确定到底是哪些参数致使应用程序提出HTTP请求。

(2)检查文件包含测试结果,确定在应用程序的响应中造成反常延迟的所有测试。在这些情况下,可能应用程序本身易于受到攻击,但HTTP请求可能因为网络级过滤而超时。

(3)如果发现一个远程文件包含漏洞,部署一台包含恶意脚本(专门针对所攻击的语言而编写)的Web服务器,使用和测试脚本注入类似的命令确定脚本是否被执行。