注入攻击的本质,是把用户输入的数据当做代码执行。这里有两个关键条件,第一个是用户能够控制输入;第二个是原本程序要执行的代码,拼接了用户输入的数据。

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注入