服务器之家:专注于服务器技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - 数据库技术 - 简单聊一聊SQL注入及防止SQL注入

简单聊一聊SQL注入及防止SQL注入

2023-07-30 12:21未知服务器之家 数据库技术

SQL注入 SQL注入是通过操作输入来修改事先定义好的SQL语句,对用户输入的字符串进行过滤,转义,限制或处理不严谨,导致用户可以通过输入精心构造的字符串去非法获取到数据库中的数据,以达到执行代码对服务器进行攻击的方

SQL注入

SQL注入是通过操作输入来修改事先定义好的SQL语句,对用户输入的字符串进行过滤,转义,限制或处理不严谨,导致用户可以通过输入精心构造的字符串去非法获取到数据库中的数据,以达到执行代码对服务器进行攻击的方法。

现有一个数据库test中的表user,可以通过账号name,密码pass登录,查看id

简单聊一聊SQL注入及防止SQL注入

登录代码

package JDBCtest;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

/*
 * 用户登录
 */
public class Demo4 {

    public static void main(String[] args) throws Exception {
        // 1.加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 2.创建连接
        String url = "jdbc:mysql:///test";
        String username = "root";
        String password = "1234";
        Connection connection = DriverManager.getConnection(url, username, password);
        // 接收用户名密码
        Scanner sc = new Scanner(System.in);
        String name = sc.next();
        String pass = sc.next();// 3.sql语句
        String sql = "Select * from user where name='" + name + "' and pass ='" + pass + "'";
        // System.out.println(sql);
        // 4.获取sql对象statement
        Statement statement = connection.createStatement();
        // 5.执行sql语句
        ResultSet rs = statement.executeQuery(sql);
                // 6.登录
        if (rs.next()) {
            System.out.println("登录成功");
        } else {
            System.out.println("登录失败");
        }
        // 7.释放资源
        statement.close();
        connection.close();
    }
}

通过表中账号密码登录成功

简单聊一聊SQL注入及防止SQL注入简单聊一聊SQL注入及防止SQL注入

由于账号或密码错误登录失败

简单聊一聊SQL注入及防止SQL注入简单聊一聊SQL注入及防止SQL注入

以上可以正确登录成功或失败

注意!

如果此时我这样输入 【lihua 'or'1'='1】,也成功登录了,但是数据库没根本没有这条数据

简单聊一聊SQL注入及防止SQL注入

这是为什么呢?让我们从代码里找问题!

        String sql = "Select * from user where name='" + name + "' and pass ='" + pass + "'";

为了调用数据库,使用字符串拼接SQL语句

让我们打印一下输入 【lihua 'or'1'='1】的sql语句一探究竟

简单聊一聊SQL注入及防止SQL注入

select语句中的where条件可以看做两组并列(注意and在前先执行,or后执行)

简单聊一聊SQL注入及防止SQL注入

由于'1'='1'为TRUE,所以以上语句等价于简单聊一聊SQL注入及防止SQL注入肯定会登录成功!

同理输入【'or'1'='1'# xxx】也能登陆成功

简单聊一聊SQL注入及防止SQL注入

这是由于#在SQL中是注释符号,以上语句等价于简单聊一聊SQL注入及防止SQL注入,于是就和上述情况一样了。

附防止sql注入的一些建议

1. 代码层防止sql注入攻击的最佳方案就是sql预编译

public List<Course> orderList(String studentId){
    String sql = "select id,course_id,student_id,status from course where student_id = ?";
    return jdbcTemplate.query(sql,new Object[]{studentId},new BeanPropertyRowMapper(Course.class));
}

这样我们传进来的参数 4 or 1 = 1就会被当作是一个student_id,所以就不会出现sql注入了。

2. 确认每种数据的类型,比如是数字,数据库则必须使用int类型来存储

3. 规定数据长度,能在一定程度上防止sql注入

4. 严格限制数据库权限,能最大程度减少sql注入的危害

5. 避免直接响应一些sql异常信息,sql发生异常后,自定义异常进行响应

6. 过滤参数中含有的一些数据库关键词

