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

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

内容简介: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反序列化漏洞》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

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

Hit Refresh

Hit Refresh

Satya Nadella、Greg Shaw / HarperBusiness / 2017-9-26 / USD 20.37

Hit Refresh is about individual change, about the transformation happening inside of Microsoft and the technology that will soon impact all of our lives—the arrival of the most exciting and disruptive......一起来看看 《Hit Refresh》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具