[Python-Dev] Python Remote Code Execution in socket.recvfrom_into()

Donald Stufft donald at stufft.io
Tue Feb 25 15:20:24 CET 2014

On Feb 25, 2014, at 8:33 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:

> On 25 Feb 2014 23:09, "Maciej Fijalkowski" <fijall at gmail.com> wrote:
> >
> > On Tue, Feb 25, 2014 at 3:06 PM, Chris Angelico <rosuav at gmail.com> wrote:
> > > On Tue, Feb 25, 2014 at 11:59 PM, Maciej Fijalkowski <fijall at gmail.com> wrote:
> > >>> Last issues:
> > >>> - hash DoS
> > >>
> > >> is this fixed?
> > >
> > > Yes, hash randomization was added as an option in 2.7.3 or 2.7.4 or
> > > thereabouts, and is on by default in 3.3+. You do have to set an
> > > environment variable for 2.7 (and I think 2.6 got that too (??)), as
> > > it can break code.
> >
> > No, the hash randomization is broken, it does not provide enough
> > randomness (without changing the hash function which only happened in
> > 3.4+)
> The blind hash collision DOS attack was fixed in all applicable branches. There was then a second vulnerability in the randomisation that still allowed a relatively straightforward invocation specific secret recovery attack against earlier versions that is only fixed with the SipHash change in 3.4.
> You and the other PyPy devs apparently feel that the existence of the second vulnerability means it isn't worth your while to fix the original one either. While this mirrors the core team's original position that it was up to applications and frameworks to deal with the problem, conflating the two vulnerabilities like that is still just your perspective, not ours (in addition to all the same measures that limited the impact of the original issue, there are many measures that specifically mitigate the latter one, with process recycling being one of the simplest).

I don’t have a PoC but my gut is that process cycling is not nearly enough to mitigate the second class of attack. You’d only need 256 * N requests to recover the secret where N is the number of samples you need to factor out network noise. However if you decide you don’t care about recovering the secret and you just care about DoSing a server you can just hit it with colliding values for all 256 possible values. 255 of them will complete quickly and one of them will take a long time, repeat this a few times and you’ll have the server DoS’d in a short amount of time.

I’m not sure what you mean by I don’t think it’s worth my while. I don’t run any project where I would fix this in. I do agree with the sentiment of the PyPy developers that implementing this fix is more or less pointless for PyPy because it’s so trivially worked around. Saying that the original fix fixed the original issue is taking a very narrow view of what the original issue even is. It’s not *wrong* to take that view, but I don’t think it’s very useful outside the context of not wanting to admit that the original fix wasn’t good enough. I *do* believe that calling it fixed is misleading to people who will assume it means they no longer have to worry about a trivial DoS via hash collisions when they still do need to, just slightly different than before.

In the end, it’s good that it was fixed in 3.4, I wish it had been back ported and applied to 2.7 and the relevant 3.x branches. 

Donald Stufft
PGP: 0x6E3CBCE93372DCFA // 7C6B 7C5D 5E2B 6356 A926 F04F 6E3C BCE9 3372 DCFA

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20140225/cdf59d40/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://mail.python.org/pipermail/python-dev/attachments/20140225/cdf59d40/attachment.sig>

More information about the Python-Dev mailing list