Java安全之深入了解SQL注入

news2024/12/23 11:12:23

深入了解Java中的SQL注入

本文以代码实例复现了Java中JDBC及Mybatis框架采用预编译和非预编译时可能存在SQL注入的几种情况,并给予修复建议。

JDBC

首先看第一段代码,使用了远古时期的JDBC并且并没有使用预编译。这种简单的字符串拼接就存在SQL注入

@RequestMapping("/jdbc/vuln")
public String jdbc_sqli_vul(@RequestParam("username") String username) {

    StringBuilder result = new StringBuilder();

    try {
        Class.forName(driver);
        Connection con = DriverManager.getConnection(url, user, password);

        if (!con.isClosed())
            System.out.println("Connect to database successfully.");

        // sqli vuln code
        Statement statement = con.createStatement();
        String sql = "select * from users where username = '" + username + "'";
        logger.info(sql);
        ResultSet rs = statement.executeQuery(sql);

        while (rs.next()) {
            String res_name = rs.getString("username");
            String res_pwd = rs.getString("password");
            String info = String.format("%s: %s\n", res_name, res_pwd);
            result.append(info);
            logger.info(info);
        }
        rs.close();
        con.close();


    } catch (ClassNotFoundException e) {
        logger.error("Sorry,can`t find the Driver!");
    } catch (SQLException e) {
        logger.error(e.toString());
    }
    return result.toString();
}

简单复现下
在这里插入图片描述

再看第二段代码,这段代码也是使用了JDBC但使用了PreparedStatement预编译,这回就避免了SQL注入

@RequestMapping("/jdbc/sec")
    public String jdbc_sqli_sec(@RequestParam("username") String username) {

        StringBuilder result = new StringBuilder();
        try {
            Class.forName(driver);
            Connection con = DriverManager.getConnection(url, user, password);

            if (!con.isClosed())
                System.out.println("Connecting to Database successfully.");

            // fix code
            String sql = "select * from users where username = ?";
            PreparedStatement st = con.prepareStatement(sql);
            st.setString(1, username);

            logger.info(st.toString());  // sql after prepare statement
            ResultSet rs = st.executeQuery();

            while (rs.next()) {
                String res_name = rs.getString("username");
                String res_pwd = rs.getString("password");
                String info = String.format("%s: %s\n", res_name, res_pwd);
                result.append(info);
                logger.info(info);
            }

            rs.close();
            con.close();

        } catch (ClassNotFoundException e) {
            logger.error("Sorry, can`t find the Driver!");
            e.printStackTrace();
        } catch (SQLException e) {
            logger.error(e.toString());
        }
        return result.toString();
    }

但是这种预编译在某些情况并不能使用

like模糊查询

例如在使用like进行模糊查询的时候,我们对第二段代码的sql进行修改

select * from users where username like '%?%'

预编译报错

在这里插入图片描述

order by

在order by的情况中也不能使用预编译,因为会将进行排序的字段名解析为字符串导致无法正常排序

若强行预编译

select * from users order by ?

数据库数据如下

在这里插入图片描述

我想根据username进行排序则需要以下sql

select * from users order by username

成功执行顺序是对的

在这里插入图片描述

但是强行预编译会将sql解析成

select * from users order by 'username'

在这里插入图片描述

排序错误导致失去作用
在这里插入图片描述

in

正常情况下的where in

select * from users where id in (1,2,3)

在这里插入图片描述

若强行预编译

select * from users where id in ?

导致结果报错

select * from users where id in '(1,2,3)'

在这里插入图片描述

mybatis

mybatis与hibernate等框架同样存在这些问题,hibernate现在很少用以mybatis为例

Mapper注解未使用占位符预编译存在SQL注入

 @Select("select * from users where username = '${username}'")
 List<User> findByUserNameVuln01(@Param("username") String username);

在这里插入图片描述

Mapper xml未使用占位符预编译存在SQL注入

<select id="findByUserNameVuln02" parameterType="String" resultMap="User">
	select * from users where username like '%${_parameter}%'
</select>

在这里插入图片描述

Mapper xml在排序时未采用占位符预编译存在SQL注入

<select id="findByUserNameVuln03" parameterType="String" resultMap="User">
	select * from users
	<if test="order != null">
    	order by ${order} asc
	</if>
</select>

在这里插入图片描述

安全的mybatis代码

@Select("select * from users where username = #{username}")
User findByUserName(@Param("username") String username);
<select id="findById" resultMap="User">
	select * from users where id = #{id}
