记一次shiro反序列化漏洞getshell

  • A+
所属分类:安全文章

0x01 背景

偶然发现一个只有后台登录页面的网站系统,疑似是有一些防爬机制,具体是什么样的防护机制我也是两眼一抹黑,没弄明白..点击登录按钮后要么账号密码参数值直接在框内加密显示,页面没反应,要么直接就网页找不到,下面是测试前后的大概流程,还有部分burp插件中模块的扩展学习,献丑了..

0x02 信息收集

浏览器插件

一般拿到目标,按照小习惯,先使用谷歌浏览器插件对目标网站的信息做一个简单的了解后,再使用其他工具收集其他信息

Wappalyzer插件,简单了解一下网站平台构架、网站环境、服务器配置环境、JavaScript框架、编程语言等参数

记一次shiro反序列化漏洞getshell

Shodan,查看目标网站的IP和端口,此处显示目标IP为xxx.xxx.1.59,端口开放了80和443,没有其他服务:

记一次shiro反序列化漏洞getshell

探测CND&真实IP

使用nslookup命令和多地ping的方式探测网站真实IP地址和是否使用了CDN

记一次shiro反序列化漏洞getshell

记一次shiro反序列化漏洞getshell

基本看来目标网站并未使用CDN

端口扫描

使用nmap探测端口开放情况

Nmap

Nmap scan report for xxx.xxx.1.59
Host is up (0.017s latency).
Not shown: 997 filtered ports
PORT     STATE  SERVICE    VERSION
80/tcp   open   http       nginx 1.18.0
|_http-server-header: nginx/1.18.0
443/tcp  open   ssl/https
| fingerprint-strings:
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, RPCCheck, RTSPRequest:
|     HTTP/1.1 400
|     Date: Thu, 07 Jan 2021 11:52:52 GMT
|     Connectionclose
|   FourOhFourRequest, HTTPOptions:
|     HTTP/1.1 404
|     Content-Length0
|     Date: Thu, 07 Jan 2021 11:52:47 GMT
|     Connectionclose
|   GetRequest:
|     HTTP/1.1 404
|     Content-Length0
|     Date: Thu, 07 Jan 2021 11:52:46 GMT
|     Connectionclose
|   Kerberos, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServerCookie, X11Probe:
|     HTTP/1.1 400
|     Date: Thu, 07 Jan 2021 11:52:53 GMT
|     Connectionclose
|   tor-versions:
|     HTTP/1.1 400
|     Date: Thu, 07 Jan 2021 11:52:47 GMT
|_    Connectionclose
|_http-title: Site doesn't have a title.
| ssl-cert: Subject: commonName=*.dzzgsw.com/organizationName=xE4xB8xADxE5x9BxBDxE5xB7xA5xE4xBAxBAxE5x87xBAxE7x89x88xE7xA4xBE/stateOrProvinceName=xE5x8Cx97xE4xBAxACxE5xB8x82/countryName=CN
| Subject Alternative Name: DNS:*.dzzgsw.com, DNS:dzzgsw.com
| Not valid before: 2020-03-30T00:00:00
|_Not valid after:  2022-03-30T12:00:00
|_ssl-date: 2021-01-07T11:53:21+00:00; -18m38s from scanner time.
8080/tcp closed http-proxy

同样的,和shodan显示的端口开放情况无二

目标网站IP地址:xxx.xxx.1.59

端口开放情况:80、443

目录扫描

使用dirsearch工具对目录进行探测,考虑到网站有一些防护机制,设置了下延迟,使用随机获取的UA,也设置代理,然而dirsearch这次也不香了,无果。

记一次shiro反序列化漏洞getshell

前端敏感接口

端口目录没什么收获,继续尝试在前端F12翻js无果后,使用脚本在js文件中寻找敏感接口,可依次查看下来,也并没什么卵用….心痛….

记一次shiro反序列化漏洞getshell

0x03 jsEncrypter插件自定义加密算法模块

接下来将目光转移到网站功能上,最开始只是想简单的尝试几个弱口令,没想到网站系统不讲武德,也就是开头提到的,应该是有一些防爬机制:

