java反序列化提取payload之Xray高级版的shiro回显poc的提取过程

admin 2022年3月17日09:54:17评论144 views字数 3566阅读11分53秒阅读模式

本文中xray高级版shiro payload来源于雷石安全实验室公众号发布的shiroExploit.jar

感谢雷石安全实验室,雷石安全实验室牛逼

本文主要描述如何从shiro的payload中提取有效payload。该方法适合从各种java反序列化漏洞中提取payload

0x01 前言

某日小伙伴发来雷石安全实验室的shiro利用工具,据称payload提取自xray。利用如下java反序列化提取payload之Xray高级版的shiro回显poc的提取过程

0x02 反编译雷石利用工具

首先拖入idea中反编译,查看如何利用payload。代码如下

java反序列化提取payload之Xray高级版的shiro回显poc的提取过程

java反序列化提取payload之Xray高级版的shiro回显poc的提取过程

t是遍历数组的下标变量

不得不说,当我看到这人写的代码时,心中一万个草泥马飘过。第一次看到这样遍历数组的方式!!!!再看一下变量命名,浓郁地乡村非主流风格。雷石安全实验室写的代码,自带混淆,牛皮。

payload呢,原来是xray已经生成并加密的,一共430个。所以我们的问题变为如何从这430个已加密的payload中提取未加密的内容

0x03 shiro payload解密

根据shiro漏洞的原理,shiro的cookie通过如下方式加密, key为kPH+bIxk5D2deZiIxcaaaA==解码后的内容

base64Encode(iv+aes(java serialize object))

而java反序列化后的数据,以aced开头。于是我们可以使用shiro默认密钥,批量解密上面的430个key。如果正常解密,且解密后的数据以正确的magic number开头。则保存文件。代码如下

    public static String bytesToHex(byte[] bytes) {
      StringBuffer sb = new StringBuffer();
      for(int i = 0; i < bytes.length; i++) {
          String hex = Integer.toHexString(bytes[i] & 0xFF);
          if(hex.length() < 2){
              sb.append(0);
          }
          sb.append(hex);
      }
      return sb.toString();
  }

  public static byte[] decrypt(byte[] cipherTextBytes, byte[] pwdBytes, byte[] iv) {
      try {
// 1 获取解密密钥
          SecretKeySpec keySpec = new SecretKeySpec(pwdBytes, ENCRY_ALGORITHM);
// 2 获取Cipher实例
          Cipher cipher = Cipher.getInstance(CIPHER_MODE);
// 查看数据块位数 默认为16(byte) * 8 =128 bit
// System.out.println("数据块位数(byte):" + cipher.getBlockSize());
// 3 初始化Cipher实例。设置执行模式以及加密密钥
          IvParameterSpec iv1 = new IvParameterSpec(iv);//使用CBC模式,需要一个向量iv,可增加加密算法的强度
          cipher.init(Cipher.DECRYPT_MODE, keySpec, iv1);
// 4 执行
          byte[] clearTextBytes = cipher.doFinal(cipherTextBytes);
// 5 返回明文字符集
          return clearTextBytes;
      } catch (NoSuchAlgorithmException e) {
          e.printStackTrace();
      } catch (InvalidKeyException e) {
          e.printStackTrace();
      } catch (NoSuchPaddingException e) {
          e.printStackTrace();
      } catch (BadPaddingException e) {
          e.printStackTrace();
      } catch (IllegalBlockSizeException e) {
          e.printStackTrace();
      } catch (Exception e) {
          e.printStackTrace();
      }
// 解密错误 返回null
      return null;
  }

  public static void main(String... args) throws IOException {
      for(int i = 0; i< xray.cookie.length; i++){
          String payload = xray.payloads(i);
          System.out.println(payload);
          byte[] rawpayloadBytes = Base64.decode(payload);
          byte[] key = Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");
          int ivSize = key.length;
          byte[] iv = new byte[ivSize];
          System.arraycopy(rawpayloadBytes, 0, iv, 0, ivSize);
          byte[] payloadBytes = new byte[rawpayloadBytes.length - ivSize];
          System.arraycopy(rawpayloadBytes, ivSize, payloadBytes, 0, payloadBytes.length);
              byte[] result = EncryptUtil.decrypt(payloadBytes, key, iv);
              if (result != null){
                  String hexResult = bytesToHex(result);
                  if (hexResult.startsWith("aced")) {
                      System.out.println(payload);
                      new FileOutputStream(new File("res.ser")).write(result);
                  }
              }
      }
  }

结果通过010editor查看如下java反序列化提取payload之Xray高级版的shiro回显poc的提取过程

0x04 查看java反序列化数据

通过SerializationDumper工具即可查看java反序列化提取payload之Xray高级版的shiro回显poc的提取过程

shiro中通过反序列化漏洞回显,需要执行自定义的java代码。查看ysoserial代码,执行自定义代码,需要通过com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet的方式,编写一个继承自该类的class,读取字节码并设置_bytecodes,代码如下java反序列化提取payload之Xray高级版的shiro回显poc的提取过程

所以我们的重点在于如何提取bytecode数组中的内容。而serializationDumper默认只打印数组中的值。java反序列化提取payload之Xray高级版的shiro回显poc的提取过程

查看一下serializationDumper工具是如何读取array数组的,代码如下java反序列化提取payload之Xray高级版的shiro回显poc的提取过程

首先读取array的size,然后调(byte)cd.getClassName().charAt(1)去读取array的类型,再调用readBytesField方法读取每一项具体的值,代码如下

/*******************
* Read a byte field.
******************/
private void readByteField() {
byte b1 = this._data.pop();
if(((int)b1) >= 0x20 && ((int)b1) <= 0x7e) {
//Print with ASCII
this.print("(byte)" + b1 + " (ASCII: " + ((char)b1) + ") - 0x" + this.byteToHex(b1));
} else {
//Just print byte value
this.print("(byte)" + b1 + " - 0x" + this.byteToHex(b1));
}
}

所以只需要魔改一下读取数组的地方即可,并写入文件。

java反序列化提取payload之Xray高级版的shiro回显poc的提取过程

0x05 利用

已经集成到shiro综合利用工具中,可以选择gadget以及生成方式,不过目前只集成16个key。

java反序列化提取payload之Xray高级版的shiro回显poc的提取过程java反序列化提取payload之Xray高级版的shiro回显poc的提取过程

参考

  1. https://mp.weixin.qq.com/s/fZhL-GjoXLPqAIKBKCC_fg


java反序列化提取payload之Xray高级版的shiro回显poc的提取过程



本文始发于微信公众号(宽字节安全):java反序列化提取payload之Xray高级版的shiro回显poc的提取过程

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年3月17日09:54:17
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   java反序列化提取payload之Xray高级版的shiro回显poc的提取过程http://cn-sec.com/archives/497794.html

发表评论

匿名网友 填写信息