12月8日,Apache官方发布安全公告,修复了一个Struts的远程代码执行漏洞S2-066(CVE-2023-50164)。
▌关于 Apache Struts2
Apache Struts2 是一个开源的 Java Web 应用程序开发框架,旨在帮助开发人员构建灵活、可维护和可扩展的企业级Web应用程序。
经过分析和研判,该漏洞利用难度低,攻击者可以通过污染相关上传参数导致目录遍历,在具体代码环境中可能导致上传 Webshell,执行任意代码。
▌影响范围
- 2.5.0 <= Apache Struts <= 2.5.32、
- 6.0.0 <= Apache Struts <= 6.3.0
▌漏洞修复
-
Apache Struts >= 2.5.33
-
Apache Struts >= 6.3.0.2
目前官方已发布新版本修复了此漏洞,敦促受影响的用户尽快更新进行防护,下载链接:https://struts.apache.org/download.cgi#struts-ga
▌漏洞分析
1. 漏洞POC
没有特定的路径,根据具体环境代码
2. 代码分析
参数污染
-
在org.apache.struts2.interceptor.FileUploadInterceptor#intercept 方法中有使用上传添加请求参数
-
通过注释,可以了解该类为文件上传的拦截器,将文件上传相关的参数添加至 HttpParameters 对象中。
-
可以了解到,FileUploadInterceptor 会获取 3 个参数,也就是上面提到的 upload、uploadContentType 和 uploadFileName,开发者可通过在 Action 中定义相关的 setter 方法获取这些参数的内容。
-
而 FileUploadInterceptor 中获取的参数却是来存储在 HttpParameters 类型的对象中。HttpParameters 对参数大小写不敏感, HttpParameters 存储了参数名大写和参数名小写形式的参数,其中一方会把另一方给覆盖掉,通过 setter 方法
-
在 setter 方法打下断点,发现只被调用了一次。根据调用栈中的方法名和经验,可以很直接的了解到是通过反射调用的。只调用了一次必然和方法名的获取逻辑有关,一般和 Bean 相关的,都是根据成员的名称,得到 setter/getter 方法名,例如成员名首字母大写再拼接上 set
-
所以,将构造的请求中的 UPLOAD 改为了 Upload,发现 setter 方法被成功调用了两次。那么后调用的,会覆盖先调用的。根据 execute 的输出可以知道,name=”upload” 覆盖了 name=”Upload”,而这里的相关逻辑,在com.opensymphony.xwork2.interceptor.ParametersInterceptor#setParameters 代码中体现
-
原本在 HttpParameters#parameters 成员中,顺序是小写在前,大写开头在后『HashMap』,而这里的 acceptableParameters 类型为 TreeMap,从 HashMap 中读取内容再插入 TreeMap 后顺序发生了变化。
-
由此可以知道,可以通过小写模式,覆盖首字母大写模式的参数内容了。
目录穿越
-
目录穿越在 JakartaMultiPartRequest#processUpload 的逻辑,上传的内容路径并不可控,文件上传参数存储在 Commons Fileupload 库创建的临时文件中,文件名也不可控。
-
FileUploadInterceptor#intercept 中在获取上传的文件名时,会通过 JakartaMultiPartRequest#getCanonicalName 方法会对获取的文件名进行截断
所以使用如下方式进行请求不会成功
-
目录穿越无法发生在 Struts 框架中,根据 S2 历史漏洞的特点,只能是在二次开发的业务代码中。
-
业务逻辑自身没有做检查就可能导致目录穿越发生,只要覆盖掉 Action 中 uploadFileName 这个成员就可以了,name=”uploadFileName” 在 JakartaMultiPartRequest#processUpload 中会被识别为表单参数,而非文件参数,所以其内容也不会经过 FileUploadInterceptor。而参数最终都会经过 ParametersInterceptor#setParameters 添加至 Action 中
文件上传
根据具体业务逻辑代码,如果自身没做检查,就可能导致文件上传,进而导致命令执行。
塞讯验证规则
12月12日,针对该漏洞的攻击模拟已经加入到塞讯安全度量验证平台中,您可以在塞讯安全度量验证平台中搜索关键词“Struts2”或“CVE-2023-50164”获取相关攻击模拟验证动作,从而验证您的安全防御体系是否能够有效应对该漏洞,平台以业界独有方式确保您的验证过程安全无害。