0x00:背景

​ shiro反序列化RCE是在实战中一个比较高频且舒适的漏洞,shiro框架在java web登录认证中广泛应用,每一次目标较多的情况下几乎都可以遇见shiro,而因其payload本身就是加密的,无攻击特征,所以几乎不会被waf检测和拦截。

0x01:shiro反序列化的原理

先来看看shiro在1.2.4版本反序列化的原理

这里是shiro拿到cookie后的关键代码,先decrypt再反序列化

跟到decrypt方法

调用具体的cipherService,传入加密后的数据和cipherKey进行解密

getDeryptionCipherKey()获取的值也就是这个DEFALUT key,硬编码在程序中

查看CipherService接口的继承关系,发现其仅有一个实现类JcaCipherService(静态可以这样看,动态调试会直接跟进去)

查看实现类的decrypt方法,可以看到iv即ciphertext的前16个字节,因为iv由我们随机定义并附加在最后的ciphertext前面,也就是说只要知道key即可构造反序列化payload

key是硬编码,后续官方修改为获得随机key,但正如一开始所说,存在开源框架配置硬编码key,因此在1.4.2以前很多shiro都可以通过略微修改脚本遍历高频key的方式去攻击,下图举例,github上有很多类似这样的代码

CBC算法的shiro生成payload的关键代码如下,也就是我们通用的生成shiro攻击代码

python中有实现aes-cbc的算法,通过指定mode为AES-CBC,遍历key,随机生成iv,配合ysoserial的gadget即可生成payload

BS = AES.block_size

pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()

mode = AES.MODE_CBC

iv = uuid.uuid4().bytes

file_body = pad(file_body)

encryptor = AES.new(base64.b64decode(key), mode, iv)

base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))

return base64_ciphertext

0x02:高版本下的利用

而在1.4.2以后由于padding oracle的影响,shiro官方把加密方式改为了GCM,所以我们需要更改脚本,添加GCM下的攻击方式去攻击高版本的shiro,通过跟踪代码动态调试可以看出确实是使用GCM加密

所以shiro的攻击脚本中的核心代码我们来修改一下,GCM加密不需要padding,但需要一个MAC值(也就是我代码里的tag),这块可以自己跟一下源码,核心代码如下:

iv = os.urandom(16)

cipher = AES.new(base64.b64decode(key), AES.MODE_GCM, iv)

ciphertext, tag = cipher.encrypt_and_digest(file_body)

ciphertext = ciphertext + tag

base64_ciphertext = base64.b64encode(iv + ciphertext)

return base64_ciphertext

0x03:获得key&回显&内存shell

从三月到八月有很多师傅写了很多文章集中在shiro的利用上,我也综合了各位师傅的想法和思路搞了一些脚本

1.key检测:

以前的脚本批量检测shiro的存在或者说获得key我们用到最多的还是ysoserial中的urldns模块,不过这个有一个问题就是如果不出网的话会有问题,所以这里还有一个新的办法就是使用一个空的SimPlePrincpalCollection作为我们要序列化的对象,也就是构造一个正确的rememberMe触发反序列化,如果key是正确的,响应包中不会返回rememberMe=deleteMe,这里一开始我想在脚本中通过检测返回包中是否有deleteMe关键字来做判断,结果发现有一些环境本身就会返回rememberMe=deleteMe,因此最终选择了一个比较暴力的方式,关键代码如下

r1 = requests.get(target, cookies={'rememberMe': "123"}, timeout=10, proxies=PROXY,

verify=False, headers=myheader,allow_redirects=False)

rsp1=len(str(r1.headers))

#这里我先给一个肯定不正确的rememberMe

try:

for key in keys:

print("[-] start key: {0}".format(key))

if ciphertype == 'CBC':

payload = CBCCipher(key,base64.b64decode(checkdata))

if ciphertype == 'GCM':

payload = GCMCipher(key,base64.b64decode(checkdata))

payload = payload.decode()

#print(payload)

r = requests.get(target, cookies={'rememberMe': payload}, timeout=10, proxies=PROXY,

verify=False, headers=myheader,allow_redirects=False) # 发送验证请求

rsp = len(str(r.headers))

if rsp1 != rsp and r.status_code != 400:

#在这里和肯定不正确的返回包header的lenth做比较,如果有差异,则是正确的的key

print("!! Get key: {0}".format(key))

exit()

当然这样也有可能存在误报,大家可以酌情修改,用起来是这样

2.回显:

回显这个点也是有很多师傅发了很多文章,从一开始linux下的半回显到kingkk师傅的tomcat通用半回显再到c0ny1师傅的半自动化挖掘再到fnmsd师傅的通用回显,中间也穿插着其他师傅的文章这里就不列出来了,当然最终我用的也是fnmsd师傅的代码,一路跟了这些文章过来不得不感慨师傅们真是tql以及这种不断提出新思路不断完善的过程实在令本菜鸡拍断大腿。

