注入攻击的本质,是把用户输入的数据当做代码执行。这里有两个关键条件,第一个是用户能够控制输入;第二个是原本程序要执行的代码,拼接了用户输入的数据。
SQL注入
在SQL注入的过程中,如果网站的Web服务器开启了错误回显,则会为攻击者提供极大的便利,比如攻击者在参数中输入一个单引号“ ‘ ”,引起执行查询语句的语法错误,服务器直接返回了错误信息。
错误回显披露了敏感信息,对于攻击者来说,构造SQL注入的语句就可以更加得心应手了。
盲注(Blind Injection)
所谓“盲注”,就是在服务器没有错误回显时完成的注入攻击。
最常见的盲注验证方法是,构造简单的条件语句,根据返回页面是否发生变化,来判断SQL语句是否得到执行。
服务器虽然关闭了错误回显,但是攻击者通过简单的条件判断,再对比页面返回结果的差异,就可以判断出SQL注入漏洞是否存在。
Timing Attack
在MySQL中,有一个BENCHMARK()函数,它是用于测试函数性能的。它有两个参数:
BENCHMARK(count, expr)
函数执行的结果,是将表达式expr执行count次。
利用BENCHMARK()函数,可以让同一个函数执行若干次,使得结果返回的时间比平时要长;通过时间长短的变化,可以判断出注入语句是否执行成功。这是一种边信道攻击,这个技巧在盲注中被称为Timing Attack。
数据库攻击技巧
常见的攻击技巧
SQL注入可以猜解出数据库的对应版本,确认表名和列名是否存在,甚至通过判断字符的范围猜出列名的具体的值。有一些自动化工具来帮助完成整个过程。
命令执行
在MySQL中,可以利用“用户自定义函数”的技巧,即UDF(User-Defined Function)来执行命令。
在流行的数据库中,一般都支持从本地文件系统中导入一个共享库文件作为自定义函数。
一般来说,在数据库中执行系统命令,要求具有较高的权限。在数据库加固时,可以参阅官方文档给出的安全指导文档。
在建立数据库账户时应该遵循“最小权限原则”,尽量避免给Web应用使用数据库的管理员权限。
攻击存储过程
在MS SQL Server和Oracle数据库中,都有大量内置的存储过程。在注入攻击的过程中,存储过程将为攻击者提供很大的便利。
除了利用存储过程直接攻击外,存储过程本身也可能会存在注入漏洞。比如:一个存储过程中的变量是由外部传入的,且未经过任何处理,将直接造成SQL注入问题。在Oracle数据库中,由于内置的存储过程非常多,很多存储过程都可能存在SQL注入问题,需要特别引起注意。
编码问题
在有些时候,不同的字符编码也可能会导致一些安全问题。在注入的历史上,曾经出现过“基于字符集”的注入攻击技巧。
在进入数据库之前,在Web语言中则没有考虑到双字节字符的问题,双字节字符会被认为是两个字节。当数据库使用了“宽字符集”时,可能会产生一些意想不到的漏洞。比如,当MySQL使用了GBK编码时,0xbf27和0xbf5c都会被认为是一个字符(双字节字符)。
要解决这种问题,需要统一数据库、操作系统、Web应用所使用的字符集,以避免各层对字符的理解存在差异,统一设置为UTF-8是一个很好的方法。
SQL Column Truncation
在MySQL的配置选项中,有一个名为“SQL Column Truncation”的攻击方式,在某些情况下,即没有开启STRICT_ALL_TABLES选项时,MySQL对于用户插入的超长值只会提示warning,而不是error(如果是error则插入不成功),这可能会导致发生一些“截断”问题。
正确地防御SQL注入
(1)找到所有的SQL注入漏洞
(2)修补这些漏洞
使用预编译语句
防御SQL注入的最佳方式。在SQL语句中,变量用?表示,攻击者无法改变SQL的结构。
使用存储过程
使用安全的存储过程对抗SQL注入,尽量避免在存储过程中使用动态的SQL语句。如果无法避免,则应该使用严格的输入过滤或者是编码函数来处理用户的输入数据。
检查数据类型
限制输入数据的类型,数据格式和类型检查。
使用安全函数
如果有多个不同的应用在使用同一个数据库,则也应该为每个应用分配不同的账户。Web应用使用的数据库账户,不应该有创建自定义函数、操作本地文件的权限。
其他注入攻击
XML注入、代码注入、CRLF注入