当在应用程序中探查命令注入及其他缺陷时,尝试在受控制的数据中插入相关元字符后,接着在每个元字符前插入一个反斜线,测试前面描述的逻辑缺陷。
注解
一些防御跨站点脚本攻击(请参阅第12章了解相关内容)的措施中也存在这种的逻辑缺陷。将用户提交的输入直接复制到一段JavaScript脚本的字符串变量值中时,这个值包含在引号内。为防御跨站点脚本攻击,许多应用程序使用反斜线对出现在用户输入中的引号进行转义。然而,如果反斜线本身并没有转义,那么攻击者就可以提交\’破坏字符串,从而控制脚本。早先版本的Ruby On Rails 框架的escape_javascript函数中就存在这种漏洞。
笔者曾在一个电子商务站点的Web应用程序中发现这种逻辑缺陷。许多其他应用程序中也存在类似的缺陷。
1.功能
该应用程序包含一组输入确认程序,以防范各种类型的攻击。其中的两种防御机制为SQL注 入过滤和长度限制。
通常,应用程序对在基于字符串的用户输入中出现的任何单引号进行转义(并拒绝在数字输入中出现的任何单引号),以防范SQL注入。如第9章所述,两个单引号在一起将构成一个转义序列,表示一个原义单引号,数据库会将其解释为引用字符串中的数据,而不是结束字符串的终止符。因此,许多开发者认为,通过将用户提交的输入中的任何单引号配对,就可以防止SQL注入攻击。
长度限制适用于所有输入,确保用户提交的变量不会超过128个字符。如果任何变量超过128个字符,它会将其截短。
2.假设
从安全的角度来说,SQL注入过滤和长度限制都属于适当的防御机制,因此两种防御机制都应该采用。
3.攻击方法
SQL注入防御通过将用户输入中的任何引号配对而生效,因此,在每对引号中,第一个引号将作为第二个引号的转义字符。但是,开发者并没有考虑到,如果将经过转义的输入提交给“截短”功能,将会发生什么情况。
回到第9章中的登录功能SQL注入示例。假设应用程序将用户输入中的任何单引号配对,然后对该数据实施长度限制,将其截短为128个字符。如果提交以下用户名:
将导致以下无法避开登录的查询:
但是,如果提交以下用户名(包含127个a后接一个单引号):
应用程序会首先将单引号配对,然后将字符串截短为128个字符,导致输入又恢复其原始值。这时会生成数据库错误,因为在查询中注入了另外一个单引号,而没有纠正周围的语法。此时如果提交密码:
应用程序将执行以下查询,从而成功避开登录:
由a组成的字符串末尾的已配对引号将被解释为转义引号,因而被作为查询数据的一部分。这个字符串将继续有效,直到下一个单引号位置结束,而在原始的查询中,这个位置为用户提交的密码值的开始部分。这样,数据库理解的用户名为如下所示的字符串数据:
因此,之后的任何内容均被解释为查询的一部分,因而可以进行专门设计以破坏查询逻辑。