Confluence CVE-2023-22515分析
2023-10-11 10:35:59

参考:

https://attackerkb.com/topics/Q5f0ItSzw5/cve-2023-22515/rapid7-analysis

https://mp.weixin.qq.com/s/rIfYrO1i4LPpgCGyxSLHUg

https://blog.s1r1us.ninja/research/brokenconflu

漏洞复现和分析

复现起来非常简单,在首页加上参数

1
/login.action?bootstrapStatusProvider.applicationConfig.setupComplete=false

就能访问 /setup 添加管理员了

1
/setup/setupadministrator-start.action

原理也很简单,因为在默认的 interceptor 中包含了一个:

1
com.atlassian.xwork.interceptors.SafeParametersInterceptor

它继承了父类并且调用了 super.doIntercept(invocation)

1
com.opensymphony.xwork2.interceptor.ParametersInterceptor

image-20231011111721707

image-20231011110906031

这里做的东西大概就是获取参数然后进入到 setParameters,这部分和 S2-003 那个洞一样的入口,都是这个 ParametersInterceptor

https://zhzhdoai.github.io/2020/12/24/Struts2%E6%BC%8F%E6%B4%9E%E7%AC%94%E8%AE%B0%E4%B9%8BS2-003/

7.x 的分析

那么为什么 7.x 的版本没有呢,因为关键类 SafeParametersInterceptor 并没有继承 ParametersInterceptor,然后整体也没有调用到这个 ParametersInterceptor

虽然 SafeParametersInterceptor 这个类也是有一些 ognl 的操作的,但是他有一个函数:

image-20231011111929964

进入函数,测试调用一下会发现 a.b 也会返回 false:

image-20231011112037230

稍微看一下:

image-20231011112242023

能看到这里最基本的就是不能有 .,有的话就需要进入 isSafeComplexParameterName 再额外一些判断,这里就不细跟了。

8.5.2 的修复

8.5.2 中,依然会继承 ParametersInterceptor,但是它会过经过一些判断

首先就是:

1
com.opensymphony.xwork2.interceptor.ParametersInterceptor#setParameters

image-20231011154100685

这里判断是否是可接受的参数:

1
com.opensymphony.xwork2.interceptor.ParametersInterceptor#isAcceptableParameter

image-20231011154139630

然后跳过一些判断,直接讲两个比较关键的判断,首先是判断是否是 acceptable 的,就是要满足这个正则:

1
com.atlassian.xwork.interceptors.SafeParametersInterceptor#isAcceptableParameter

这里的:

1
acceptedPatterns = \w+((\.\w+)|(\[\d+])|(\['\w+']))*

然后就是这里:

1
com.atlassian.xwork.interceptors.SafeParametersInterceptor#isSafeComplexParameter

image-20231011152057161

首先是最上面的 com.atlassian.xwork.interceptors.SafeParametersInterceptor#isComplexParameter,判断如果包含 . 或者满足这个正则 ".*\\['\\w+']" 就代表复杂。

复杂的话就会获取 Descriptors 然后又要判断方法是否有 ParameterSafe 这个注解(基本是不用看了感觉~

总结一下,首先是必须要满足上面的 acceptedPatterns,然后最好不要满足 isComplexParameter

这里举个例子,比如:

1
a[0] = 1

这里 0

修复对比

说了这么多,好像还没说新旧版本具体的区别,其实就是在新版的:

1
com.atlassian.xwork.interceptors.SafeParametersInterceptor

多了个函数 isAcceptableParameter

image-20231011155444522

这个函数做了一些额外的判断,在旧版本是没有的。

虽然默认来说

1
com.opensymphony.xwork2.interceptor.ParametersInterceptor

这个类有个默认的 isAcceptableParameter 函数,但是并没有起到非常具体的过滤作用,新版本的判断了要 set 的方法是否存在 ParameterSafe 的注解。

一些扩展思考

其实类似的判断在 7.x的版本就有了:

1
com.atlassian.xwork.interceptors.SafeParametersInterceptor#isSafeParameterName(java.lang.String, com.opensymphony.xwork.Action, boolean)

判断了是否包含 . 啊,是否符合 a['b'] 这样的格式啊。

image-20231011165826202

然后 isSafeComplexParameterName 下面就是判断了 write 的方法是否是 ParameterSafe 这个注解。

在最上面的第三个参考链接中提到了一个绕过方式,就是:

1
?a['a'][0]=abc

这样的方法,为什么可以绕过这个函数呢:

第一个比较严苛的条件:

image-20231011170438324

首先是需要符合这个正则:

1
\w+((\.\w+)|(\[\d+\])|(\['[\w.]*'\]))* 

a['b'][数字] 这样的格式是可以过的

然后到 else

image-20231011170836117

不能符合这个正则:

1
.*\['[a-zA-Z0-9_]+'\]

然后如果能找到这样的方式利用的话,7.X 也就可以利用了。

Prev
2023-10-11 10:35:59
Next