代码审计之实战中各类SQL注入漏洞代码分析及其成因分析(以jeecgboot3.5.3为例)
follycat 漏洞分析 1832浏览 · 2025-04-11 09:34

jeecgboot3.5.3版本各类sql注入漏洞代码分析

这篇文章主要分享在实际项目中各类SQL注入漏洞形成的原因,并且使用了较多企业使用的开源项目jeecg-boot为例子,从而进一步理解SQL注入漏洞是如何形成以及为什么会出现sql注入漏洞。

jinmureport中的未授权sql注入(布尔盲注)

CVE-2023-42268以及CVE-2023-41543这俩个漏洞都是依赖这段防护代码进行绕过,并且jeecgboot中存在某些路由无需使用token进行身份检测,可以直接未授权拿到数据库。

这里取的是/jeecg-boot/jmreport/show接口,

首先,可以找到位于org.jeecg.modules.jmreport.desreport.a.a中的show方法。



其造成漏洞的方法为POST访问的show方法

这个方法获取了json数据中的id以及params这俩个参数,并将其放入jmReportDesignService.show中进行数据查询操作。

跟进show方法,找到实现这个接口的org.jeecg.modules.jmreport.desreport.service.a.e类中的show方法。



完整代码如下:

看到json查询部分,这部分代码主要是进行参数的查询以及数据的返回,其中造成漏洞的参数为params参数,所以重点看到getDataById这个方法。

getDataById这个方法很长,这个方法的主要起到通过报表ID来获取报表数据的作用



继续跟进后会走到getDbsql中,这个方法是执行sql语句查询的方法。

进入到getDbSql方法,代码如下

这个方法主要进行sql数据的查询操作,其中包括了对sql语句的校验、过滤以及执行。

其中过滤操作位于i.a方法中,可以跟进该方法,以查看造成该漏洞的过滤代码。

可以看到其过滤的黑名单为" exec |peformance_schema|information_schema|extractvalue|updatexml|geohash|gtid_subset|gtid_subtract| insert | alter | delete | grant | update | drop | chr | mid | master | truncate | char | declare |user()|";,因为其过滤并不完全,没有过滤ascii,having等可以造成注入的代码,从而导致了布尔注入,由于这个路由的代码都没有身份校验,所以无需登录以及token即可完成注入。

exp:

漏洞成因分析

这个漏洞的成因就是黑名单过滤不完全,从而导致了sql注入漏洞。

漏洞修复

作者升级了积木报表的版本,并补全了黑名单。

jeecgboot中的sql注入(时间盲注)

这里分析选择的是/sys/dict/loadTreeData路由,位于org/jeecg/modules/system/controller/SysDictController类中



其完整代码如下:

这段代码中sql校验的代码为SqlInjectionUtil.filterContent(dictCode);其他进行sql语句查询的方法也是用该方法进行校验的,所以跟进到SqlInjectionUtil类中的filterContent方法



代码如下:

fielterContent方法是jeecgboot3.5.3版本中的检测sql语句是否安全的方法,基本上所有进行sql语句查询的方法都调用了这个方法,这个方法首先校验传入参数是否为空,然后进入到checkSqlAnnotation方法继续校验,跟进到checkSqlAnnotation



代码如下:

这个方法首先校验了是否存在违规的字符,然后判断是否有sleep位于参数中。

仔细观察filterContent方法的逻辑,如图,他是先判断违规字符以及sleep是否存在于参数中,然后再进行小写转换的,所以当sleep为大写时,就可以绕过sleep。



这个漏洞还存在于

验证exp:parseSql路由以及其他使用sql查询的路由中

漏洞成因分析

正则表达式不匹配不完全,或者代码逻辑错误,将sleep的匹配放到了将其转换为小写之前。

漏洞修复



作者对正则表达式进行了修改,让其不区分大小写进行匹配sleep。

jeecgboot中的sql注入(普通用户越权查询所有表的信息)

这里分析的同样也是/sys/dict/loadTreeData路由,但造成漏洞的原因与上面的时间盲注漏洞并不相同,这个漏洞是由于没有对用户权限以及用户输入进行有效的过滤,从而导致普通用户可以直接查询到管理员用户的账号密码等信息。

之前在对/sys/dict/loadTreeData路由代码审计的过程中,以及审计完了验证sql语句安全的代码SqlInjectionUtil.filterContent(dictCode);

接下来继续向下分析



可以看到有一个黑名单检测的操作,造成sql注入的代码就是这一段,继续跟进isPass方法,



代码如下:

这个方法通过解析传入的 SQL 语句,获取其中的表格信息,并根据规则检查表格和字段是否合法。如果 SQL 涉及的表或字段在黑名单中,则返回 false,否则返回 true

首先,跟进getQueryTableInfo方法,来查看是如何解析sql语句的



代码如下:

这段代码首先,对字符串进行了检查与拆分,并判断差分字符串的数组长度是否符合预期的3或者4,然后使用getTableName方法来获取表的具体值,因此继续跟进到getTableName方法中。



代码如下:

进入getTableName方法中可以发现其对sys这一类型的表进行了正则操作,以此来维护管理员账号以及密码的安全,但是其过滤并不完全,从而导致了该漏洞的产生。

只需要给表添加别名即可绕过

exp:

漏洞成因分析

对于黑名单的表单正则匹配并不完全,导致出现越权查询漏洞。

漏洞修复

这个漏洞进行了多次修复,其中包括去除前后空格如果表名包含数据库名(即 .),则去除数据库名部分。去除表名中的空格,使用正则表达式去除表名中的空格、括号和反引号等特殊字符。

最终修复代码:



总结

在实战中,造成sql注入的原因主要有下面三点

1sql语句过滤不完全,导致可以进行绕过导致漏洞产生

2代码逻辑错误,导致本来可以进行过滤的操作无法产生效果。

3对用户的查询操作没有进行权限限制,或者限制不完全,从而导致获取到本不应该获取的数据。

0 条评论
某人
表情
可输入 255