fnmsd师傅用的其实也是c0ny1师傅的思路,就是在当前线程对象里搜索request对象,判断请求头中是否存在指定请求头,再从response对象里获取输出。

fnmsd师傅也对代码里存在的几个小问题做了好几个版本的修改,最终我在实际运用的时候依然存在一点点问题就是师傅设置的深度优先搜索是52层,结果测试时还是遇到了52层没有搜到的情况,结果随意改成100层就找到了.... 以及在用ysoserial里面有的cc链比较长生成出来的payload差不多逼近了tomact默认对header的限制长度,有点危险。nginx就不说了直接凉,如果遇到nginx需要换个思路,比如可以尝试先分段注入,最后再执行。

代码就不贴了,列一下师傅的文章,他有给出代码

先跑一下测试能不能回显,效果如图

再把输出的payload粘贴到burp中执行命令

3.内存webshell

其实严格来说在回显里提到的kingkk师傅做的是内存webshell,一开始是有点混杂的,但其实跟一路会发现内存和webshell到最后利用的点是不一样的,内存webshell的思路是注册filter(当然还有观星的师傅写的通杀spring的,思路是注册controller,链接在此 基于内存 Webshell 的无文件攻击技术研究),其实在有了fnmsd师傅思路比较好的回显之后,内存webshell可能需求就不太大了,但有时候红队可能需要一个内存shell来维持权限(?)或者需要配合reGeorg代理进内网,所以这个东西还是有必要的

一开始看到threedr3am师傅的基于tomcat的内存 Webshell 无文件攻击技术文章,解决了shiro下的利用,也能做到勉强通杀tomcat(除了tomcat6,原因可看评论区,这个我没测试),但是遇到sihro有一个最大的问题就是长度,没错,这个长度超大发了。菜鸡如我也上蹿下跳试图通过修改ysoserial和payload的代码缩短payload,事实证明我确实不行,长亭师傅的解决办法看了一眼感觉不是特别好用,再加上后来又继续去跟了回显,就没管这个了。后来又看到了涙笑师傅的思路,解决了长度的问题

涙笑师傅的文章:

其实原理就是在cookie中反序列执行的代码只是插入了一个我们自定义的ClassLoader,这块长度很小。在这个ClassLoader中反射调用defineClass方法,这个方法的byte参数从POST参数中取出来。也就是把我们注册filter的这段payload写在static代码块里,编译后的byte再通过POST传递,自定义ClassLoader加载时会自动执行static代码块的代码。

攻击的时候先生成payload,上面是最终要执行的类,下面是rememberMe中要执行的插入classloader的payload

在burp里是这样:

要注意classData一定要url编码,我刚开始测试没注意这点一直不成功。

涙笑师傅的文中给出了配合reGerog的payload,这里就不粘贴了。

4.内存webshell适配:

后面还有一个问题就是内存webshell怎么适配冰蝎,因为冰蝎用的pageContext类在springboot里面是没有的,所以解决方案一个是反编译后修改冰蝎的代码重新打包,这一块虽然能做出来,但是不通用,而且比较麻烦,有师傅在先知发过文,可以参考冰蝎改造之适配基于tomcat Filter的无文件webshell

另外一个思路就是不改冰蝎的服务端,改内存webshell,也看到有师傅发的文,思路是沿用涙笑师傅通过自定义classloader,接着先注入一个pageContext类,再注入内存webshell,链接在此 冰蝎改造之不改动客户端=>内存马,有兴趣的师傅可以去研究一下。

然而不知道是我学艺不精还是师傅的文章写的有点模糊(划掉),我总感觉在类加载机制下,这样做好像有点不对劲的地方,而我也确实没搞出来,一直报错,希望这位师傅如果看到这篇文章可以联系一下弟弟,ddddhm,我找了半天也不知道怎么联系上您。

0x04:后记

上文涉及到的所有脚本和我修改后的ysoserial包将在github中放出

才疏学浅,也是第一次做java安全的研(zong)究(jie)和分享,其他的工作也很多导致shiro研究的断断续续,文章也写得断断续续,时间跨度拉的很大,长达好几个月,后面写的时候很多的东西都快忘记了,因此文章中可能存在错误和疏漏,希望师傅们不吝指出。

最后感谢上文中提到的每一位师傅和部分没有提到的师傅,感谢你们无私的分享,才会让菜鸡如我学习到这么多知识。

