Shiro密钥检测工具编写思路

·
Java代码审计 no tag November 4, 2021

密钥检测部分

密钥检测原理

首先是检测是否为shiro

检测是否为shiro,只需要在http头输入rememberMe=1,那么响应头就会有rememberMe=deleteMe字段。

image-20211104161349572

核心点在shiro-core-1.2.4-sources.jar!\org\apache\shiro\mgt\AbstractRememberMeManager.java的getRememberedPrincipals方法中。

当key不正确时,AbstractRememberMeManager#decrypt是处理解密的过程

image-20211104162422794

我们调式一下,跟进cipherService.decrypt

image-20211104162600212

因为无法正确解密,所以抛出错误。

image-20211104162715859

并进入AbstractRememberMeManager#getRememberedPrincipals的错误处理。

然后跟进onRememberedPrincipalFailure方法。

image-20211104162956302

然后进入forgetIdentity 方法。

image-20211104163307745在 forgetIdentity 方法当中从 subjectContext 对象获取 request 和 response ,继续由forgetIdentity(HttpServletRequest request, HttpServletResponse response)这个构造方法处理。

继续跟进进入removeFrom

image-20211104164427027

关键就是addCookieHeader增加了rememberMe字段

image-20211104165157339

爆破密钥

那么,如果我们输入了正确的cookie,那么会如何处理?

image-20211104174623236

如果是正确的,那么就不会进入错误处理,而是正确的反序列化,因此不会打印出rememberMe=deleteMe

所以我们选择用不同的密钥加密,当爆破到正确的密钥时,就不会输出rememberMe=deleteMe。

  • 构造一个继承 PrincipalCollection 的序列化对象。
  • key正常不返回deleteMe,key错误返回deleteMe

image-20211104193949273

所以就找到了simplePrincipalCollection

因此就用密钥序列化这个类。

密钥检测实现

public class KeyDetect {
    public byte[] getPayload() throws Exception {
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        SimplePrincipalCollection simplePrincipalCollection = new SimplePrincipalCollection();
        ObjectOutputStream obj = new ObjectOutputStream(barr);
        obj.writeObject(simplePrincipalCollection);
        obj.close();


        return barr.toByteArray();
    }
}

首先我们就对SimplePrincipalCollection类序列化。

然后对序列化数据进行AES加密。

public class createAESGCMCipher {
    //实现AES中的GCM加密 shiro1.4.2版本更换为了AES-GCM加密方式
    public static String encrypt(String Shirokey) throws Exception {
        byte[] payloads = new KeyDetect().getPayload();
        byte[] key = java.util.Base64.getDecoder().decode(Shirokey);


        int ivSize = 16;
        byte[] iv = new byte[ivSize];
        SecureRandom random = new SecureRandom();
        random.nextBytes(iv);
        GCMParameterSpec ivParameterSpec = new GCMParameterSpec(128,iv);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        cipher.init(1, secretKeySpec, ivParameterSpec);
        byte[] encrypted = cipher.doFinal(payloads);
        byte[] encryptedIvandtext = new byte[ivSize + encrypted.length];
        System.arraycopy(iv, 0, encryptedIvandtext, 0, ivSize);
        System.arraycopy(encrypted, 0, encryptedIvandtext, ivSize, encrypted.length);
//        return new BASE64Encoder().encode(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。
        String b64Payload = Base64.encodeToString(encryptedIvandtext);


//        System.out.println(b64Payload);
        return b64Payload;
    }

}

然后对序列化数据进行AES加密。

这里的加密方式分为CBC加密和GCM加密。

在shiro1.4.2版本更换为了AES-GCM加密方式。

然后用java实现发包,注意这里要检测一下是否为https,如果是就跳过证书检测。否则会报错。

if (url.startsWith("https")) {
SSLContext sslContext = SSLContext.getInstance("SSL");
TrustManager[] tm = new TrustManager[]{new MyCert()};
sslContext.init(null, tm, new SecureRandom());
SSLSocketFactory ssf = sslContext.getSocketFactory();
hsc = (HttpsURLConnection)realUrl.openConnection();

hsc.setSSLSocketFactory(ssf);
hsc.setHostnameVerifier(allHostsValid);
httpUrlConn = hsc;
}else {
hc = (HttpURLConnection)realUrl.openConnection();
hc.setRequestMethod("GET");
hc.setInstanceFollowRedirects(false);
System.out.println(hc.getRequestProperties());
httpUrlConn = hc;
}

注意这里javafx的ui会卡住,所以我使用了多线程。

        Thread thread = new Thread(()->{
            ShiroKeyDetect shiroKeyDetect = new ShiroKeyDetect();
            String targetUrl = attackUrl.getText();
            if(ShiroKeyDetect.isShiro(targetUrl)){
                try {
                    shiroKeyDetect.ShiroKey(targetUrl);
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }else {
                result.appendText("未检测到shiro框架"+"\n");
            }

        });
        thread.start();

这样在处理的时候就不会未响应了。

ShiroKey检测项目地址https://github.com/Yang9999999/ShiroKeyDetect

参考 :https://mp.weixin.qq.com/s/do88_4Td1CSeKLmFqhGCuQ

  • fastjson1.2.25-1.2.47绕过
  • 内存马笔记
取消回复

说点什么?
Title
首先是检测是否为shiro
爆破密钥

© 2023 Cuckoo. Using Typecho & Moricolor.