
思路确定
题目是jdk17环境,先看依赖:
1 | <dependency> |
分析一下可用资源:
1、springboot自带的jackson链
2、h2可以打JDBC,能够自定义函数执行,或者直接用JavaScript引擎加载(这个方法在jdk17失效)
3、有tomcat,但是版本比较高,10.1.36,在jndi时也许能用
再看一下题目:
1、从Dockerfile里可以看到,是jre17,而不是jdk17。这意味着我们无法编译代码
2、反序列化入口明显,且没有任何过滤
3、MyDataSource存在getConnection方法,且连接的url可控
综上,能够大概确定思路:
1、jackson触发MyDataSource的getConnection,然后打h2数据库
h2 新打法
一般来说,h2数据库要么用自定义函数执行,或者直接用JavaScript引擎加载。不过这两种这里都不能用。前者因为自定义的函数在jre环境下无法编译,后者是因为jdk17里JavaScript引擎被废除。因此我们需要找新的方法。
如果做过其他jdk17打JDBC的题,就会发现:许多数据库都是可以直接调用Java的public static方法的。h2也不例外,这点可以去翻看官方文档https://h2database.com/html/features.html
或者去问AI验证一下:
那么,我们现在就可以确定怎么打h2 JDBC了。不过我们还需要确定通过什么public static方法去打。
看了wp,发现里面用的是org.springframework.cglib.core.ReflectUtils#newInstance(java.lang.Class, java.lang.Class[], java.lang.Object[])
ReflectUtils是Springboot自带的一个很好用的类,里面还有defineClass。
另外,值得一提的还有org.springframework.util.SerializationUtils#deserialize,这个可以用来二次反序列化。
后面新学了一个rce的方法,就是加载xml。就是通过org.springframework.context.support.ClassPathXmlApplicationContext的构造方法加载恶意xml文件
1 | package solution; |
直接在xml目录下起一个http服务就行。
最后还需要编写一下poc.sql文件。这里也有一个注意点,先展示:
1 | CREATE ALIAS CLASS_FOR_NAME FOR 'java.lang.Class.forName(java.lang.String)'; |
要注意的地方就是@url_str算varchar类型,而我们的newInstance里需要Object[],所以需要找一个public static类,能够把String转为Object。(这里勘误一下,应该是Object转为String。因为最终需要的Object[]里面的内容是String,而现在需要将VERCHAR转为String。并且ARRAY[]只支持String。但是这样下面的查询语句就不对了,也就找不到wp里的那个类了,不知道有没有师傅知道应该怎么解释)用tabby找一下:
搜出来的方法不是很多,排除掉没有exports的模块其实剩的就很少了。我们需要的javax.naming.ldap.Rdn.unescapeValue也在里面。
tabby找新类(失败)
这里我发现org.springframework.scripting.bsh.BshScriptUtils#createBshObject应该也行,给的输入是”new java.lang.Object[]{"http://127.0.0.1/1.xml\"}"就行。然而这个类本身有报错,说是包没导入:
我想既然spring里有这个类,那不应该自动下所需的包吗,不知道这里为什么。
后面又去试了一下createBshObject,发现可能不行。虽然能返回Object[],但是h2sql转化不了,会报类型转化错误,不知道有没有师傅可以解决。
最后觉得应该是必须用 sql 语句自带的 ARRAY 转成 Object 数组,而不能直接传一个 Object[]。然后上面那个缺失包的情况,其实还挺常见的,就是在需要用时,自己把包导入。所以这题就没法用这个新找的链子了。自己找链子又失败了,悲。