</select>
<select id="OrderByUsername" resultMap="User">
	select * from users order by id asc limit 1
</select>

修复

1.可以的话对参数进行类型转换,数字型注入很少出现大多都是字符串拼接

Interge.valueof()

2.占位符预编译,目前最有效的办法

3.like,order by,where in需要特殊处理

例如:

处理like

select * from user where username like concat('%', ?, '%')

处理order by

可以做白名单处理sql

/**
     * 过滤mybatis中order by不能用#的情况。
     * 严格限制用户输入只能包含<code>a-zA-Z0-9_-.</code>字符。
     *
     * @param sql sql
     * @return 安全sql,否则返回null
     */
private static final Pattern FILTER_PATTERN = Pattern.compile("^[a-zA-Z0-9_/\\.-]+$");
    public static String sqlFilter(String sql) {
        if (!FILTER_PATTERN.matcher(sql).matches()) {
            return null;
        }
        return sql;
    }

也可以在java层面做映射处理,例如限制用户输入1或2不同数字对应不同的排序

处理in

可以使用Mybatis自带循环指令解决SQL语句动态拼接的问题

select * from users where id in
	<foreach collection="ids" item="item" open="("separator="," close=")">
		#{item} 
	</foreach>

SQL注入排查

可以使用专业的安全扫描工具也可以进行手动排查

关键字:Select、Dao 、from 、delete 、update、insert

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

信息化带来的制造业生产管理系统究竟有哪些作用呢?

制造业是一个现代国家的经济基础&#xff0c;决定着着国家的兴衰存亡。长期以来人们和国家都对制造业给予高度重视&#xff0c;无论是资金投入还是管理的手段和方法的提高&#xff0c;制造业在生产行业中的优势越来越明显。尤其是随着科学技术的快速发展&#xff0c;制造业的现…

uniapp easycom

easycom 是 uniapp 的一种组件自动引入的规则&#xff0c;使用这种规则可以使满足规则的组件无需注册直接使用。 接下来我们来看一眼效果 这里可以看到我并没有进行组件注册而是直接使用了组件&#xff0c;这样的效果就是通过 easycom 的自定义规则来实现的。 来看一眼我的自…

庐山真面目之——LWIP初探

目录 LWIP简介 网络层协议分层模型介绍 LWIP源代码结构 lwip源码文件说明 lwip的contrib包文件说明 以太网接入MCU方案 LWIP结构框图 LWIP简介 lwIP 是 Light Weight&#xff08;轻型&#xff09;IP 协议&#xff0c;有无操作系统的支持都可以运行。lwIP 实现的重点 是在保…

Android Studio compose的简单使用与案例实现

Compose是Android团队与JetBrain大力推动的新一代UI框架&#xff0c;它能够简化安卓界面的开发&#xff0c;让本来繁琐的xml文件写法变为简便的kt文件写法。 其声明式 UI、更简单的自定义、实时且带交互的预览功能更是让安卓开发锦上添花 android compose框架的使用一.前置知识…

vue+elementUI 使用腾讯地图

效果如下 引入地图qqmap 刚开始我是直接用 npm install qqmap&#xff0c;但是好像只有v1版本的&#xff0c;我需要用v2版本的&#xff0c;所以直接使用script标签加载API服务。 文件&#xff1a;/public/index.html <script charset"utf-8" src"https:…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java双笙映画ou5oj

毕业设计也不需要做多高端的程序&#xff0c;毕业设计对于大多数同学来说&#xff0c;为什么感觉到难&#xff0c;最重要的一个原因&#xff0c;那就是理论课到实践课的转变&#xff0c;很多人一下不适应&#xff0c;本能开始拒绝&#xff0c;如果是一个考试&#xff0c;大家都…

spring boot基于Java的电影院售票与管理系统毕业设计源码011449

电影院售票与管理系统的设计与实现 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对电影院售…

SpringBoot —— 整合RabbitMQ常见问题及解决方案

前言 企业中最常用的消息中间件既不是RocketMQ&#xff0c;也不是Kafka&#xff0c;而是RabbitMQ。 RocketMQ很强大&#xff0c;但主要是阿里推广自己的云产品而开源出来的一款消息队列&#xff0c;其实中小企业用RocketMQ的没有想象中那么多。 至于Kafka&#xff0c;主要还是…

常见的推荐算法原理介绍

