SQL注入(非常详细)零基础入门到精通,收藏这一篇就够了

SQL注入(非常详细)零基础入门到精通,收藏这一篇就够了SQL注入简介
SQL注入就是指Web应用程序对用户输入数据的合理性没有进行判断,前端传入后端的参数是攻击者可控制的,并且根据参数带入数据库查询&#xff

服务器被远程控制并安装后门:攻击者利用数据库服务器提供的操作系统支持,可以进一步修改或控制操作系统,从而在服务器上安装后门程序,从而可以远程控制您的服务器。这为后续的攻击和盗窃行为提供了基础。

破坏硬盘数据,使整个系统瘫痪:更严重的是,有些数据库系统允许SQL指令直接操作文件系统,使得SQL注入的危害性更大。攻击者可利用该漏洞直接破坏服务器硬盘上的数据或导致整个系统瘫痪,从而造成重大的经济损失和安全威胁。

3. SQL注入攻击的分类

注入点类型

1. 数字化注入

这主要涉及应用程序对用户输入的数字参数的不当处理。如果应用程序在构造SQL查询语句时无法完全验证和过滤用户输入的数字参数,攻击者就可以输入恶意SQL代码并修改原始查询语句来操纵数据库可能达到的目的。

具体来说,结构类似于http://xxx.com/users.php?id=1。基于此格式的注入通常是因为注入点ID 是数字类型。例如,如果你想显示用户的个人信息或显示一篇文章,你很可能会使用这种类型的结构来传递ID或其他信息,将其传递到后端,并在数据库中创建相应的信息。查询信息并返回给服务器。正面。

如果输入参数是整数,并且存在注入漏洞,则可以认为是数字注入。

测试程序:

(1) 添加单引号。网址: xxx.xxx.xxx/xxx.php?id=3\’;

对应SQL:select * from table where id=3\’ 这种情况下,SQL语句失败,程序无法成功从数据库查询数据,并抛出异常。

(2) 添加1=1,URL:xxx.xxx.xxx/xxx.php?id=3 和1=1。

对应的SQL:select * from table where id=3’ and 1=1语句运行正常,与原来页面没有变化。

(3) 添加1=2,URL:xxx.xxx.xxx/xxx.php?id=3,1=2。

对应的SQL:select * from table where id=3 and 1=2语句可以正常执行,但是无法查询结果,所以返回的数据会和原来的网页不一样。

如果满足以上三点,就可以判定某个URL存在数字注入。

2. 字符注入

主要原因是应用程序没有对用户输入的字符数据进行严格的过滤和验证。如果应用程序在构建SQL 查询语句时直接使用用户输入的字符数据,而不执行任何必要的转义或过滤,则攻击者可能会将恶意SQL 代码注入到这些输入中。

具体来说,该结构类似于http://xxx.com/users.php?name=admin。注入点名称的类型为字符类型,因此称为字符注入点。这类SQL语句的原型大概是“select * from table name where name=\’admin\’”。注意,相比于数值注入型SQL语句的原型,多了引号,并且使用了单引号或单引号。双引号。

当输入参数是字符串时,称为字符类型。字符类型和数字类型之间最大的区别之一是数字类型不需要用单引号括起来,而字符串通常需要用单引号括起来。

例如数字语句:select * from table where id=3;

字符的类型如下。从表中选择*,其中name=\’admin\’;

因此,您可以在构建有效负载时通过用单引号将语句结束来成功执行该语句。

测试程序:

(1)添加单引号:select * from table where name=\’admin\’\’;

添加一个单引号会导致出现三个单引号,因此无法运行并且程序会报错。

(2) 添加“且1=1”。本例的SQL语句为: select * from table where name=\’admin\’ and 1=1\’ 无法执行注入,必须通过注释符号绕过。

所以构造语句看起来像这样: select * from table where name=\’admin\’ and 1=\’ 可以执行成功,返回结果正确。

(3)加上1=2——则SQL语句为:如果select * from table where name=\’admin\’ and 1=2\’ 则会报错。

如果满足以上三点,就可以判定该URL是字符注入。

3. 搜索注入

这主要涉及应用程序不正确地处理用户输入的搜索关键字。如果您的应用程序允许用户通过搜索功能查询数据库中的信息,而用户输入的搜索关键字没有经过严格的验证和过滤,攻击者就可以利用此漏洞发出恶意搜索请求,从而达到创建和过滤的目的。破坏数据库。非法操纵数据库。

这是一种特殊类型的注射。具体来说,这种类型的注入在执行数据搜索时不会过滤搜索参数。一般情况下,链接地址可能会包含keyword=keyword,但不会出现在链接地址中,而是直接从搜索框表单提交。此类注入点发送的SQL语句原型大致为:从表名中选择*,其中字段如“%keyword%”

如何提交注入点

1. 注射

SQL Get注入的原理主要涉及Web应用程序错误处理用户通过GET方法发送的参数。当用户直接在浏览器地址栏中键入URL 并通过GET 方法向服务器发送请求时,应用程序会解析URL 中的参数并使用它们创建SQL 查询语句。如果应用程序没有对用户提交的GET参数进行严格的验证和过滤,攻击者就有可能构造恶意URL,并通过GET参数注入恶意SQL代码,对数据库执行未经授权的操作。

