IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> Mybatis与SQL注入 -> 正文阅读

[大数据]Mybatis与SQL注入

1.简述

1.1.什么是SQL注入

????????SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

2.SQL注入案例(Jdbc)

2.1.建表语句

create table user_mybatis(?

??? id????? int Primary key,?

??? username??? varchar(30),?

??? password??? varchar(30)?

);?

insert into user_table values(1,user -1','12345');?

insert into user_table values(2,user-2','12345');?

2.2.使用Jdbc加载sql文

package com.me.homesickness.mybatis.test;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import com.mysql.jdbc.Connection;

import com.mysql.jdbc.PreparedStatement;

/**

?* sql注入Jdbc

?* @author Administrator

?*

?*/

public class JdbcSqlInjection {

??? public static void main(String[] args) throws ClassNotFoundException, SQLException {

??????? String userName = "zhangsan";

??????? String password = "hdhdfbhgs+++jse";

??????? String sql = "SELECT id,username from user_mybatis WHERE " + "username='" + userName + "' AND " + "password='" + password + "'";

???????

??????? // 1.加载驱动

??????? Class.forName("com.mysql.jdbc.Driver");

???????

??????? // 2.创建数据库连接对象

??????? Connection conn = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql?characterEncoding=utf8", "root", "mnj852123");

???????

??????? // 3.指定查询sql

??????? PreparedStatement stat = (PreparedStatement) conn.prepareStatement(sql);

??????? System.out.println(stat.toString());

???????

??????? // 4.执行查询,获取结果集

??????? ResultSet rs = stat.executeQuery();

???????

??????? // 5.输出查询内容

??????? while(rs.next()) {

??????????? String id = rs.getString(1);

??????????? String name = rs.getString(2);

??????????? System.out.println("id:" + id + "??????? name:" + name);

??????? }

??? }

}

2.3.执行结果

2.4.修改username的值

??????? // String userName = "zhangsan";

??? ??? String userName = "' OR 1=1 -- '";

解析:

1)“--” 表示SQL注释,因此后面语句忽略;

2)因为1=1恒成立,因此 username='' OR 1=1? 恒成立,因此SQL语句等同于:

SELECT id,username from user_mybatis WHERE username='' OR 1=1 -- '' AND password='hdhdfbhgs+++jse'

2.5.执行代码

package com.me.homesickness.mybatis.test;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import com.mysql.jdbc.Connection;

import com.mysql.jdbc.PreparedStatement;

/**

?* sql注入Jdbc

?* @author Administrator

?*

?*/

public class JdbcSqlInjection {

??? public static void main(String[] args) throws ClassNotFoundException, SQLException {

??????? // String userName = "zhangsan";

??????? String userName = "' OR 1=1 -- '";

??????? String password = "hdhdfbhgs+++jse";

??????? String sql = "SELECT id,username from user_mybatis WHERE " + "username='" + userName + "' AND " + "password='" + password + "'";

???????

??????? // 1.加载驱动

??????? Class.forName("com.mysql.jdbc.Driver");

???????

??????? // 2.创建数据库连接对象

??????? Connection conn = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql?characterEncoding=utf8", "root", "mnj852123");

???????

??????? // 3.指定查询sql

??????? PreparedStatement stat = (PreparedStatement) conn.prepareStatement(sql);

??????? System.out.println(stat.toString());

???????

??????? // 4.执行查询,获取结果集

??????? ResultSet rs = stat.executeQuery();

???????

??????? // 5.输出查询内容

??????? while(rs.next()) {

??????????? String id = rs.getString(1);

??????????? String name = rs.getString(2);

??????????? System.out.println("id:" + id + "??????? name:" + name);

??????? }

??? }

}

2.6.解决方法

??????? /**

??????? ?* JDBC解决SQL注入

??????? ?*/

??????? String userName = "' OR 1=1 -- '";

??????? String password = "hdhdfbhgs+++jse";

??????? String sql = "SELECT id,username FROM user_mybatis WHERE username = ? AND password = ?";

???????

??????? // 1.加载驱动

??????? Class.forName("com.mysql.jdbc.Driver");

???????

??????? // 2.创建数据库连接对象

??????? Connection conn = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql?characterEncoding=utf8", "root", "mnj852123");

???????

??????? // 3.指定查询sql

??????? PreparedStatement stat = (PreparedStatement) conn.prepareStatement(sql);

??????? stat.setString(1, userName);

??????? stat.setString(2, password);

??????? System.out.println(stat.toString());???????

???????

??????? // 4.执行查询,获取结果集

??????? ResultSet rs = stat.executeQuery();

???????

??????? // 5.输出查询内容

??????? while(rs.next()) {

??????????? String id = rs.getString(1);

??????????? String name = rs.getString(2);

??????????? System.out.println("id:" + id + "???? ???name:" + name);

??????? }

2.7.执行结果

3.Mybatis中符号#与符号$的区别

????????动态 sql mybatis 的主要特性之一,在 mapper 中定义的参数传到 xml 中之后,在查询之前 mybatis 会对其进行动态解析。mybatis 为我们提供了两种支持动态 sql 的语法:#{} 以及 ${}

????????在下面的语句中,如果 username 的值为 zhangsan,则两种方式无任何区别:

?????????????? select * from user where name = #{name};

?????????????? select * from user where name = ${name};

????????其解析之后的结果均为

?????????????? select * from user where name = 'zhangsan';

 ??? 但是 #{} ${} 在预编译中的处理是不一样的。#{} 在预处理时,会把参数部分用一个占位符 ? 代替,变成如下的 sql 语句:

