NCCloudGatewayServlet 命令执行漏洞 补丁绕过 之前的文章分析过,这个补丁只是对com.ufida.zior.console.IActionInvokeServicenc.bs.pub.util.ProcessFileUtils,并且类名不能包含nc.itf.uap.IUAPQueryBS

public void checkBlackITFAuthority(String serviceClassName, Object[] argValues) throws BusinessException {  
    if ("com.ufida.zior.console.IActionInvokeService".equalsIgnoreCase(serviceClassName) && "nc.bs.pub.util.ProcessFileUtils".equalsIgnoreCase(String.valueOf(argValues[0]))) {  
        Logger.error("目前没有查【nc.bs.pub.util.ProcessFileUtils】接口权限");  
        throw new BusinessException("目前没查询【nc.bs.pub.util.ProcessFileUtils】接口权限");  
    }  
    if ("nc.itf.uap.IUAPQueryBS".equalsIgnoreCase(serviceClassName)) {  
        String argSql = ((String) argValues[0]).toLowerCase();  
        for (String word : BannedSqlWord) {  
            if (argSql.contains(word)) {  
                Logger.error("SQL语句中存在敏感词:" + word);  
                throw new BusinessException("SQL语句中存在敏感词:" + word);  
            }  
        }  
    }  
}

所以绕过方法也很简单,再找一个其他的sink类即可,这里提供另外一个写文件的方法nc.impl.uap.pfxxdev.PfxxDevFileServiceImpl#writePluginJavaCodeToServer,实际上还有很多可以利用的,具体就不详细分析了。

public void writePluginJavaCodeToServer(byte[] javasource, String filename, String modulename) throws BusinessException {  
    String sourcepath = RuntimeEnv.getInstance().getNCHome() + "/modules/" + modulename + "/META-INF/var/source/" + filename;  
    String classpath = RuntimeEnv.getInstance().getNCHome() + "/modules/" + modulename + "/META-INF/var/classes/";  
    try {  
        File file = new File(classpath);  
        if (!file.exists()) {  
            file.mkdirs();  
        }  
  
        FileUtils.writeBytesToFile(javasource, sourcepath);  
    } catch (IOException e) {  
        Logger.error(NCLangResOnserver.getInstance().getStrByID("uapde_pfxx", "PfxxDevFileServiceImpl-000001"), e);  
        throw new BusinessException(NCLangResOnserver.getInstance().getStrByID("uapde_pfxx", "PfxxDevFileServiceImpl-000002"));  
    }  
}

实际上,这个反射调用和之前的反序列化的最终效果都是一样的,可以调用Service的任意方法,并且参数可控。

//  
// Source code recreated from a .class file by IntelliJ IDEA  
// (powered by FernFlower decompiler)  
//  
  
package nc.impl.uap.pfxxdev;  
  
import java.io.File;  
import java.io.IOException;  
import nc.bs.framework.common.RuntimeEnv;  
import nc.bs.logging.Logger;  
import nc.bs.ml.NCLangResOnserver;  
import nc.itf.uap.pfxxdev.IPfxxDevFileService;  
import nc.vo.jcom.io.fileparse.FileParseException;  
import nc.vo.jcom.io.fileparse.IntellijFileReader;  
import nc.vo.jcom.io.fileparse.IntellijFileReaderPool;  
import nc.vo.jcom.lang.StringUtil;  
import nc.vo.pfxx.exception.FileConfigException;  
import nc.vo.pfxx.pub.PfxxServerSidePathVocabulary;  
import nc.vo.pfxx.util.FileUtils;  
import nc.vo.pub.BusinessException;  
  
public class PfxxDevFileServiceImpl implements IPfxxDevFileService {  
    public byte[] getXMLDocFromTestPlugin(String filename) throws BusinessException {  
        if (StringUtil.isEmpty(filename)) {  
            throw new BusinessException(NCLangResOnserver.getInstance().getStrByID("uapde_pfxx", "PfxxDevFileServiceImpl-000000"));  
        } else {  
            filename = filename.replace('\\', '/');  
            String filepath = PfxxServerSidePathVocabulary.EXPORTBILLS_PATH + "test/" + filename;  
  
            try {  
                IntellijFileReader filereader = IntellijFileReaderPool.getIntellijFileReader(new PluginTestXMLParser(new File(filepath)));  
                return (byte[])filereader.getResult();  
            } catch (FileParseException e) {  
                Logger.error(e.getMessage(), e);  
                throw new FileConfigException(filepath, e.getMessage());  
            }  
        }  
    }  
  
    public void writePluginJavaCodeToServer(byte[] javasource, String filename, String modulename) throws BusinessException {  
        String sourcepath = RuntimeEnv.getInstance().getNCHome() + "/modules/" + modulename + "/META-INF/var/source/" + filename;  
        String classpath = RuntimeEnv.getInstance().getNCHome() + "/modules/" + modulename + "/META-INF/var/classes/";  
  
        try {  
            File file = new File(classpath);  
            if (!file.exists()) {  
                file.mkdirs();  
            }  
  
            FileUtils.writeBytesToFile(javasource, sourcepath);  
        } catch (IOException e) {  
            Logger.error(NCLangResOnserver.getInstance().getStrByID("uapde_pfxx", "PfxxDevFileServiceImpl-000001"), e);  
            throw new BusinessException(NCLangResOnserver.getInstance().getStrByID("uapde_pfxx", "PfxxDevFileServiceImpl-000002"));  
        }  
    }  
}