shiro 内存马_深入利用Shiro反序列化漏洞相关推荐

  1. 内存马检测与利用研究的优秀文章汇总

    出品|MS08067实验室(www.ms08067.com) 随着攻防技术演变,传统形式的jsp木马已经不能满足攻击者的需求,因此内存马(无文件落地Webshell)重回大众视野,成为RedTeam广 ...

  2. java反序列化漏洞POP查找_利用 Java 反序列化漏洞在受限环境下获取反向 Shell

    原标题:利用 Java 反序列化漏洞在受限环境下获取反向 Shell 原文链接: https://medium.com/abn-amro-red-team/java-deserialization-f ...

  3. 利用Java反序列化漏洞在Windows上的挖矿实验

    最近,安全社区中有很多人都在讨论如何利用Java反序列化漏洞来攻击类似Apache.SOLR和WebLogic之类的系统.不说废话,我们直接进入正题.目前绝大多数的此类攻击针对的都是Linux/Uni ...

  4. shiro 内存马_Tomcat 内存马检测

    随着HW.攻防对抗的强度越来越高,各大厂商对于webshell的检测技术愈发成熟,对于攻击方来说,传统的文件落地webshell的生存空间越来越小,无文件webshell已经逐步成为新的研究趋势. 三 ...

  5. 『Java安全』Tomcat内存马_动态注册Listener内存马

    『Java安全』反序列化- 文章目录 前言 Tomcat Servlet API Listener介绍 ServletRequestListener介绍 ServletRequestListener调 ...

  6. 『Java安全』Tomcat内存马_动态注册Servlet内存马

    文章目录 Servlet调用流程分析 1. StandardContext.startInternal注册servlet 2. StandardContextValue.invoke获取wrapper ...

  7. java序列化_技术干货 | JAVA反序列化漏洞

    目录 反序列化漏洞 序列化和反序列化 JAVA WEB中的序列化和反序列化 对象序列化和反序列范例 JAVA中执行系统命令 重写readObject()方法 Apache Commons Collec ...

  8. 00005在java结果输出_浅谈Java反序列化漏洞原理(案例未完善后续补充)

    摘要: 0005,这个16进制流基本上也意味者java反序列化的开始:(2)HTTP:必有rO0AB,其实这就是aced0005的base64编码的结果:以上意味着存在Java反序列化,可尝试构造pa ...

  9. Shiro反序列化漏洞综合

    原因:Apache Shiro框架提供了记住我的功能(RememberMe),用户登陆成功后会生成经过加密并编码的cookie,在服务端接收cookie值后,Base64解码–>AES解密–&g ...

最新文章

  1. Java后台开发Tomcat添加https支持小程序开发过程
  2. JavaScript数据结构与算法——链表详解(上)
  3. linux常用命令大全(转)好东西要分享
  4. halcon中面到面的距离_halcon学习笔记——(8)由标定板得到测量平面位姿-阿里云开发者社区...
  5. 上位机获取单片机发来的数据并进行检验(完整版,附完整源码)
  6. 【clickhouse】Application: DB::Exception: Duplicate interserver IO endpoint: DataPartsExchange
  7. Tomcat学习总结(19)—— 为什么首选Tomcat作为JavaWeb应用服务器?
  8. td和div超出部分隐藏的区别和用法
  9. openssl ca文档翻译
  10. python图片变清晰的软件_Python功能确实非常强大!不止PS可以美化照片Python也可以!满分...
  11. 前程无忧网站大数据职位信息分析可视化(源码)
  12. 249PHP等于多少钱,一百万新台币等于多少人民币
  13. android导出微信朋友圈怎么发文字,微信朋友圈怎么发纯文字?看完这篇文章,你就知道该怎么操作了...
  14. [SIGMOD 2022]DMCS Density Modularity based Community Search
  15. 记录一次微信小程序+阿里云oss的配置步骤和方法
  16. TIME_WAIT和CLOSE_WAIT的区别
  17. fft函数图像横坐标是什么_FFT结果的物理意义
  18. [流表] ovs常规操作
  19. 【物理应用】基于傅里叶伽辽金谱法二维纳维-斯托克斯附matlab代码
  20. 苹果应用商店AppStore审核中文指南(译本)

热门文章

  1. 360安全卫士静态页面(html+css)
  2. 安全-认证授权、数据脱敏
  3. Nginx 配置文件常用配置详解
  4. idea非活动变更列表中的文件被修改_互动活动策划别抓瞎,用这13条套路搞定!...
  5. 内容分发技术平台_内容分发平台及排名_编辑机器人|Giiso智搜
  6. shuriken粒子系统(5)
  7. linux文件中的注释符号,Linux中特殊符号的作用
  8. 学校计算机室发生火灾自救,强化师生消防意识 筑牢学校安全堡垒
  9. “卜算子·大数据”学习系列原创文章、源码——从入门到精通
  10. 超详细window10添加美式键盘