深入了解Java中的SQL注入
创始人
2024-03-21 21:39:40
0

深入了解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 codeStatement 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 codeString sql = "select * from users where username = ?";PreparedStatement st = con.prepareStatement(sql);st.setString(1, username);logger.info(st.toString());  // sql after prepare statementResultSet 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 findByUserNameVuln01(@Param("username") String username);

在这里插入图片描述

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


在这里插入图片描述

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


在这里插入图片描述

安全的mybatis代码

@Select("select * from users where username = #{username}")
User findByUserName(@Param("username") String username);


修复

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

Interge.valueof()

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

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

例如:

处理like

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

处理order by

可以做白名单处理sql

/*** 过滤mybatis中order by不能用#的情况。* 严格限制用户输入只能包含a-zA-Z0-9_-.字符。** @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#{item} 

SQL注入排查

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

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

相关内容

热门资讯

律师进阶:直面对金钱的喜爱 律师这个职业,已经从光鲜亮丽的精英群体逐步走向了平常职业。但是想要做好律师,难度却一点也没减少。 律...
公安部有关部门下发通知要求 依... 本报北京12月26日讯 记者张晨 2026年元旦、春节将至,节令食品和假期餐饮进入消费高峰期。为切实...
重庆建工集团股份有限公司 关于... 本公司董事会及全体董事保证本公告内容不存在任何虚假记载、误导性陈述或者重大遗漏,并对其内容的真实性、...
产能闲置vs退役潮来袭:动力电... 来源:财联社 中国新能源汽车市场连续多年的高速增长,正将动力电池回收产业推至一个关键的十字路口。 财...
*ST建艺[002789]关于... 本版导读 2025-12-27 2025-12-27 2025-12-27 2025...
诺普信定增与减持并行 年内诉讼... 【深圳商报讯】(记者 詹钰叶)深圳诺普信作物科学股份有限公司(下称诺普信)最近连发两条关于实际控制人...
释新闻|美国在公海扣押委内瑞拉... 继在加勒比海域集结大批军力并对涉嫌运送毒品的船只进行打击之后,特朗普如今又把目标对准了油轮。自12月...
亿晶光电科技股份有限公司关于累... 本公司董事会及全体董事保证本公告内容不存在任何虚假记载、误导性陈述或者重大遗漏,并对其内容的真实性、...
重庆四方新材股份有限公司 关于... 证券代码:605122 证券简称:四方新材 公告编号:2025-080 重庆四方新材股份有限公司 关...
深圳市建艺装饰集团股份有限公司... ■ 深圳市建艺装饰集团股份有限公司 关于诉讼的进展公告 本公司及董事会全体成员保证信息披露的内容真实...