百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

SQL注入问题(sql注入解决方法)

toyiye 2024-07-15 01:34 13 浏览 0 评论

下述操作将会以MySql数据库为例

引用的是ums库中的t_user表

表中只有一条数据,username与password的数据均为admin

1.简介

SQL注入攻击是比较常见的网络攻击方式之一

它不是利用操作系统的BUG来实现攻击,而是发生于应用程序之数据库层的安全漏洞。

针对程序员编写时的疏忽通过SQL语句,实现无账号登录,甚至篡改数据库

简单来讲,是在输入的字符串之中注入SQL的指令

那么这些注入进去的指令就会被数据库服务器误认为是正常的SQL指令而运行

因此遭到破坏或是入侵。

最常见的就是我们在应用程序中使用字符串联结方式组合 SQL 指令

有心之人就会写一些特殊的符号,恶意篡改原本的 SQL 语法的作用,达到注入攻击的目的。

// 比如验证用户登录需要 username 和 password,编写的 SQL 语句如下:
select * from t_user where (username = '"+ username +"') and (password = '"+ password +"');
// username 和 password 字段被恶意填入
username = "1' OR '1'='1";
password = "1' OR '1'='1";
// 将导致原本的 SQL 字符串被填为:
select * from t_user where (username = '1' or '1'='1') and (password = '1' or '1'='1');
// 此时实际上运行的sql为
select * from t_user;
// 也就是不再需要 username 和 password 账密即达到登录的目的,结果不言而喻。
public static void main(String[] args) {
    // 此时真实数据库中只有一个用户,username与password均为admin
    login("admin","admin"); //登录成功
    login("admin","111"); // 登录失败
    login("1' or '1' = '1","1' or '1' = '1"); //登录成功
}

public static void login(String username,String password){
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    String url = "jdbc:mysql://127.0.0.1:3306/ums?useUnicode=true&characterEncoding=utf-8";
    User user = null;
    try {
        Class.forName("com.mysql.jdbc.Driver");
        conn = DriverManager.getConnection(url,"root","");
        String sql = new StringBuffer()
                .append(" select id,username,password,phone,address ")
                .append(" from t_user ")
                .append(" where username = '"+ username +"' ")
                .append(" and password = '"+ password +"' ")
                .toString();
        ps = conn.prepareStatement(sql);
        rs = ps.executeQuery();
        while(rs.next()){
            System.out.println("登录成功");
            return;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println("登录失败");
}

2.解决sql注入问题

MySQL的驱动提供了预编译语句的支持,不同的程序语言,都分别有使用预编译语句的方法

实际上,绑定变量使用预编译语句是预防SQL注入的最佳方式

使用预编译的SQL语句语义不会发生改变

在SQL语句中,变量用问号?表示,黑客即使本事再大,也无法改变SQL语句的结构

public static void main(String[] args) {
    login("admin","admin"); //登录成功
    login("admin","111"); // 登录失败
    login("'1' or '1' = '1'","'1' or '1' = '1'"); // 登录失败
}

public static void login(String username,String password){
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    String url = "jdbc:mysql://127.0.0.1:3306/ums?useUnicode=true&characterEncoding=utf-8";
    User user = null;
    try {
        Class.forName("com.mysql.jdbc.Driver");
        conn = DriverManager.getConnection(url,"root","");
        String sql = new StringBuffer()
                .append(" select id,username,password,phone,address ")
                .append(" from t_user ")
                .append(" where username = ? ")
                .append(" and password = ? ")
                .toString();
        ps = conn.prepareStatement(sql);
        ps.setString(1,username);
        ps.setString(2,password);
        rs = ps.executeQuery();
        while(rs.next()){
            System.out.println("登录成功");
            return;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println("登录失败");
}

3.MyBatis中的Sql注入问题

我们使用 mybatis 编写 SQL 语句时,难免会使用模糊查询的方法,mybatis 提供了两种方式 #{}${}

当用户使用${param}进行参数传递时,表示使用拼接字符串的方式进行参数的注入

会将接受到参数的内容不加任何修饰符拼接在 SQL 中,将引起 SQL 注入问题。

<!-- sql注入问题 -->
<select id="selectByUsernameAndPassword4" resultType="user">
    select <include refid="userColumn"></include>
    from t_user
    where username = ${username}
    and password = ${password}
</select>
// 在遇到sql注入后,相当于查询了所有
public List<User> selectByUsernameAndPassword4(@Param("username") String username, @Param("password") String password);

// 测试
SqlSession session = null;
try {
    session = MyBatisUtil.getSession();
    UserDao userDao = session.getMapper(UserDao.class);
    List<User> users = userDao.selectByUsernameAndPassword4("'1' or '1'='1'","'1' or '1'='1'");
    // 此时查询了所有的t_user表中的数据
    // 可以将此时的sql语句看做:select * from user
    System.out.println(users);
    session.commit();
} catch (Exception e) {
    e.printStackTrace();
    session.rollback();
} finally {
    MyBatisUtil.close();
}

运行后控制台效果如下

根据最终展现效果我们可以发现

此时是将参数作为字符串拼接的形式存在

在原本代码中只存在两个查询条件

但是拼接之后最终将会产生四个条件

由于多的两个条件是通过or连接的

最终运行效果相当于select * from t_user

4.MyBatis解决sql注入问题

使用#{param}的方式进行参数传递时

在预处理的时候会把参数部分用一个占位符?替代

其中 param表示接受输入参数的名称。

这样能够有效的解决 SQL 注入问题

从而避免SQL注入的问题出现

<!-- 避免sql注入 -->
<select id="selectByUsernameAndPassword5" resultType="user">
    select <include refid="userColumn"></include>
    from t_user
    where username = #{username}
    and password = #{password}
</select>
SqlSession session = null;
try {
    session = MyBatisUtil.getSession();
    UserDao userDao = session.getMapper(UserDao.class);
    List<User> users = userDao.selectByUsernameAndPassword5("'1' or '1'='1'","'1' or '1'='1'");
    // 此时将传递的参数整体作为一个字符串
    // 即username的值为:'1' or '1'='1'
    // password的值为:'1' or '1'='1'
    // 因此没有查询到对应的数据
    session.commit();
} catch (Exception e) {
    e.printStackTrace();
    session.rollback();
} finally {
    MyBatisUtil.close();
}

运行后控制台效果如下

根据最终展现效果我们可以发现

此时在预处理的时候会把参数部分用一个占位符?替代

传递的参数作为一个整体存在

最终在运行时仍然是原本的两个查询结果

从而避免SQL注入的问题出现

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码