?????????????? select * from user where name = ?;

????????而 ${} 则只是简单的字符串替换,在动态解析阶段,该 sql 语句会被解析成

????????select * from user where name = 'zhangsan';

????????以上,#{} 的参数替换是发生在 DBMS 中,而 ${} 则发生在动态解析过程中。

????????那么,在使用过程中我们应该使用哪种方式呢?

????????答案是,优先使用 #{}。因为 ${} 会导致 sql 注入的问题。看下面的例子:

 ??? select * from ${tableName} where name = #{name}

????????在这个例子中,如果表名为

?????????user; delete user; --?

   则动态解析之后 sql 如下:

?????????????? select * from user; delete user; -- where name = ?;

  --之后的语句被注释掉,而原本查询用户的语句变成了查询所有用户信息+删除用户表的语句,会对数据库造成重大损伤,极大可能导致服务器宕机。

????????因为数据库的原因导致表名用参数传递进来的时候,只能使用 ${},所以我们在这种用法中要小心sql注入的问。

4.SQL注入案例(Mybatis)

4.1.建表语句

create table user_mybatis(?

??? id????? int Primary key,?

??? username??? varchar(30),?

??? password??? varchar(30)?

);?

insert into user_table values(1,user -1','12345');?

insert into user_table values(2,user-2','12345');?

4.2.创建POJO类

package com.me.homesickness.mybatis.pojo;

public class UserMybatis {

???

??? private int id;

??? private String userName;

??? private String passWord;

???

??? public int getId() {

??????? return id;

??? }

??? public void setId(int id) {

??????? this.id = id;

??? }

??? public String getUserName() {

??????? return userName;

??? }

??? public void setUserName(String userName) {

??????? this.userName = userName;

??? }

??? public String getPassWord() {

??????? return passWord;

??? }

??? public void setPassWord(String passWord) {

??????? this.passWord = passWord;

??? }

}

4.3.创建Mapper类

package com.me.homesickness.mybatis.mapper;

import com.me.homesickness.mybatis.pojo.UserMybatis;

public interface UserMybatisMapper {

??? public UserMybatis login(UserMybatis userMybatis);

???

}

4.4.创建Mapper映射XML文件UserMybatisMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!-- 定义文档类型为mybatissql映射文件 -->

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

??? "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.me.homesickness.mybatis.mapper.UserMybatisMapper">

? <!-- SQL注入测试 -->

? <select id="login" parameterType="com.me.homesickness.mybatis.pojo.UserMybatis"

? ????????????? resultType="com.me.homesickness.mybatis.pojo.UserMybatis">

? ? SELECT id ,username as userName FROM user_mybatis WHERE username='${userName}' AND password='${passWord}'

? </select>

</mapper>

4.5.测试SQL注入

package com.me.homesickness.mybatis.test;

import java.io.IOException;

import java.io.Reader;

import java.util.List;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSession;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.me.homesickness.mybatis.pojo.UserMybatis;

/**

?* MybatisSQL注入

?* @author Administrator

?*

?*/

public class MybatisSqlInjection {

??? public static void main(String[] args) throws IOException {

??????? String resource = "config/SqlMapConfig.xml";

??????? String userName = "' OR 1=1 -- '";

??????? //String userName = "zhangsan";

??????? String password = "hdhdfbhgs+++jse";

???????

??????? // 1.读取配置文件

??????? Reader reader = Resources.getResourceAsReader(resource);

???????

??????? // 2.获取会话工厂

??????? SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);

??????? // 3.从会话工厂里获取SqlSession对象

??????? SqlSession openSession = sqlSessionFactory.openSession();

???????

??????? // 4.指定查询语句

??????? String sql = "com.me.homesickness.mybatis.mapper.UserMybatisMapper.login";

???????

??????? // 5.调用api查询

??????? UserMybatis userMybatis = new UserMybatis();

??????? userMybatis.setUserName(userName);

??????? userMybatis.setPassWord(password);

??????? List<UserMybatis> listUserMybatis = openSession.selectList(sql, userMybatis);

??????? listUserMybatis.forEach(user-> {

??????????? System.out.println(user.getUserName());

??????? });

??? }

}

4.6.执行结果

4.7.解决sql注入,在mapper.xml文件中将符号${}替换为符号#{}

<?xml version="1.0" encoding="UTF-8" ?>

<!-- 定义文档类型为mybatissql映射文件 -->

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

??? "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.me.homesickness.mybatis.mapper.UserMybatisMapper">

? <!-- SQL注入测试 -->

? <!-- <select id="login" parameterType="com.me.homesickness.mybatis.pojo.UserMybatis"

? ????????????? resultType="com.me.homesickness.mybatis.pojo.UserMybatis">

? ? SELECT id ,username as userName FROM user_mybatis WHERE username='#{userName}' AND password='#{passWord}'

? </select> -->

? <select id="login" parameterType="com.me.homesickness.mybatis.pojo.UserMybatis"

? ????????????? resultType="com.me.homesickness.mybatis.pojo.UserMybatis">

? ? SELECT id ,username as userName FROM user_mybatis WHERE username=#{userName} AND password=#{passWord}

? </select>

</mapper>

4.8.执行结果

4.9.总结

1)优先使用 #{}。因为 ${} 会导致 sql 注入的问题

?2)#{}被符号”’”包裹时会报错,使用时需要去掉符号"'"

参照:

https://baike.baidu.com/item/sql%E6%B3%A8%E5%85%A5/150289?fr=aladdin

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-10-17 12:03:34  更:2021-10-17 12:05:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:17:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码