漏洞介绍
Adobe ColdFusion是一种用于构建动态Web应用程序的服务器端编程语言和开发平台。它由Adobe Systems开发和维护。ColdFusion的主要目标是简化Web应用程序的开发过程,通过提供一个强大且易于使用的平台,使开发人员能够快速构建功能丰富的Web应用。
Adobe ColdFusion 2018 Update 15 和 2021 Update 5 版本及以前,存在一处文件包含漏洞。攻击者可以利用该漏洞在服务器上执行任意代码。
漏洞范围
Adobe ColdFusion < 2018.0.16、Adobe ColdFusion < 2021.0.6
漏洞靶场
使用vulhub的靶场:
使用环境为Coldfusion 2018.0.15
vulhub-master/coldfusion/CVE-2023-26360
1 | docker-compose up -d |
等待一段时间后环境启动成功,访问http://your-ip:8500/CFIDE/administrator/index.cfm,输入密码vulhub,即可成功安装Adobe ColdFusion。
漏洞原理
网上的漏洞利用入口为 /cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/filemanager.cfc ,我们就先来分析 ***.cfc** 的路由处理逻辑。从 web.xml 配置文件里面可以看到,该路由的处理类为 coldfusion.bootstrap.BootstrapServlet 。而这个类只是一个入口类,实际处理类为 coldfusion.xml.rpc.CFCServlet 。

coldfusion\cfusion\wwwroot\WEB-INF\lib\cfmx_bootstrap.jar!\coldfusion\bootstrap\BootstrapServlet.class#L60-L90, L223-L246
在 coldfusion.xml.rpc.CFCServlet 这个类里,使用 IPFilterUtils.checkAdminAccess() 函数来判断当前路由用户是否有权限访问。然而这个函数使用了 req.getRequestURI() 和 startsWith() 来判断权限,明显存在绕过。例如:原先访问 /CFIDE/adminapi 会被限制,现在改成 /CFIDE//adminapi 即可绕过程序检测。这处绕过,也就是后面的 CVE-2023-29298 漏洞。

coldfusion\cfusion\lib\cfusion.jar!\coldfusion\xml\rpc\CFCServlet.class#L213-L219
本次我们分析的是 CVE-2023-26360 ,继续往下跟代码逻辑。Adobe ColdFusion 程序根据不同的请求类型(CFC或者Axis),创建对应的 filterchain 。在 CFC 对应的的 filterchain 中,我们需要关注 GlobalsFilter、ComponentFilter 这两个 filter 。

第一个过滤器 GlobalsFilter ,主要用来初始化请求相关信息,并将这些信息封装在不同的 scope 里。后续 POC 中的部分参数,就是从这些 scope 中获取,所以这里稍微关注下就行。

coldfusion\cfusion\lib\cfusion.jar!\coldfusion\filter\GlobalsFilter.class#L16-L25
coldfusion\cfusion\lib\cfusion.jar!\coldfusion\filter\FusionContext.class#L254-L354
第二个过滤器 ComponentFilter ,就是本次漏洞要关注的核心类了。这里,我们需要重点关注以下3个部分。
- 第1个部分:我们需要将 urlScope.get(“_cfclient”) 设置为 true ,这样才能触发到后续的漏洞点。而 urlScope 中的数据来自 GET 请求数据,所以我们正常设置 _cfclient=true 就行。
- 第2个部分:这里调用了 FilterUtils.GetArgumentCollection(context) ,该函数主要是将用户请求数据重新封装起来。在函数里面,我们关注到调用了 WDDXDeserialize() ,存在一个反序列化操作。这处也就是后续的 CVE-2023-29300 漏洞,本文暂不讨论。
- 第3个部分:这处会把第2步封装好的数据,传给 JSONUtils.deserializeJSON() 函数处理。这个函数调用栈比较长,我们下面会逐步分析。

coldfusion\cfusion\lib\cfusion.jar!\coldfusion\filter\ComponentFilter.class#L38-L212
在 JSONUtils.deserializeJSON() 函数中,程序会从用户请求数据中取 classname 数据,然后将其传给 TemplateProxyFactory.resolveFile() 函数。

coldfusion\cfusion\lib\cfusion.jar!\coldfusion\runtime\JSONUtils.class#L1110-L1166
coldfusion\cfusion\lib\cfusion.jar!\coldfusion\runtime\JSONUtils.class#L1562-L1592
TemplateProxyFactory.resolveFile() 函数,会根据传进来的文件路径,去加载对应的类。如果我们指定的路径文件不是标准的 Java 字节码文件,程序会自动把他编译成字节码文件,最终缓存至 /app/WEB-INF/cfclasses/ 目录下。新编译的类继承自 coldfusion.runtime.CFPage ,并且程序最终会调用新编译类的 runPage() 方法。我们可以来看一下,当模板文件名为 ../../../../../../../../../../../../../etc/passwd 时,程序编译后的字节码文件如下:

那么通过这一特性,我们就能达到任意文件读取的效果。在审计代码时,我们会发现这个系统上自带一些 cfc 文件。这些文件里面出现了很多特殊标签,如 cfinclude、cffunction、cfargument、cfset、cfif 等。通过查询资料,我们发现这些标签都属于 CFML(ColdFusion Markup Language)语言的一部分。那么我们就可以通过翻阅官方手册,找一些危险函数来达到 RCE 的目的。
例如:写文件函数

例如:命令执行函数

最终的利用思路:将 CFML 语句通过报错写入日志文件中,然后再通过 CVE-2023-26360 漏洞编译、执行日志文件实现 RCE 。
漏洞复现
发送如下请求即可读取文件/proc/self/environ:
1 | POST /cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/iedit.cfc?method=foo&_cfclient=true HTTP/1.1 |
可以在返回包中找到Adobe ColdFusion的根目录/opt/coldfusion/cfusion:

从../../../../../../../../opt/coldfusion/cfusion/lib/password.properties中读取服务器密码:
1 | POST /cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/iedit.cfc?method=foo&_cfclient=true HTTP/1.1 |

想要利用文件包含漏洞执行任意代码,需要先发送如下请求来写入CFM脚本:
1 | POST /cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/iedit.cfc?method=foo&_cfclient=true HTTP/1.1 |
然后包含日志文件,执行该CFM代码:
1 | POST /cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/iedit.cfc?method=foo&_cfclient=true HTTP/1.1 |
可见,id命令的执行结果已经被写入/tmp/success:

exp使用
https://github.com/yosef0x01/CVE-2023-26360
1 | python CVE-2023-26360.py http://192.168.159.132:8500/ "../../../../etc/passwd" /CFIDE/AIR/Conflict.cfc |

参考
https://xz.aliyun.com/news/12835
https://github.com/vulhub/vulhub/blob/master/coldfusion/CVE-2023-26360/README.zh-cn.md