文章记录了分析shiro反序列化漏洞的思路和过程,漏洞用的次数挺多,感觉不认真走一遍分析还是缺点什么。排版也是按照我所理解的分析1day的思路进行排版的,emm~ 不太专业哈 见谅 ┭┮﹏┭┮
友情提示:文章写的感觉比较亲民,理论上有一些其他语言的基础都可以阅读,比较倾向于将东西写的详细(废话很多),就是那种看帖按着步骤走跟着思考大概自行理解的程度(记性不好,不写可能会忘的)
一切都要从官方shiro的某个人提出的问题描述开始说起 ~ 下图为谷歌翻译结果
url: https://issues.apache.org/jira/browse/SHIRO-550
通过描述可知:
shiro对每次访问都会用到"记住我"的功能进行以下操作:
检索rememberMe
cookie的值 //cookie中是否有这个参数
ObjectInputStream
)反序列化。 //对解出的参数的值进行反序列化以此确定一个需要通过Debug代码来达成的大概目的:
控制rememberMe参数的值
传输加密
好的恶意序列化payload
,成功让shiro进行解密到反序列化的步骤就可以达到执行命令的目的AES加密算法:属于对称加密算法,意思就是加密和解密用相同的密钥
加密过程:
明文 --> AES加密函数 + 密钥位数(128/192.256) + iv(初始化向量) + 密钥(key) + 模式(CBC和GCM等) + padding(填充方式)--> 密文
IDEA的Debug按钮功能:
Step Over : 单步执行,遇到方法直接获得返回值而不会进入
Step Into : 单步执行,遇到方法会进入方法,不会进入jdk实现的方法中
Force Step Into : 可以进入任何的方法,比如jdk,jar包
Step Out : 在方法内会直接获得返回值跳出该方法
Run To Cursor : 让程序运行到鼠标所在的位置
Drop Frame : 返回上一步,摧毁当前方法获得的值
Resume Program : 运行至下一个断点所在位置
研究的前提自然是要搭建好环境
下载shiro的漏洞环境,这里使用war包,放在tomcat的webapps里,启动tomcat,然后war包自动解析成文件夹,使用IDEA打开此文件夹
顺便讲一下IDEA配置调试shiro
Run -> Edit Configurations -> 点击+号添加TomcatServer(Local) -> Server中配置Tomcat路径 -> 选择JRE版本 ->Deployment中点击+号添加tomcat里生成的shiro文件夹 -> 点击Apply
运行起来
首先第一个目的是控制rememberMe参数的值,先找到参数所在位置,对环境的功能先正常使用一遍
当我访问http://localhost:8080/shiro_web_1_2_4_war/login.jsp 登录时勾选Remember Me后,cookie中出现rememberMe参数,而shiro每次都会对cookie中的rememberMe来进行解密后反序列化操作来确定访问者权限,所以直接在cookie传输rememberMe参数就可以控制shiro反序列化的值
第二个目的是获得加密解密的方法,以此来自行加密解密恶意payload进行传输
反编译此漏洞环境中的shiro组件jar包
选中shiro-core-1.2.4.jar -> 右键 -> Add as Library -> ok
选中shiro-web-1.2.4.jar -> 右键 -> Add as Library -> ok
IDEA中按两次shift 搜索咱们前面准备当做入口点的CookieRememberMeManager类,按着函数列表查看后并未发现有关加密的信息,so跟进父类AbstractRememberMeManager去看一下
进入此类可以发现一个很明显的key,根据参数名DEFAULT_CIPHER_KEY_BYTES
也可以断定是AES加密中所使用的密钥,同时确实是直接写入了代码中,符合上面通过描述可知的AES密钥硬编码在源代码中的条件
这里我在AbstractRememberMeManager类函数名为encrypt(加密)中下了断点,然后在web端进行登录操作,开始debug,运行至encrypt函数传入参数serialized,然后点击Drop Frame返回上个方法发现传入的serialized的值是我刚才web端登录的用户名root序列化后的数据,根据运行步骤函数名猜测流程是shiro验证完了登录的账号密码,然后根据用户名生成序列化数据准备进行加密了