记录一个sql注入的漏洞

背景说明

渗透测试的时候,发现图片库的搜索框存在sql注入漏洞,攻击者利用该漏洞可执行’"<>&*等sql语句,造成数据库访问异常,甚至进行脱库

当我们拿着这段sql直接到数据库进行搜索的时候,会发现语法上就直接报错了
在这里插入图片描述


解决

先说结论:我们找到图片的mapper文件,排查sql语句后,将 ${ } 赋值改为 #{ } ,问题解决。如下:

sql语句优化前

<where>
	<trim prefixOverrides = "AND | OR" suffixOverrides = ",">
	<if test = "@Ognl@isNotEmpty(name)">
		AND Name LIKE '%${name}%'
	</if>
</where>

sql语句优化后

<where>
	<trim prefixOverrides = "AND | OR" suffixOverrides = ",">
	<if test = "@Ognl@isNotEmpty(name)">
		AND Name LIKE '%#{name}%'
	</if>
</where>

这里的name字段,在项目中是作为一个变量,后期动态赋值的。那说明进入到mysql里被执行的sql语句,就和开头一样,语法上就有错误。
而 #{ } 和 ${ } 方式都是后期动态赋值,为何 ${ } 会被sql注入呢?这里涉及不得不提到 # 和 $ 的两个知识点了

核心知识点:#和$的区别

mybatis 在对 sql 语句进行预编译之前,会对 sql 进行动态解析。

1、在这个解析阶段里:
#{ } 会被解析为一个 JDBC 预编译语句的占位符“?”传入mysql中。之后无论传什么值进去,在mysql中都只会被当做字符串,而不会被识别为sql语句;
${ }在这个阶段会进行纯粹的String变量替换,也就是传什么值,就替换为什么值,在预编译阶段,传到mysql中的就是一个完成的、已经赋值完成的sql语句。所以,如果传的值包含sql语句,到mysql中时则会被一并执行

2、如果采用#{ } 传值,那后续赋的值,mysql中会自动进行语法修正。(语法修正这一点,从控制台打印实际执行的sql语句就可以验证。在日志配置文件里,将log级别改为debug,即可打印实际执行的sql语句)


示例

给name字段传入一个值 Lucy # Mary

//1、#{ }方式
SELECT * FROM user WHERE name = #{name};
//sql解析后
SELECT * FROM user WHERE name =;
//赋值后,实际传到mysql中的sql语句
SELECT * FROM user WHERE name = 'Lucy # Mary';

//2、${ }方式
SELECT * FROM user WHERE name = ${name};
//sql解析后(直接替换变量值),实际传到mysql中的sql语句
SELECT * FROM user WHERE name = Lucy # Mary;

把这两条sql拿到数据库查询发现:${ }方式赋值后,#后面的内容都被注释掉了。在这里插入图片描述

所以,大部分情况下,咱们都采用 #{ } 方式赋值,来避免sql注入的情况。
那什么时候用 ${ } 呢?

拓展

#和$还有一个小区别:

#{ }在sql解析时不是会被解析为一个标识符“?”吗,而 sql 占位符,替换为字符串时会带上单引号 ''
${ }在sql解析时进行的变量替换,就是个单纯的String替换,所以不会加单引号’’

从这个区别里,我们可以联想到,sql查询里,哪些查询不能加单引号呢?
这里提一个常见的:表名不能加单引号 ‘’(但着重号是可以的)。
在这里插入图片描述
从上图可以发现,表名加单引号会报错。

所以在写sql语句是,我们对表名的取值通常采用${ }方式。

SELECT * FROM ${tableName} WHERE name = #{name};

总结

1、sql动态解析阶段,#{ } 会被解析为一个 JDBC 预编译语句的占位符“?”,而${ }会进行纯粹的String变量替换
2、采用#{ } 传值,mysql中会自动进行语法修正
3、 #{ } 赋值为字符串时会带上单引号 ''


最后,附上参考文档,里面还有很多有趣的东西,可以帮助大家理解~

mybatis深入理解(一)之 # 与 $ 区别以及 sql 预编译
数据库预编译为什么能防止SQL注入呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值