2. 后注射

SQL后注入的原理主要涉及Web应用程序对用户通过POST方法提交的参数进行不当处理。当用户向服务器提交数据(例如通过HTML 表单)时,通常使用POST 方法。在此过程中,用户输入的数据包含在HTTP 请求的正文中,并通过POST 参数传递到服务器。如果应用程序没有完全验证和过滤用户通过POST 方法发送的参数,攻击者就有可能制作恶意POST 请求并注入恶意SQL 代码以对数据库执行未经授权的操作。

3.Cookie注入

SQL cookie注入的原理是,攻击者主要利用Web应用程序的cookie处理不当漏洞,通过修改或伪造cookie值,将恶意SQL注入到应用程序的数据库查询中,从而执行未经授权的操作或检索未经授权的数据。坏数据。

Web 应用程序通常使用cookie 在服务器和客户端之间传递用户凭据和会话ID 等数据。当用户登录网站或执行某些操作时,服务器会生成包含相关信息的cookie并将其发送到客户端(浏览器)。然后,您的浏览器会自动保留此cookie,并通过每个请求将其发送到服务器,以帮助服务器识别您并维护会话状态。

但是,如果应用程序在验证和过滤cookie 中的数据方面做得不好,攻击者就可以创建恶意cookie 值并向其中注入恶意SQL 代码。如果应用程序解析此恶意cookie 并构造数据库查询,则恶意SQL 代码可能会嵌入到查询中并执行。

4.HTTP头注入

HTTP 标头注入的原理主要是攻击者利用Web 应用程序中的漏洞,对HTTP 请求标头字段进行不当处理,通过修改或伪造请求标头中的信息,将恶意SQL 代码注入到您的应用程序中。它查询数据库并可能执行未经授权的操作或检索不正确的数据。

HTTP请求头包含了User-Agent、Cookie、X-Forwarded-For等丰富的信息。这些领域在Web 应用程序中发挥着重要作用。例如,User-Agent字段用于标识客户端类型和版本信息,Cookie字段用于传输会话状态信息,X-Forwarded-For字段记录客户端的IP地址等信息。

但是,如果Web 应用程序没有正确验证和过滤这些请求标头字段中的数据,攻击者就可以修改这些字段中的值并注入恶意SQL 代码。当应用程序解析这些恶意请求头字段并构造数据库查询语句时,可以将恶意SQL代码嵌入到查询中并执行。

4. 演示示例

首先,创建一个测试表并插入一些简单数据(MySQL数据库)。

创建表`t_user` (

`id` int(11) NOT NULL AUTO_INCRMENT,

`用户名` varchar(30) 默认NULL,

`密码` varchar(30) 默认NULL,

主键(`id`)

) 引擎=InnoDB 默认字符集=utf8mb4;

INSERT INTO `t_user` VALUES (\’1\’, \’John\’, \’111111\’);

INSERT INTO `t_user` VALUES (\’2\’, \’Tom\’, \’222222\’);

接下来是使用Spring Boot和MyBatis的Java程序部分。如果您是构建Spring Cloud 项目的新手,请参阅上一篇文章逐步:构建Spring Cloud 阿里巴巴项目。

将依赖项添加到pom.xml 文件。

!– 连接Spring Boot 和MyBatis —

依赖

groupIdorg.mybatis.spring.boot/groupId

artifactIdmybatis-spring-boot-starter/artifactId

版本2.1.1/版本

/依赖

!– mysql 驱动–

依赖

组IDmysql/组ID

artifactIdmysql-connector-java/artifactId

/依赖

接下来,我们有Java 每一层的代码,从控制器到dao。为了完整性,我发布了所有代码。我在控制器层有一个方法,参数是用户名,为了演示目的,返回用户详细信息。

包com.fullstack.commerce.user.controller;

导入com.fullstack.commerce.user.entity.User。

导入com.fullstack.commerce.user.service.UserService;

导入org.springframework.web.bind.annotation.RequestMapping。

导入org.springframework.web.bind.annotation.RequestParam。

导入org.springframework.web.bind.annotation.ResponseBody。

导入org.springframework.web.bind.annotation.RestController。

导入javax.annotation.Resource。

导入java.util.List。

@RestController

@RequestMapping(\’用户\’)

公共类用户控制器{

@资源

私有UserService 用户服务;

@RequestMapping(\’getUserInfo\’)

@ResponseBody

//根据用户名查询用户列表信息

公共ListUser getUserInfo(@RequestParam(\’用户名\’)字符串用户名){

ListUser 结果=userService.getUserInfo(用户名);

返回结果。

}

}

服务层比较简单,有一个接口和相应的实现类,调用dao方法查询用户列表。

包com.fullstack.commerce.user.service;

导入com.fullstack.commerce.user.entity.User。

导入java.util.List。

公共接口用户服务{

ListUser getUserInfo(字符串用户名);

}

包com.fullstack.commerce.user.service.impl;

导入com.fullstack.commerce.user.dao.UserDao。

