Bug 1152544 (CVE-2014-3699) - CVE-2014-3699 eDeploy: Remote code execution due to cPickle deserialization of untrusted data
Summary: CVE-2014-3699 eDeploy: Remote code execution due to cPickle deserialization o...
Keywords:
Status: CLOSED WONTFIX
Alias: CVE-2014-3699
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
high
high
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks: 1152549
TreeView+ depends on / blocked
 
Reported: 2014-10-14 11:42 UTC by David Jorm
Modified: 2023-05-12 13:34 UTC (History)
6 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2015-03-17 23:21:30 UTC
Embargoed:


Attachments (Terms of Use)

Description David Jorm 2014-10-14 11:42:05 UTC
It was found that under certain conditions, eDeploy would bind cPickle to a TCP port. A remote, unauthenticated attacker able to connect to this port could provide malicious serialized data, leading to remote code execution.

Comment 1 David Jorm 2014-10-14 11:43:00 UTC
Acknowledgements:

This issue was discovered by Kurt Seifried of Red Hat Product Security.

Comment 3 Kurt Seifried 2015-03-17 19:44:37 UTC
So in src/netdetect.py and src/health_protocol.py we send and receive pickled 
data, no authentication, so anyone with network access == code execution 

Code, snipped, basically:

src/netdetect.py

def start_sync_bench_server():
    '''Server is made for receiving keepalives and manage them.'''
    ''' Let's bind a server to the Multicast group '''
        ''' Let's get keepalives from servers '''
        answer = cPickle.loads(sock.recv(10240))

def start_discovery_server():
    '''Server is made for receiving keepalives and manage them.'''
    ''' Let's bind a server to the Multicast group '''
    ''' Until we got a synthesis list from another server '''
    while not synthesis:
        answer = {}
        ''' Let's get keepalives from servers '''
        answer = cPickle.loads(sock.recv(10240))

def start_client(mode, max_clients=0):
        ''' While we are in discovery mode, let's send keepalives '''
        while discovery:
            sys.stderr.write("Sending keepalive for %s\n" % my_mac_addr)
            sock.sendto(cPickle.dumps(host_info), (MCAST_GRP, MCAST_PORT))

            sys.stderr.write("Sending Ready To Bench for %s\n" % my_mac_addr)
            sock.sendto(cPickle.dumps(host_info), (MCAST_GRP, MCAST_PORT))
  
        sys.stderr.write("Sending Go !\n")
        sock.sendto(cPickle.dumps(host_info), (MCAST_GRP, MCAST_PORT_GO))

def scrub_timestamp():
    '''Scrubing deletes server that didn't sent keepalive on time.'''
                    sock.sendto(cPickle.dumps(server_list),
                                (MCAST_GRP, MCAST_PORT))

                    sys.stderr.write("No remote system detected, exiting\n")
                    sock.sendto(cPickle.dumps(message),
                                (MCAST_GRP, MCAST_PORT))
                ''' It's time to send the synthesis to the other nodes '''
                leader = True
                sock.sendto(cPickle.dumps(server_list),
                            (MCAST_GRP, MCAST_PORT))

def wait_for_go():
    global ready_to_bench
    ''' Let's bind a server to the Multicast group '''
        ''' Let's get keepalives from servers '''
        answer = cPickle.loads(sock.recv(10240))

===============================================================================

src/health_protocol.py

def start_sync_bench_server():
    '''Server is made for receiving keepalives and manage them.'''
    ''' Let's bind a server to the Multicast group '''
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
        ''' Let's get keepalives from servers '''
        answer = cPickle.loads(sock.recv(10240))

def start_discovery_server():
    '''Server is made for receiving keepalives and manage them.'''
    ''' Let's bind a server to the Multicast group '''
    ''' Until we got a synthesis list from another server '''
    while not synthesis:
        answer = {}
        ''' Let's get keepalives from servers '''
        answer = cPickle.loads(sock.recv(10240))

def start_client(mode, max_clients=0):
    '''Client is made for generating keepalives.'''
    ''' Let's prepare the socket '''
        ''' While we are in discovery mode, let's send keepalives '''
        while discovery:
            sys.stderr.write("Sending keepalive for %s\n" % my_mac_addr)
            sock.sendto(cPickle.dumps(host_info), (MCAST_GRP, MCAST_PORT))

        while ready_to_bench:
            sys.stderr.write("Sending Ready To Bench for %s\n" % my_mac_addr)
            sock.sendto(cPickle.dumps(host_info), (MCAST_GRP, MCAST_PORT))

        sys.stderr.write("Sending Go !\n")
        sock.sendto(cPickle.dumps(host_info), (MCAST_GRP, MCAST_PORT_GO))

def scrub_timestamp():
    '''Scrubing deletes server that didn't sent keepalive on time.'''
                    sock.sendto(cPickle.dumps(server_list),
					
                    sys.stderr.write("No remote system detected, exiting\n")
                    sock.sendto(cPickle.dumps(message),

                ''' It's time to send the synthesis to the other nodes '''
                leader = True
                sock.sendto(cPickle.dumps(server_list),

def wait_for_go():
    global ready_to_bench
    ''' Let's bind a server to the Multicast group '''
        ''' Let's get keepalives from servers '''
        answer = cPickle.loads(sock.recv(10240))

Comment 4 Kurt Seifried 2015-03-17 23:21:30 UTC
This is now public https://github.com/enovance/edeploy/issues/229

Comment 5 Kurt Seifried 2015-03-19 04:17:09 UTC
Statement:

Red Hat does not currently ship eNovance edeploy in a product form and as such this issue has been filed upstream.


Note You need to log in before you can comment on or make changes to this bug.