白帽子讲Web安全(第 7 章 注入攻击)

第 7 章 注入攻击

注入攻击是 Web 安全领域中一种最为常见的攻击方式。

安全设计原则----“数据与代码分离”原则,它可以说是专门为了解决注入攻击而生的。

注入攻击的本质,是把用户输入的数据当作代码执行。这里有两个关键条件:

  1. 用户能够控制输入
  2. 原本程序要执行的代码,拼接了用户输入的数据。

7.1 SQL注入

在 SQL 注入的过程中,如果网站的 Web 服务器开启了错误回显,则会为攻击者提供极大的便利,比如攻击者在参数中输入一个单引号“ ' ”,引起执行查询语句的语法错误,服务器直接返回了错误信息。

7.1.1 盲注( Blind Injection )

Web 服务器关闭了错误回显,这时就没有办法成功实施 SQL 注入攻击了吗?攻击者为了应对这种情况,研究出了“盲注”( Blind Injection )的技巧。

“盲注”就是在服务器没有错误回显时完成的注入攻击。

攻击者必须找到一个方法来验证注入的 SQL 语句是否得到执行。

最常见的盲注验证方法时,构造简单的条件语句,根据返回页面是否发生变化,来判断 SQL 语句是否得到执行。

7.1.2 Timing Attack

在 MySQL 数据库中,有一个 BENCHMARK() 函数,它是用来测试函数性能的。

利用 BENCHMARK() 函数,可以让同一个函数执行若干次,使得结果返回的时间比平时要长;通过时间长短的变化,可以判断出注入语句是否执行成功。 这是一种边信道攻击,这个技巧在盲注中被称为 Timing Attack 。

7.2 数据库攻击技巧

找到 SQL 注入漏洞,仅仅是一个开始。要实施一次完整的攻击,还有许多事情需要做。

SQL 注入是基于数据库的一种攻击。不同的数据库有着不同的功能、不同的语法和函数,因此针对不同的数据库,SQL 注入的技巧也有所不同。

7.2.1 常见的攻击技巧

SQL 注入可以拆解出数据库的对应版本

在注入攻击的过程中,常常会用到一些读写文件的技巧。比如在 MySQL 中,就可以通过 LOAD_FILE() 读取系统文件,并通过 INTO DUMPFILE 写入本地文件。当然这要求当前数据库用户有读写系统相应文件或目录的权限。

... union select 1,1 LOAD_FILE( '/etc/passwd' ),1,1;

如果要将文件读出后,再返回结果给攻击者,则可以使用下面这个技巧:

CREATE TABLE potatoes(line BLOB);
UNION SELECT 1,1 HEX(LOAD_FILE( '/etc/passwd' )),1,1 INTO DUMPFILE '/tmp/potatoes';
LOAD DATA INFILE '/tmp/potatoes' INTO TABLE potatoes;

这就需要当前数据库用户有创建表的权限。首先通过 LOAD_INFO() 将系统文件读出,再通过 INTO DUMPFILE 将该文件写入系统中,然后通过 LOAD DATA INFILE 将文件写入系统中,然后通过 LOAD DATA INFILE 将文件导入创建的表中,最后就可以通过一般的注入技巧直接操作表数据了。

写入文件的技巧,经常被用于导出一个 Webshell,为攻击者的进一步攻击做铺垫。因此在设计数据库安全方案时,可以禁止普通数据库用户具备操作文件的权限。

7.2.2 命令执行

在 MySQL 中,除了可以通过导出 webshell 间接地执行命令外,还可以 利用“用户自定义函数”的技巧,即 UDF(User-Defined Functions)来执行命令。

在建立数据库账户时应该遵循“最小权限原则”,尽量避免给 Web 应用使用数据库的管理员权限。

7.2.3 攻击存储过程

利用存储过程直接攻击外,存储过程本身也可能会存在注入漏洞。

7.2.4 编码问题

“基于字符集”的注入攻击技巧。

统一数据库、操作系统、Web 应用所使用的字符集,以避免各层对字符的理解存在差异。

基于字符集的攻击并不局限于 SQL 注入,凡是会解析数据的地方都可能存在此问题。比如再 XSS 攻击时,由于浏览器与服务器返回的字符编码不同,也可能会存在字符集攻击。

如果因为种种原因无法统一字符编码,则需要单独实现一个用于过滤或转义的安全函数,在其中需要考虑字符的可能范围。

根据不同字符集来限制用户输入数据的字符允许范围,以实现安全过滤。

7.2.5 SQL Column Truncation

2008 年 8 月,Stefan Esser 提出了一种名为“ SQL Column Truncation ”的攻击方式,在某些情况下,将会导致发生一些安全问题。

7.3 正确地防御 SQL 注入

  1. 找到所有的 SQL 注入漏洞;
  2. 修补这些漏洞。

7.3.1 使用预编译语句

防御 SQL 注入的最佳方式,就是使用预编译语句,绑定变量。

7.3.2 使用存储过程

使用安全的存储过程对抗 SQL 注入。

存储过程中也可能会存在注入问题,因此应该尽量避免在存储过程内使用动态的 SQL 语句。如果无法避免,则应该严格的输入过滤或者是编码函数来处理用户的输入数据。

7.3.3 检查数据类型

7.3.4 使用安全函数

从数据库自身的角度来说,应该使用 最小权限原则 ,避免 Web 应用直接使用 root 、dbowner 等高权限账户直接连接数据库。如果有多个不同的应用在使用同一个数据库,则也应该为每个应用分配不同的账户。Web 应用使用的数据库账户,不应该有创建自定义函数、操作本地文件的权限。

7.4 其他注入攻击

除了 SQl 注入外,在 Web 安全领域还有其他的注入攻击,这些注入攻击都有相同的特点,就是应用违背了“数据与代码分离”原则。

XML 攻击

代码注入

代码注入往往是由于不安全的编程习惯所造成的,危险函数应该尽量避免在开发中使用,可以在开发规范中明确指出哪些函数是禁止使用的。这些危险函数一般在开发语言的官方文档中可以找到一些建议。

7.4.3 CRLF 注入

CRLF 实际上是两个字符:CR 是 Carriage Return( ASCII 13, \r ) ,LF 是 Line Feed ( ASCII 10, \n ) 。 \r\n 这两个字符是用于表示换行的,其十六进制编码分别为 0x0d 、0x0a。

CRLF 常被用做不同语义之间的分隔符。因此通过“注入 CRLF 字符”,就有可能改变原有的语义。

在 HTTP 协议中,HTTP 头是通过 “ \r\n ”来分割的。因此如果服务器端没有过滤 “ \r\n ”,而又把用户输入的数据放在 HTTP 头中,则有可能导致安全隐患。这种在 HTTP 头中的 CRLF 注入,又可以称为 “ Http Response Splitting ”。

对抗 CRLF 的方法非常简单,只需要处理好 “ \r ”、" \n " 这两个保留字符即可,尤其是那些使用“换行符”作为分隔符的应用。

7.5 小结

注入攻击时应用违背了“数据与代码分离原则”导致的结果。它有两个条件:

  1. 用户能够控制数据的输入;
  2. 代码拼凑了用户输入的数据,把数据当作代码执行了。

在对抗注入攻击时,只需要牢记“数据与代码分离原则”,在“拼凑”发生的地方进行安全检查,就能避免此类问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值