一、前言
打CTF时翻到的一篇文章,反正CTF不会做,正好就记录一下(我太菜了555)
链接:
首先给本次SQL注入的payload加上了一些条件:
- 不能出现
in
或者or
等关键词 - 不能出现
information_schema
- 不能使用
union ... select
我测试使用的mysql版本为:5.7.26
二、information_schema
直奔主题吧,还有哪些表可以用?
sys.x$schema_flattened_keys
,数据库字段为table_schema
,表字段为table_name
sys.schema_table_statistics
,字段名同上,比上面的表数据更多mysql.innodb_table_stats
,数据库字段database_name
,表字段table_name
mysql.innodb_index_stats
,同上,显示的比上面多,不过这两个表在这不能用了
sys.x$statement_analysis
这个表会保留执行过的SQL语句
三、无字段名注入
重点在这,找到可以用的表后,因为不知道字段名,所以采用这个方法
大概的思路就是:
假如这个表只有一列,那么直接substr((select * from example),1,1)='a'
就行了
但是多列多条记录的情况下就会报错,所以这里有个技巧,通过比较来确定字符,假设有两列,那么:
select (0,0) <= (select * from example limit 0,1)
因为一般存在数据库中的都是数字、字母,所以先用0来判断列数,有些字符比0还要小,需要注意
这样就能一个个字符的比较出来了,但是在mysql中是不区分大小写的,可能在CTF中flag存在大小写
这里又是一个小技巧,将字母转换为二进制,这样mysql会按位进行比较
select (0,binary('A')) <= (select * from example limit 0,1)
但是因为过滤了in,所以binary()不能使用
但是mysql中json对象是二进制对象,所以cast(0 as json)
会返回一个二进制字符串
select (0,concat('A',cast(0 as json)) <= (select * from example limit 0,1)
因为是一个字符一个字符进行比较的,所以大小写就可以比较出来了
注意点
1、假如example表中的数据为('!','t!S!')
那么上面的例子中,本质上比较的就是(0,'A0') <= ('!','t!S!')
但是我们需要比较的是第二个字段,由于!
比0小,这就变成永真了
所以一开始最好将比较的字符设置为最小的空格(' ','A0')
2、假如表中的数据为('!','t!S!')
由于我们连接的二进制字符串总会加上一个0,例如A0
但是我们比较的是第一位A,所以我们不知道0比较的情况
例如(' ','t0') <= ('!','t!S!')
,这时结果为0
(' ','t!0') <= ('!','t!S!')
这时结果为1
可以看到第二个例子和我们想要的不一样,所以在特殊情况下,会出现一个字符的偏差
所以在0的位置我们需要加上一个比较大的字符或者比较小的字符,来使我们想要的结果一致
例如:
select (' ',concat('A~',cast(0 as json)) <= (select * from example limit 0,1)
select (' ',concat('A ',cast(0 as json)) <= (select * from example limit 0,1)
这样就不会出现结果不相同的情况了
- 本文链接:http://siii0.github.io/mysql%E6%97%A0%E5%AD%97%E6%AE%B5%E5%90%8D%E6%B3%A8%E5%85%A5/
- 版权声明:本博客所有文章除特别声明外,均默认采用 许可协议。