导入com.fullstack.commerce.user.entity.User。

导入com.fullstack.commerce.user.service.UserService;

导入org.springframework.stereotype.Service。

导入javax.annotation.Resource。

导入java.util.List。

@服务

公共类UserServiceImpl 实现UserService {

@资源

私有UserDao userDao;

@覆盖

公共ListUser getUserInfo(字符串用户名){

return userDao.getUserInfo(用户名);

}

}

dao层是一个只有一个方法的接口。

包com.fullstack.commerce.user.dao;

导入com.fullstack.commerce.user.entity.User。

导入java.util.List。

公共接口UserDao {

ListUser getUserInfo(字符串用户名);

}

除了上面的业务代码之外,我们还需要一个启动类。

包com.fullstack.commerce.user;

导入org.mybatis.spring.annotation.MapperScan。

导入org.springframework.boot.SpringApplication。

导入org.springframework.boot.autoconfigure.SpringBootApplication。

@SpringBootApplication

@MapperScan(basePackages=\’com.fullstack.commerce.user.dao\’)

公共类用户应用程序{

公共静态无效主(字符串[] args){

SpringApplication.run(UserApplication.class, args);

}

}

对应的mapper文件是:

?xml 版本=\’1.0\’ 编码=\’UTF-8\’ ?

!DOCTYPE 映射器PUBLIC \’-//mybatis.org//DTD 映射器3.0//EN\’ \’http://mybatis.org/dtd/mybatis-3-mapper.dtd\’

映射器命名空间=\’com.fullstack.commerce.user.dao.UserDao\’

resultMap id=\’UserMap\’ type=\’com.fullstack.commerce.user.entity.User\’

结果属性=\’id\’列=\’id\’jdbcType=\’INTEGER\’/

结果属性=\’用户名\’列=\’用户名\’jdbcType=\’VARCHAR\’/

结果属性=\’密码\’ 列=\’密码\’ jdbcType=\’VARCHAR\’/

/结果图

选择id=\’getUserInfo\’ resultMap=\’UserMap\’

SELECT * FROM t_user WHERE 用户名=${用户名}

/选择

/映射器

注意,上面的mapper文件中只有一条select语句,并且该语句使用符号$来传递参数。这将直接替换参数值,而不进行任何预编译(如果使用占位符#,则会进行预编译,因此不会执行SQL注入)。

当然,您还需要配置application.yml文件,数据库用户名和密码将替换为您自己的。

弹簧:

数据来源:

url: jdbc:mysql: //localhost:3306/测试

用户名: myuser

密码: myuser

驱动程序类名: com.mysql.cj.jdbc.Driver

mybatis:

映射器位置: mapper/*.xml

代码完成后,就可以对其进行测试了。

5、测试验证:

让我们启动程序并测试它。在浏览器中输入以下地址并按Enter 键。

http://localhost:8080/user/getUserInfo?username=\’约翰\’

没问题。查找用户名John 的数据会返回以下结果:这完全符合预期。

但是当我重置参数时,我得到:

http://localhost:8080/user/getUserInfo?username=\’约翰\’ 或1=1

这相当于在数据库中运行以下SQL,它返回所有用户数据。

SELECT * FROM t_user WHERE username=\’John\’ OR 1=1

查看结果,表中的两条记录都返回给客户端(测试数据只插入两条记录;如果有多条记录,也返回全部数据)。

这显然是错误的,如果接口搜索查询范围之外的所有数据,修改数据或操作数据库就更加危险。

当然,将mapper文件的参数部分改为占位符#。这样会先预编译一下,就不会出现之前的情况了。 # 运行程序并运行上面的URL后,返回一个空值。这是因为此时正在数据库中搜索用户名[\’John\’ OR 1=1] 的记录。不存在。

网络安全学习资源分享:

我想分享一套完整的网络安全学习资料,对任何想学习网络安全的人都有用。

正确的

于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

因篇幅有限,仅展示部分资料,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,需要点击下方链接即可前往获取

读者福利 | CSDN大礼包:《网络安全入门&进阶学习资源包》免费分享 (安全链接,放心点击)

同时每个成长路线对应的板块都有配套的视频提供:

学习资料工具包

压箱底的好资料,全面地介绍网络安全的基础理论,包括逆向、八层网络防御、汇编语言、白帽子web安全、密码学、网络安全协议等,将基础理论和主流工具的应用实践紧密结合,有利于读者理解各种主流工具背后的实现机制。

面试刷题

视频配套资料&国内外网安书籍、文档

当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料

所有资料共282G,朋友们如果有需要全套《网络安全入门+进阶学习资源包》,可以扫描下方二维码或链接免费领取~

读者福利 | CSDN大礼包:《网络安全入门&进阶学习资源包》免费分享 (安全链接,放心点击)

#以上关于SQL注入(非常详细)零基础入门到精通,收藏这一篇就够了的相关内容来源网络仅供参考,相关信息请以官方公告为准!

原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/93102.html

(0)
CSDN's avatarCSDN
上一篇 2024年7月5日 上午11:03
下一篇 2024年7月5日 上午11:03

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注