记一次shiro反序列化漏洞getshell

记一次shiro反序列化漏洞getshell

(后来想补一张点击登录后账号密码在框内编码显示的图片,发现网站不能访问了,与我无瓜,绝对不是我打挂的….不是我..)

Burp拦截登录数据包,看到账号密码参数值被加密处理,好奇心被勾了起来:

123456 加密后:s2ypDtQpq5F/4xvZUu9HxA==

记一次shiro反序列化漏洞getshell

前端F12开发者模式打开,走位~走位~….算了,我还是直接搜索吧,搜索crypt或username、password等关键词,来到加密账号密码的函数,emm..有密钥,emm..AES,emm..ECB模式….看样子应该是base64输出

记一次shiro反序列化漏洞getshell

随后想到c0ny1师傅在github的一个用于前端加密Fuzz的burp插件项目,在以往测试过程中,有很多前端都是被各种各样的加密,也是用过很多次这个插件来应对这种场景,但是c0ny1师傅的模块没有AES,需要自己去照虎画猫了:

【c0ny1师傅的jsEncrypter插件,github地址:https://github.com/c0ny1/jsEncrypter】

记一次shiro反序列化漏洞getshell

我们需要进行算法的提炼,这里参考了文章:https://blog.csdn.net/qq_43592994/article/details/105148765

文章中也有提炼算法和添加依赖的方法,过程中虽然遇到了些小问题,但最后也是顺利解决了,大概流程如下。

创建所需文件

创建AES文件夹,在此文件夹下需要crypto-js.js和jsEncrypter_aes.js这两个文件

