Java安全之深入了解SQL注入

news/2024/7/24 12:43:11 标签: java, sql, 数据库, 后端, web安全

深入了解Java中的SQL注入

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

JDBC

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

java">@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注入

java">@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进行修改

sql">select * from users where username like '%?%'

预编译报错

在这里插入图片描述

order by

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

若强行预编译

sql">select * from users order by ?

数据库数据如下

在这里插入图片描述

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

sql">select * from users order by username

成功执行顺序是对的

在这里插入图片描述

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

sql">select * from users order by 'username'

在这里插入图片描述

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

in

正常情况下的where in

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

在这里插入图片描述

若强行预编译

sql">select * from users where id in ?

导致结果报错

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

在这里插入图片描述

mybatis

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

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

java"> @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代码

java">@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.可以的话对参数进行类型转换,数字型注入很少出现大多都是字符串拼接

java">Interge.valueof()

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

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

例如:

处理like

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

处理order by

可以做白名单处理sql

java">/**
     * 过滤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.niftyadmin.cn/n/14726.html

相关文章

ADSP-21489的图形化编程详解(3:音效开发例程-直通三个例程讲清楚)

Fireware 烧写好了之后&#xff0c;SigmaStudio 图形化开发的基本条件就达成了。我们重新来链接一下硬件&#xff0c;进入图形化编程的阶段&#xff0c;这个阶段我尽量多写一些例程&#xff0c;让大家能够尽快熟悉这个软件开发的全过程。 1. 直通&#xff08;1&#xff09; 1&…

【前端】前端监控体系

文章目录一、所需的数据1.1、生命周期数据1.2、HTTP测速数据1.3、系统异常数据1.4、用户行为数据1.5、用户日志二、埋点与收集2.1、数据埋点2.1、数据上报2.3、数据监控对于一个应用来说&#xff0c;除了前期的开发和设计&#xff0c;在项目上线后端维护很重要&#xff0c;其中…

免费分享20套微信小程序源码 源码免费下载【强烈推荐】

淘源码&#xff1a;国内知名的源码免费下载平台 微信小程序源码包括&#xff1a;商城系统、点餐外卖、垃圾分类、预约洗车、物业管理、校园跑腿、驾考学习、会议预约、图书管理、智能停车、在线答题等小程序源码。 源码分享&#xff0c;文末获取源码&#xff01; 1、JAVA微信…

2022建筑架子工(建筑特殊工种)考试练习题及在线模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2022建筑架子工(建筑特殊工种)考试题模拟考试题库为建筑架子工(建筑特殊工种)理论题库考前必练习题目&#xff01;2022建筑架子工(建筑特殊工种)考试练习题及在线模拟考试依据建筑架子工(建筑特殊工种)考前押题。建筑…

NPDP考试倒计时,如何高效提分?

NPDP的中文名称是产品经理国际资格认证&#xff0c;英文全称New Product Development Professional(NPDP)&#xff0c;由美国产品开发与管理协会&#xff08;PDMA&#xff09;所发起&#xff0c;是国际公认的唯一的新产品开发专业认证。2022年12月11日的考试就快到了&#xff0…

2022CTF培训(五)字符串混淆进阶代码自解密

附件下载链接 复杂的字符串混淆 原理 之前的字符串混淆是一次性解密的&#xff0c;找到解密函数即可获得所有字符串&#xff0c;同时执行解密函数后内存中也可直接获得所有字符串。 因此对抗人员升级了混淆技术&#xff0c;使得解密仅在使用时发生&#xff0c;从而避免了全部…

一个很骚的sql报错:分页查询,每次返回数据可能不同

主表&#xff1a;bdg_budget_project 辅表&#xff1a;bdg_budget 关系&#xff1a;一对一关系 问题&#xff1a;相同sql &#xff0c;分页查询&#xff0c;多次点击&#xff0c;返回的数据可能不同 原因&#xff1a;排序字段是辅表的字段【具体原理暂时没弄明白&#xff0c;…

适用于现代制造业的ERP系统有哪些?

现代ERP系统连接着企业的每个部门和各个方面&#xff0c;当今市场上的ERP系统非常灵活&#xff0c;提供各种工具、特性和功能&#xff0c;旨在满足不同行业的独特需求和挑战。 现代ERP解决方案不仅包括基于项目的制造、供应链管理以及财务和会计能力&#xff0c;而且还具有高级…