@Component
public class SqlInjectionFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req=(HttpServletRequest)servletRequest;
        HttpServletRequest res=(HttpServletRequest)servletResponse;
        //获得所有请求参数名
        Enumeration params = req.getParameterNames();
        String sql = "";
        while (params.hasMoreElements()) {
            // 得到参数名
            String name = params.nextElement().toString();
            // 得到参数对应值
            String[] value = req.getParameterValues(name);
            for (int i = 0; i < value.length; i++) {
                sql = sql + value[i];
            }
        }
        if (sqlValidate(sql)) {
            throw new IOException("您发送请求中的参数中含有非法字符");
        } else {
            chain.doFilter(servletRequest,servletResponse);
        }
    }

    /**
     * 关键词校验
     * @param str
     * @return
     */
    protected static boolean sqlValidate(String str) {
        // 统一转为小写
        str = str.toLowerCase();
        // 过滤掉的sql关键字,可以手动添加
        String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate|" +
                "char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like'|and|exec|execute|insert|create|drop|" +
                "table|from|grant|use|group_concat|column_name|" +
                "information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|" +
                "chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#";
        String[] badStrs = badStr.split("\\|");
        for (int i = 0; i < badStrs.length; i++) {
            if (str.indexOf(badStrs[i]) >= 0) {
                return true;
            }
        }
        return false;
    }
}

总结

延伸 · 阅读

精彩推荐
  • 数据库技术RedisDesktopManager怎么远程连接redis

    RedisDesktopManager怎么远程连接redis

    直接去官网或者csdn上搜就行 2.安装RedisDesktopManager 傻瓜式安装,一直点next就行 安装完成后就是这样 3.建立远程连接 开始连接之前需要以下准备工作 修改...

    未知662023-05-27
  • 数据库技术云服务器和数据库服务器的区别

    云服务器和数据库服务器的区别

    云服务器 和数据库服务器是互联网领域常见的服务器类型,它们也是整个互联网服务架构中最为重要的两个组成部分。云服务器作为互联网服务的基础,提...

    未知1502023-06-09
  • 数据库技术Django项目优化数据库操作总结

    Django项目优化数据库操作总结

    这篇文章主要介绍了Django项目中优化数据库操作总结,有需要的朋友可以借鉴参考下,希望可以有所帮助,祝大家共进步,早日升职加薪...

    gf_lvah5262021-12-13
  • 数据库技术阿里云ecs服务器使用数据库

    阿里云ecs服务器使用数据库

    阿里云 ECS服务器是一种基于云计算技术的服务器,能够在云端为客户提供虚拟化的计算资源和存储资源,为客户的业务提供更加可靠、高效、灵活的部署和...

    未知902023-05-21
  • 数据库技术云数据库选型必读:总有一款适合你!

    云数据库选型必读:总有一款适合你!

    我最近查看的DB-Engines排名中有373个系统,不过其中许多产品不是明确的云数据库。我选择了有代表性的12家云服务和云数据库供应商,按首字母排序来介绍...

    计算机世界9162021-08-31
  • 数据库技术数据库导出sql时页面报错

    数据库导出sql时页面报错

    问:数据库导出sql时页面报错 http://www.tco2o.cc:8080/login 用户名:**********密码:**********://www.tco2o.cc/phpmy/用户名:**********密码:**********,数据库导出sql时页面报错...

    未知1232023-05-07
  • 数据库技术Redis的过期策略和内存淘汰策略怎么用

    Redis的过期策略和内存淘汰策略怎么用

    设置 key 的过期时间。超时后,将会自动删除该 key 。在Redis的术语中一个 key 的相关超时是volatile的。 超时后只有对 key 执行DEL、SET、GETSET时才会清除。 这...

    未知1362023-06-10
  • 数据库技术数据库云服务器购买

    数据库云服务器购买

    数据库 云服务器 购买指南 摘要: 本文旨在提供关于数据库云服务器购买的全面指南。首先介绍了数据库云服务器的基本概念和优势,然后详细介绍了购买...

    未知892023-07-06