记一次shiro反序列化漏洞getshell

  1. crypto-js依赖

    第一个crypto-js.js文件是依赖,只需要把sha256文件夹下的同名文件复制过来即可;

  2. jsEncrypter_aes.js文件

    第二个jsEncrypter_aes.js文件可复制一下模板,以此创建上图中第二个文件:

      /**
      * author: c0ny1
      */

      var fs = require('fs');
      var webserver = require('webserver');
      server = webserver.create();

      var logfile = 'jsEncrypter.log';
      var host = '127.0.0.1';
      var port = '1664';

      /* 1.在这引入实现加密所有js文件,注意引入顺序和网页一致 */
      //var wasSuccessful = phantom.injectJs('crypto-js.js');/* 引入实现加密的js文件*/

      // loadScript("script-2.js");
      // loadScript("script-n.js");
      /**********************************************/

      function loadScript(scriptName{
          var isSuccess = phantom.injectJs(scriptName);
          if(isSuccess){
              console.log("[*] load " + scriptName + " successful")
          }else{
              console.log("[!] load " + scriptName + " fail")
              console.log("[*] phantomjs server exit");
              phantom.exit();
          }
      }

      // var key = CryptoJS.enc.Utf8.parse("PBLUREBUWNXCXHRQ"); //16位
      // var iv = CryptoJS.enc.Utf8.parse("1234567812345678");
      function jsEncrypt(burp_payload){
        var new_payload;
        /* 2.在这里编写调用加密函数进行加密的代码,并把结果赋值给new_payload */
          // 编辑 加密函数的位置
        /*********************************************************/
        return new_payload;
      }

      console.log("[*] Phantomjs server for jsEncrypter started successfully!");
      console.log("[*] address: http://"+host+":"+port);
      console.log("[!] ^_^");

      var service = server.listen(host+':'+port,function(request, response){
        try{
          if(request.method == 'POST'){
            var payload = request.post['payload'];
            var encrypt_payload = jsEncrypt(payload);
            var log = payload + ':' + encrypt_payload;
            console.log('[+] ' + log);
                  fs.write(logfile,log + 'n''w+');
            response.statusCode = 200;
                  response.setEncoding('UTF-8');
            response.write(encrypt_payload.toString());
            response.close();
          }else{
              response.statusCode = 200;
              response.setEncoding('UTF-8');
              response.write("^_^nrhello jsEncrypter!");
              response.close();
          }
        }catch(e){
          //console.log('[Error]'+e.message+' happen '+e.line+'line');
          console.log('n-----------------Error Info--------------------');
          var fullMessage = "Message: "+e.toString() + ':'+ e.line;
          for (var p in e) {
            fullMessage += "n" + p.toUpperCase() + ": " + e

    ;
          } 
          console.log(fullMessage);
          console.log('---------------------------------------------');
              response.statusCode = 200;
              response.setEncoding('UTF-8');
              response.write(fullMessage);
              response.close();
          console.log('[*] phantomJS exit!');
          phantom.exit();
          } 
      });

  3. 添加依赖以及提炼好的算法

    第一处红框引入实现加密的js文件

    第二处红框编写调用加密函数进行加密的代码

    密钥:o7H8uIM2O5qv65l2

    偏移量:无

    加密模式:ECB

    填充:pkcs7

    输出:base64

记一次shiro反序列化漏洞getshell

(注意算法中的密钥是否与网站一致,网站加密算法是否有偏移量,注意加密模式、填充方式、输出方式..阿巴阿巴….)

运行测试

打包好插件后导入Burp,使用phantomjs.exe运行jsEncrypter_aes.js文件进行测试,经测试和Burp拦截到的加密数据一致

123456:s2ypDtQpq5F/4xvZUu9HxA==

记一次shiro反序列化漏洞getshell

0x04东方不亮西方亮

继续回到测试正题,在测试忘记密码功能处,发现用户名可枚举漏洞,填写用户名后点击忘记密码,根据不同的用户名会显示【该用户未设置邮箱信息,无法找回】或【用户不存在】,使用top500用户名字典倒是也枚举出来几个,验证码也可使用验证码识别工具识别,但奈何网站奇怪的防护机制就此打住,不继续占过多篇幅….

Dirb目录扫描

不死心的我掏出可爱的kali,使用kali的web目录扫描工具------dirb,本以为又是做无用功,但kali诚不欺我,果然没有让人失望,还算有点收获

记一次shiro反序列化漏洞getshell

紧接着自然是一个左勾拳加一个右鞭腿,马不停蹄的访问一下,看红框内三个熟悉的字重新燃起了希望,啪的一下就站起来,我非要跟它试试

记一次shiro反序列化漏洞getshell

Cookie中加入rememberMe=1,很快啊,响应数据包set-cookie显示rememberMe=deleteMe,

符合Apache Shiro框架特征判断

记一次shiro反序列化漏洞getshell

Shiro反序列化回显工具

浮萍大佬倾心力作,2.4版本重磅来袭!居家旅行渗透测试必备利器!

使用默认DNSLOG和key检测存在反序列化漏洞

记一次shiro反序列化漏洞getshell

记一次shiro反序列化漏洞getshell

尝试使用工具写入内存shell,设置好密码,shell类型和可以自定义的Header:

记一次shiro反序列化漏洞getshell

记一次shiro反序列化漏洞getshell

使用蚁剑连接,URL需要有ver参数,连接类型为CUSTOM,设置好正确的Header,这三点都需配置正确,否则会连接不成功。

记一次shiro反序列化漏洞getshell

记一次shiro反序列化漏洞getshell

点击连接,成功getshell:

记一次shiro反序列化漏洞getshell

shiro反序列化回显工具还支持一键卸载内存shell功能,最后卸马,溜了溜了~

记一次shiro反序列化漏洞getshell

0x05总结

首先自然是吹爆浮萍大佬的Shiro反序列化回显工具,支持Tomcat7、8、9下的回显,支持Tomcat7、8、9下蚁剑内存shell、冰蝎内存shell的写入与卸载,支持自定义UA和Accept-Header,支持AES-GCM加密方式等强大功能!

其次便是自己的测试感受,测试工具、字典五花八门,使用一种工具或测试手法就判定某一方面的探测有无成果过于草率,引以为戒;同时另外一方面原因也是自己的字(ji)典(shu)不(tai)全(cai),根据信息收集成果、渗透测试情况、文章等途径及时更新自己的字典还是很重要滴~


本文始发于微信公众号(猎户攻防实验室):记一次shiro反序列化漏洞getshell

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: