Bug 638330 (CVE-2010-3492)

Summary: CVE-2010-3492 python accept() implementation in async core is broken
Product: [Other] Security Response Reporter: Josh Bressers <bressers>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED CANTFIX QA Contact:
Severity: low Docs Contact:
Priority: low    
Version: unspecifiedCC: dmalcolm, ivazqueznet, james.antill, jonathansteffan, katzj, robinlee.sysu
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2010-12-15 20:10:15 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Josh Bressers 2010-09-28 19:26:05 UTC
From the upstream bug: http://bugs.python.org/issue6706

An old bad design choice in asyncore is how it forces the user to override
handle_accept() and then call self.accept() to obtain a socket pair.

    def handle_accept(self):
        conn, addr = self.accept()

The documentation itself shows the code above as an example of how an
asyncore-based server should handle an incoming connection.  What the doc
doesn't say is that the user calling self.accept() is exposed to different
risks:

- self.accept() can return None instead of a socket pair in which case
TypeError is raised (see pyftpdlib bug: 
http://code.google.com/p/pyftpdlib/issues/detail?id=91)

- ECONNABORTED can be raised. This is reproducible on Linux by hammering
the server with nmap (see pyftpdlib bug: 
http://code.google.com/p/pyftpdlib/issues/detail?id=105)

- EAGAIN can be raised too. I never experienced this error condition 
myself in pyftpdlib but by looking at twisted/internet/tcp.py it seems 
reasonable to catch EAGAIN too.

- The resulting address can be None, which means that the connection didn't
take place.  This is reproducible by hammering the server with nmap (see
pyftpdlib 
bug http://code.google.com/p/pyftpdlib/issues/detail?id=104).


The right thing to do when one of such events occur is to "return" as no
connection has really been established between client and server.

Now, altough handling these kind of conditions is quite easy, the API
design remains fundamentally wrong, as it forces the user to call accept().
As asyncore.py is structured right now the only chance the user has to
properly accepting a connection is manually handling all these cases in his
subclass.

Comment 1 Josh Bressers 2010-12-15 19:29:37 UTC
Upstream has a fix for this now:
http://svn.python.org/view?view=rev&revision=86084

It seems that the fix still can return None, which some clients will not handle gracefully. I suspect the solution is going to be to patch clients, not python itself.

Comment 2 Josh Bressers 2010-12-15 20:10:15 UTC
Statement:

This issue affects the version of the python package as shipped with Red Hat Enterprise Linux 4, 5, and 6. Due to the nature of this flaw, it cannot be fixed in the python language, but must be addressed in each module which calls accept().