CVE-2016-5003 xmlrpc反序列化漏洞

栏目: 服务器 · Apache · 发布时间: 5年前

内容简介:Apache XML-RPC是一个java的XML-RPC库。XML-RPC是在XML的帮助下通过HTTP进行远程过程调用的协议。 Apache XML-RPC可以在客户端用于进XML-RPC调用,也可以在服务器端用XML-RPC公开一些函数。现在ws-xmlrpc库不被Apache支持。 最新版本是2013年发布的3.1.3版本。但是,许多应用程序仍然使用ws-xmlrpc库新建Maven工程,引入如下依赖主方法

一、xmlrpc简介

Apache XML-RPC是一个 java 的XML-RPC库。XML-RPC是在XML的帮助下通过HTTP进行远程过程调用的协议。 Apache XML-RPC可以在客户端用于进XML-RPC调用,也可以在服务器端用XML-RPC公开一些函数。现在ws-xmlrpc库不被Apache支持。 最新版本是2013年发布的3.1.3版本。但是,许多应用程序仍然使用ws-xmlrpc库

二、漏洞重现

新建Maven工程,引入如下依赖

<dependencies>  
        <dependency>
            <groupId>org.apache.xmlrpc</groupId>
            <artifactId>xmlrpc-common</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlrpc</groupId>
            <artifactId>xmlrpc-server</artifactId>
            <version>3.1.3</version>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.1</version>
        </dependency>
    </dependencies>

主方法 App.java

public class App {  
    private static final int port = 8888;

    public static void main(String[] args) throws Exception {
        WebServer webServer = new WebServer(port);   
        XmlRpcServer xmlRpcServer = webServer.getXmlRpcServer();   
        PropertyHandlerMapping phm = new PropertyHandlerMapping();
        phm.addHandler("User", User.class);
        xmlRpcServer.setHandlerMapping(phm);
        XmlRpcServerConfigImpl serverConfig = (XmlRpcServerConfigImpl) xmlRpcServer.getConfig();
        serverConfig.setEnabledForExtensions(true);
        webServer.start();
    }
}

接收传入对象 User.java

public class User {  
    public String welcome(String name) {
        return "welcome " + name;
    }
}

运行 App.java 后即在 8888 端口建立 HTTP 服务。即可使用Burpsuite进行发包测试 CVE-2016-5003 xmlrpc反序列化漏洞 参考 官网帮助文档 ,可以发现xmlrpc支持 java.io.Serializable 序列化后的base64编码的数据,但是需要引用命名空间 http://ws.apache.org/xmlrpc/namespaces/extensions 。所以使用 ysoserialCommonsCollections5 生成payload。 因为本机测试环境为jdk1.8,用其它payload会爆错CVE-2016-5003 xmlrpc反序列化漏洞 然后使用certutil -encode 将生成的文件进行base64编码。 CVE-2016-5003 xmlrpc反序列化漏洞

漏洞分析

当客户端发送请求时, org.apache.xmlrpc.server.XmlRpcStreamServer.getRequest(XmlRpcStreamRequestConfig, InputStream) 方法会接收到该请求,该方法会将请求内容封闭到XMLReader对象中。

protected XmlRpcRequest getRequest(final XmlRpcStreamRequestConfig pConfig,  
                                       InputStream pStream) throws XmlRpcException {
        final XmlRpcRequestParser parser = new XmlRpcRequestParser(pConfig, getTypeFactory());
        final XMLReader xr = SAXParsers.newXMLReader();
        xr.setContentHandler(parser);
        try {
            xr.parse(new InputSource(pStream));
        } catch (SAXException e) {
            Exception ex = e.getException();
            if (ex != null  &&  ex instanceof XmlRpcException) {
                throw (XmlRpcException) ex;
            }
            throw new XmlRpcException("Failed to parse XML-RPC request: " + e.getMessage(), e);
        } catch (IOException e) {
            throw new XmlRpcException("Failed to read XML-RPC request: " + e.getMessage(), e);
        }
        final List params = parser.getParams();
        return new XmlRpcRequest(){
            public XmlRpcRequestConfig getConfig() { return pConfig; }
            public String getMethodName() { return parser.getMethodName(); }
            public int getParameterCount() { return params == null ? 0 : params.size(); }
            public Object getParameter(int pIndex) { return params.get(pIndex); }
        };
    }

