jeecgboot智能开发平台任意代码执行漏洞
JeecgBoot的发平漏洞公告是去年底在几个安全圈子里传开的,但真正让事情变得微妙的台任是,很多用这套低代码平台的意代公司,压根不知道自己线上跑着哪个版本。码执一个做供应链系统的行漏朋友告诉我,他们前端页面上还挂着JeecgBoot的发平默认Logo,后端接口却早就被改得面目全非——这种“半定制”状态,台任恰恰是意代漏洞利用链最舒服的温床。
问题出在 jmreport 这个报表模块。码执JeecgBoot为了做可视化数据查询,行漏开放了一组 /jmreport/queryFieldBySql 之类的发平接口,允许前端传SQL片段过来执行。台任设计初衷是意代给报表设计器用的,但没做严格的码执权限校验和SQL语法过滤。攻击者只要构造一个带 select ... into outfile 或者 updatexml 报错注入的行漏请求,就能把数据库里的数据带出来。更狠的是,如果数据库账号有写文件权限,直接往Web目录写个JSP木马,服务器就归别人了。
我复现过一版3.5.0的漏洞环境。用Burp抓包,把 POST /jeecg-boot/jmreport/queryFieldBySql 的 sql 参数改成 select '<% out.println("pwned"); %>' into outfile '/opt/tomcat/webapps/ROOT/test.jsp',返回包直接报语法错误——但错误信息里带了文件路径。换用UNION SELECT配合load_file()读/etc/passwd,成功回显。整个过程不需要登录,因为该接口在部分版本里被错误地加入了白名单。
官方在3.5.3版本里修了,补丁方式是给jmreport接口加了@PermissionData注解,并强制校验SQL关键字黑名单。但黑名单这东西,绕过的姿势太多了。比如用/*!50000select*/这种内联注释,或者把select拆成se/**/lect。我试过在3.5.3上跑同样的payload,确实被拦了,但换成MySQL的handler语句读表,又绕过去了。所以严格来说,这不是一个“修好了”的漏洞,而是一个“被临时堵住”的入口。
真正让人头疼的是资产测绘。ZoomEye上搜app:"JeecgBoot",国内能匹配到两千多个独立IP,其中将近三成还开着jmreport的默认路径。有些是测试环境忘了关,有些是开发人员图省事,直接把/jeecg-boot/jmreport/*加进了Spring Security的permitAll列表。我甚至见过一个政务云上的实例,数据库账号是root,密码是jeecg@2023——这种配置配上任意SQL执行,基本等于把大门钥匙插在锁孔上。
低代码平台的安全困境在这里暴露得很典型:为了降低使用门槛,把大量高危能力包装成“开箱即用”的接口。报表要支持动态SQL,流程要支持脚本节点,这些功能在演示环境里跑得飞快,一上生产就成了攻击者的跳板。JeecgBoot不是第一个,也不会是最后一个。我翻过它的更新日志,从3.4到3.6,光jmreport模块就修了四次SQL注入相关的问题,每次都是“增加过滤规则”,而不是从架构上把SQL执行权限收回到服务端白名单里。
如果你正在用这套平台,别只看版本号。打开浏览器开发者工具,手动请求一下/jmreport/queryFieldBySql,随便传个sql=select 1,看看返回什么。如果直接返回了查询结果,哪怕版本号写着3.5.3,也说明补丁没打全。更稳妥的做法是直接在Nginx层把/jmreport/路径对公网封死,只允许内网IP访问。至于那些已经暴露在公网上的实例,建议查一下数据库的general_log,看看有没有人执行过into outfile——很多入侵痕迹不会留在Web日志里,但数据库会记得。
漏洞本身不复杂,复杂的是那些跑在业务关键路径上的老版本系统。没人敢随便升级,因为改过源码,一升就崩。这种“带病运行”的状态,才是安全圈里最真实的日常。
```(责任编辑:综合)













