3 ms·
Signing the URL should prevent that, but it still seems overly complicated.
by amock 12y ago
Signing the URL should prevent that, but it still seems overly complicated.
- nitrogen 12y agoSigned URLs is how AWS and CloudFront handle access permissions without actually storing the permissions on their servers.
- amock 12y agoYes, but that's a very different kind of system. AWS has to deal with a very large number of servers handling authentication for client that aren't trusted by the credential owner. HN has clients with credentials accessing a single server. It would be much easier to just store the serialized data in Memcached or Redis since the system is already centralized and use a token to look it up. Doing so requires less bandwidth and less messing with cryptography.
- IgorPartola 12y agoPersonally, I would be ok with a system I am responsible for giving the client a signed or encrypted token. I would not trust many (any?) crypto systems to have signed/encrypted arbitrary code passed to me from an untreated client.
- derefr 12y agoNote that the client is passing you a token with your signature on it, not the client's signature. This isn't PKI, or even shared-secret encryption like RSA; this is the client receiving an opaque blob and then passing it directly back to the server, and the server verifying the URL's HMAC to prove that A. the non-HMAC part of the URL is byte-for-byte identical to the one the HMAC claims it is; and B. the HMAC contains the server's secret. I really like this approach, myself (it works really well in Erlang, where closures can be serialized like any other term), so I'll argue in favor of it for a bit: 1. OS package managers (especially those that provide automatic security updates) are, effectively, arbitrary code execution limited solely by signature verification. If you don't trust signature verification, you basically can't trust OS update infrastructure. And these are actually less secure than URL signing, when you think about it: with a signed URL, you are the signatory, and it's very easy to know if you are you. With OS updates, you have to trust the OS manufacturer has itself granted trusts only to the right entities. (Microsoft could put an update signing key from law enforcement into Windows, letting them push automatic wiretap/rootkit "updates" to selected individuals, etc.) In other words, the security of a system is derived from its weakest link—and there are links far weaker than URL signing. 2. People already do this a ton—deserializing an opaque blob of data signed by the server and then treating it as if it was something just sitting in the server's memory to begin with. Where? In "signed-cookie session storage", the default session mechanism of both Rails and Django. The only difference is that you're putting the information in the URL (where it belongs, in this case) instead of the session—although you could just as well store a continuation table in the session, and then reference it from the URL, if you liked. Okay, there's also the fact that you're storing a serialized closure instead of a public route—but in business terms, that's no more dangerous to e.g. the valuable information in your database than storing the user's effective UID in signed-cookie session storage, presuming you have administrator-role users in your system with the ability to delete that data. The one difference might be if the limited set of all your public API endpoints acts as a slapshod "sandbox" for your server, with you trusting that sandbox to protect your system. Which is to say, if your server can do more harm by executing arbitrary code than an administrator user can do by sending messages to it, you should really look into Docker/BSD jails/etc.
- IgorPartola 12y agoI certainly understand all that. What I am arguing is that while such a system is possible, and can be done securely (as you point out: package managers), and this system is very convenient, I would not trust myself to design a system like this for a random web application I was writing. Regarding your point #2: the difference, at least in my mind, is that I can serialize/deserialize data such as user ID's, tokens, etc. with much greater security than deserializing and eval()ing arbitrary code. If you managed to fake another user's session ID within a signed cookie, you'd do some damage to my application. If you managed to remotely run arbitrary code on my servers, you'd do a lot more damage.
- derefr 12y agoWould you trust such a system if it was built into the web framework you were using, such that the closure signing/serialization/etc. code was thoroughly tested in many environments (e.g. Seaside)? Or, actually, is it just the signature-checking code you're worried about writing? nginx (among many other reverse proxies) has a battle-tested signed-URL parsing module[1] available as part of its authentication-time processing. In such a setup, you tell nginx which routes need signature protection, and then nginx will only proxy_pass requests on those routes to your app when the signature is valid, stripping the signature off in the process (so they become regular unsigned requests as far as your app is concerned—with the fact that they made it to your app at all telling you they were signed.) With that architecture, the only code you'll write is the code to generate signed links that comply with ngnix's expectations (which there might already be a library to do in your language.) Either way, if you screw that part up, you'll just have a bunch of invalid links, not a security hole. [1] http://nginx.org/en/docs/http/ngx_http_secure_link_module.html http://nginx.org/en/docs/http/ngx_http_secure_link_module.ht...
- IgorPartola 12y agoYes, if my involevment was limited to just creating a closure and passing it to the library that is secure, vetted and tested, then sure. With project like HN, I think all of this would be written from scratch, but if e.g. Django had this feature built in, I would be much more comfortable with it.