常见的推荐算法原理介绍&#xff0c;随着互联网的发展短视频运营越来越精准化&#xff0c;我们身边常见的抖音、火山小视频等软件让你刷的停不下来&#xff0c;这些软件会根据你的浏览行为推荐你感兴趣的相关内容&#xff0c;这就用到了很多推荐算法在里面。 在淘宝购物&#…

Linux 负载均衡介绍之LVS工作模式-DR直接路由模式

Linux 负载均衡介绍之LVS工作模式-DR直接路由模式 图示&#xff1a; 工作原理&#xff1a; ①.客户端将请求发往前端的负载均衡器&#xff0c;请求报文源地址是CIP&#xff0c;目标地址为VIP。 ②.负载均衡器收到报文后&#xff0c;发现请求的是在规则里面存在的地址&#x…

[Java反序列化]—Shiro反序列化(二)

0x01 这篇利用CC链来进行RCE 利用分析 在shiro-web 中加上CC依赖 <dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId><version>3.2.1</version><scope>compile</scope>…

ZKP方案衍变及对比

1. 引言 2019年是ZKP方案创新井喷的一年。 2019年10月&#xff0c;Chiesa在#zk0x04上的分享 State of the SNARG-scape - Alessandro Chiesa (UC Berkeley, StarkWare, Zcash)&#xff0c;有&#xff1a; 根据reference string的类型&#xff0c;可将zk-SNARKs分类为&#…

1.集群环境搭建

1.集群信息概览 2.集群环境搭建 2.1第一台服务器 修改静态ipvim /etc/sysconfig/network-scripts/ifcfg-ens33修改主机名echo first-node /etc/hostname修改主机名映射echo 192.168.226.140 first-node >> /etc/hosts echo 192.168.226.141 second-node >> /…

Redis缓存 缓存穿透+缓存雪崩+缓存击穿的原因及其解决方案

Redis缓存 缓存穿透缓存雪崩缓存击穿的原因及其解决方案 文章目录Redis缓存 缓存穿透缓存雪崩缓存击穿的原因及其解决方案一、缓存穿透是什么&#xff1f;解决方案&#xff1a;二、缓存雪崩是什么&#xff1f;解决方案三、缓存击穿是什么&#xff1f;解决方案一、缓存穿透是什么…

【保姆级·创建对象】如何通过factory-method创建对象

这个步骤在createBeanInstance()方法中有使用&#xff0c;我们先来看下这个方法中都干了些啥(&#xff61;&#xff65;ω&#xff65;&#xff61;)&#xff89; 首先&#xff0c;方法开头确认了beanClass是否被加载&#xff08;因为只有被加载叻的对象才是可以实例化的&#…

深入浅出MySQL事务和锁定语句

https://dev.mysql.com/doc/refman/8.0/en/sql-transactional-statements.html 13.3事务和锁定语句 13.3.1启动事务、提交和回滚语句 开启事务 begin START TRANSACTION提交事务 COMMIT回滚事务 ROLLBACK查询自动提交 show SESSION VARIABLES where variable_name "…

深入浅出InnoDB Locking

https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html 本节讨论的所有锁都是在 InnoDB 引擎下 MySQL 实现行锁定主要使用共享锁和排他锁。也就是常说的读写锁。 A shared (S) lock permits the transaction that holds the lock to read a row. An exclusive (X) l…

若依多租户集成浅析(基于数据源隔离)

背景 这边有个做 saas 化应用的需求&#xff0c;要求做到数据源级别隔离&#xff0c;选了 RuoyiCRM: 基于若依Vue平台搭建的多租户独立数据库CRM系统&#xff0c; 项目不断迭代中。欢迎提BUG交流~ (gitee.com) 这个项目做分析 先放一下码云上作者画的图&#xff0c;后面我把整…

股票量化怎样分析股票数据精准选股?

在日常的股票量化交易过程中&#xff0c;通常有不少的交易者会借助股票数据接口来分析股票数据&#xff0c;并且经过一番股票量化分析之后&#xff0c;做到精准选股也是很有可能的事情。那么&#xff0c;普通投资者进行股票量化怎样分析股票数据选好股呢&#xff1f; 首先来了…

springboot:集成Kaptcha实现图片验证码

文章目录springboot&#xff1a;集成Kaptcha实现图片验证码一、导入依赖系统配置文件二、生成验证码1、Kaptcha的配置2、自定义验证码文本生成器3、具体实现三、校验验证码1、controller接口2、自定义前端过滤器3、自定义验证码处理过滤器4、自定义BodyReaderFilter解决读取bod…