This is a great concrete example why you should never run debug mode on a public server. Django can only do so much for redacting private info. This is also a great example of how insecure pickle is!
Luckily, Django provides checks to avoid this kind of leakage before hitting production with https://docs.djangoproject.com/en/2.1/howto/deployment/check...
Remote Code Execution on a Facebook server
31–40 of 207 posts
Re: Remote Code Execution on a Facebook server
#32Wow, a fix in <24 hours, that's pretty impressive.
I mean the fix is toggling a single environmental variable from True to False, on a system that isn't normally accessed by customers, so the risk is really small in rolling out the change.
Re: Remote Code Execution on a Facebook server
#33So, this was simply taking advantage of a crash-prone webapp running on a debug-enabled Django instance using Pickle session serialization, and more specifically this was only possible because _Django didn't redact the stored secret key used to sign serialized inputs out of the crashdump information!_ Did the author tell Django about this yet, or is this a (possibly unintentional) 0-day? Besides the above interesting…
Maybe I misunderstood the article, but I thought it said that Django does strip this information, and the Sentry app went out of its way to store the secret key in the SENTRY_OPTIONS payload. This custom, non-Django code effectively circumvents Django’s protections, making the bug the responsibility of Sentry, not Django.
Wait, so that means Sentry kind of has a vulnerability.
Re: Remote Code Execution on a Facebook server
#34Earlier quoted context omitted.
I tend to agree w/ the FB security team here. Don't list email addresses owned by an adversary in your account. :-/
> Don't list email addresses owned by an adversary in your account. I mean if you're delegating your email address, your staff aren't adversaries. But they shouldn't be able to, say, drain all your retirement accounts either. Just because I want people who search for alex.krupp@gmail.com to be able to find my Facebook account doesn't mean I want password reset requests sent there. It wouldn't be at all unreasonable t…
Re: Remote Code Execution on a Facebook server
#35Other than fixing the Django source code , is there any OS level mitigation techniques that can detect and prevent such security vulnerabilities? I am thinking something like selinux, docker or chroot - a bit like internal firewall for Django (or any other webapp). Any suggestions on the links to latest best practices?
Maybe if you tell your OS "never let any data containing this string leave the machine" you can kind of mitigate this, but it's unlikely to work. The HTTP response is probably compressed. Someone probably base64-encoded the thing and stuck it inside some JSON, which is then base64-encoded again.
Ultimately, it's about managing complexity. Django and the extension punted: Django says it will print anything and everything it has access to, and the extension has a documentation caveat about how bad that would be. One could imagine an API that tries to be resistant to this sort of thing; when the extension is initialized, it deletes the key from the environment dictionary (only partially possible), stores it in a private attribute, and only provides public EncryptAndSignCookie and DecryptAndVerifyCookie methods. This will be better than a documentation caveat, maybe, but the truly ambitious debug mode will probably get the key and print it out.
(I would also point out that I'm not a fan of storing state in encrypted+signed cookies, if only because there is no way to revoke a stolen cookie without revoking every cookie ever. If you have the state on the server to store a revocation list, you might as well just store everything there and never have this problem.)
Re: Remote Code Execution on a Facebook server
#36Earlier quoted context omitted.
> Don't list email addresses owned by an adversary in your account. I mean if you're delegating your email address, your staff aren't adversaries. But they shouldn't be able to, say, drain all your retirement accounts either. Just because I want people who search for alex.krupp@gmail.com to be able to find my Facebook account doesn't mean I want password reset requests sent there. It wouldn't be at all unreasonable t…
Even if they changed it so that you could select where to send the password reset, rather than having it go by default to all accounts, that still means anyone with delegate access to the email address could go and request a reset on your behalf.
That's how it should work. You shouldn't have to remember which email address you signed up with in order to request a password reset. But that's fine as long as the pin number only gets sent to an account that's locked down to a degree that's appropriate relative to the assets under protection.
Re: Remote Code Execution on a Facebook server
#37Other than fixing the Django source code , is there any OS level mitigation techniques that can detect and prevent such security vulnerabilities? I am thinking something like selinux, docker or chroot - a bit like internal firewall for Django (or any other webapp). Any suggestions on the links to latest best practices?
Ultimately the only thing you can do is not run debug mode in production, not use insecure serialization formats and not leak secret keys. If you want to be a bit more pre-emptive about it, avoid language-specific serialization formats especially in dynamic languages ("serialization" that executes arbitrary code seems more common in those) and use taint checking or, better, a type system that can avoid leaking secrets (you likely need rank-2 types to be able to have values that you can use in certain contexts but never access outside them, a la http://okmij.org/ftp/Computation/resource-aware-prog/region-... ). It sounds like Django already has some level of taint-like functionality but this plugin/addon (sentry) then didn't use it properly. So, multiple failures interacting to create this vulnerability - I guess we should take that as a sign of progress compared to the days of basic buffer overflows?
Re: Remote Code Execution on a Facebook server
#38In contrast, I submitted a bad vulnerability in Facebook’s password reset feature yesterday that lets attacker’s send password reset PIN numbers to email addresses the user doesn’t necessarily control. The security team said to works as designed so they’re not going to fix it. Basically if someone requests a password reset on your account then the PIN number gets sent to all email addresses associated with your accou…
As an analogous example, what if you did the "forgot my password" flow and they sent a recovery code over SMS to any listed phone number on your profile, sent a twitter DM to your listed twitter account, and sent postal mail to any postal address on your profile? (All at once, without waiting or confirmation.) That would expand the attack surface significantly, and it would be pretty easy to steal someone's account by stealing their postal mail. This case is similar: a secure email for account recovery and a less secure email for contact info, but Facebook forces you to use both for account recovery.
On the other hand, some people intentionally want multiple account recovery emails so they're less likely to lose access to their account. I imagine Facebook's hesitation with this feature is that it's hard to clearly communicate the distinction between the two use cases, and they want to bias toward simplicity.
Re: Remote Code Execution on a Facebook server
#39Earlier quoted context omitted.
I mean the fix is toggling a single environmental variable from True to False, on a system that isn't normally accessed by customers, so the risk is really small in rolling out the change.
Sometimes you’re lucky if a company reads your report in this time but of course I would expect and we generally see much better from the likes of Facebook etc
Re: Remote Code Execution on a Facebook server
#40Other than fixing the Django source code , is there any OS level mitigation techniques that can detect and prevent such security vulnerabilities? I am thinking something like selinux, docker or chroot - a bit like internal firewall for Django (or any other webapp). Any suggestions on the links to latest best practices?
> wow, it looks like it’s a sort of Django SECRET-KEY override!
Sentry uses its "own" secret key, so Django doesn't know it should be stripped from the stacktrace.
A simple `DEBUG = False` in `settings.py` would fix the bug. You don't have Django run in debug mode in production.