然后程序会走到 org.apache.xmlrpc.parser.XmlRpcRequestParser.endElement(String, String, String) 方法来获取各个元素的值

public void endElement(String pURI, String pLocalName, String pQName) throws SAXException {  
        switch(--level) {
            case 0:
                break;
            case 1:
                if (inMethodName) {
                    if ("".equals(pURI)  &&  "methodName".equals(pLocalName)) {
                        if (methodName == null) {
                            methodName = "";
                        }
                    } else {
                        throw new SAXParseException("Expected /methodName, got "
                                                    + new QName(pURI, pLocalName),
                                                    getDocumentLocator());
                    }
                    inMethodName = false;
                } else if (!"".equals(pURI)  ||  !"params".equals(pLocalName)) {
                    throw new SAXParseException("Expected /params, got "
                            + new QName(pURI, pLocalName),
                            getDocumentLocator());
                }
                break;
            case 2:
                if (!"".equals(pURI)  ||  !"param".equals(pLocalName)) {
                    throw new SAXParseException("Expected /param, got "
                                                + new QName(pURI, pLocalName),
                                                getDocumentLocator());
                }
                break;
            case 3:
                if (!"".equals(pURI)  ||  !"value".equals(pLocalName)) {
                    throw new SAXParseException("Expected /value, got "
                                                + new QName(pURI, pLocalName),
                                                getDocumentLocator());
                }
                endValueTag();
                break;
            default:
                super.endElement(pURI, pLocalName, pQName);
                break;
        }
    }

当获取到最后的元素时,会执行 org.apache.xmlrpc.parser.RecursiveTypeParserImpl.endValueTag() 方法

protected void endValueTag() throws SAXException {  
        if (inValueTag) {
            if (typeParser == null) {
                addResult(text.toString());
                text.setLength(0);
            } else {
                typeParser.endDocument();
                try {
                    addResult(typeParser.getResult());
                } catch (XmlRpcException e) {
                    throw new SAXException(e);
                }
                typeParser = null;
            }
        } else {
            throw new SAXParseException("Invalid state: Not inside value tag.",
                                        getDocumentLocator());
        }
    }

即会执行typeParser.getResult(),并且此时的typeParser为SerializableParser,

public class SerializableParser extends ByteArrayParser {  
    public Object getResult() throws XmlRpcException {
        try {
            byte[] res = (byte[]) super.getResult();
            ByteArrayInputStream bais = new ByteArrayInputStream(res);
            ObjectInputStream ois = new ObjectInputStream(bais);
            return ois.readObject();
        } catch (IOException e) {
            throw new XmlRpcException("Failed to read result object: " + e.getMessage(), e);
        } catch (ClassNotFoundException e) {
            throw new XmlRpcException("Failed to load class for result object: " + e.getMessage(), e);
        }
    }
}

从而造成了反序列化命令执行漏洞。


以上所述就是小编给大家介绍的《CVE-2016-5003 xmlrpc反序列化漏洞》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

JavaScript DOM编程艺术 (第2版)

JavaScript DOM编程艺术 (第2版)

[英] Jeremy Keith、[加] Jeffrey Sambells / 杨涛、王建桥、杨晓云 等 / 人民邮电出版社 / 2011-4 / 49.00元

JavaScript是Web开发中最重要的一门语言,它强大而优美。无论是桌面开发,还是移动应用。JavaScript都是必须掌握的技术。W3C的DOM标准是开发Web应用的基石。已经得到所有现代浏览器的支持,这使得跨平台Web开发成了一件轻松惬意的事。 本书是超级畅销书的升级版,由倡导Web标准的领军人物执笔,揭示了前端开发的真谛,是学习JavaScript和DOM开发的必读之作。 本......一起来看看 《JavaScript DOM编程艺术 (第2版)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具