[Twisted-Python] Broker leak in spread server on login failure = denial of service?
David K. Hess
dhess at verscend.com
Fri Sep 9 16:36:31 MDT 2005
On Sep 9, 2005, at 5:01 PM, Jp Calderone wrote:
> On Fri, 9 Sep 2005 16:31:28 -0500, "David K. Hess"
> <dhess at verscend.com> wrote:
>
>>
>> I believe I've discovered a broker leak when a checker denies a
>> login and that it can be used to launch a denial of service
>> attack on a spread server.
>>
>> When a checker throws a Failure exception, since requestAvatar in
>> the realm doesn't get called, the realm (or anything else)
>> doesn't end up with a reference it can use to disconnect the
>> network connection that was denied login.
>>
>> If a malicious (or just buggy as was my case) client tries to
>> login over and over again and doesn't shutdown each connection
>> from the client side, the server will continue to leak brokers
>> until (under Windows) the select() call begins to fail because
>> there are greater than 512 (with a stock Python build) file
>> descriptors open and being monitored by the reactor. At this
>> point, your server is dead as the reactor goes into an infinite
>> loop retrying failing select() calls when this happens.
>>
>
> It's easier than this. A client could connect and send no bytes at
> all. The socket would remain open forever with the default factory
> behavior, allowing a user to exhaust all available file descriptors.
>
> This is an attack possible on any server that doesn't limit new
> connections or time out existing ones somehow.
Excellent points.
>
>>
>> What I think might be best is if another method in the realm (say
>> "loginFailed(self, mind)") was called with the remote reference
>> so the server could then call mind.broker.transport.loseConnection
>> () on it. It would be nice too if this was after the Failure had
>> been sent back across the connection and not before.
>>
>> clientConnectionMade in PBServerFactory also looks promising but
>> it doesn't seem possible to figure out which connection is
>> authenticating from within the checker.
>>
>> Can anybody offer some advice on how best to handle this?
>>
>
> Rather than extending the cred interface, which may not even be
> invoked, I'd start by altering the behavior of the server factory.
> Either impose a per-IP connection limit, or a connection rate
> limit, or a timeout for idle connections, or something along these
> lines. You might want to look at
> twisted.protocols.policies.LimitTotalConnectionsFactory or
> TimeoutFactory.
From my point of view, I don't want to punish the many for the sins
of the few. I know exactly who I want to disconnect when a login
fails. Also, unfortunately, my communication patterns don't support
idle timeouts *after login* so I can't use a timeout to get rid of
these.
What I want is what you would find in a normal Unix login. If there
is no activity at the login prompt then after a while you get a
disconnect. If you don't properly authenticate, you get a disconnect.
Once you are logged in, no timeouts. I'd like that kind of behavior
in my factory/realm/checker (even when the client doesn't initiate
authentication).
I guess what I'll try is using clientConnectionMade to register a
callLater of say 5 seconds on the broker's transport.loseConnection
(). I can then cancel it if requestAvatar is called in the realm.
That will cover both the denied login and 0 bytes transmitted cases.
> Hope this helps,
Yes, it did. Thanks!
Dave
>
> Jp
>
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
>
More information about the Twisted-Python
mailing list