Hacker News new | comments | show | ask | jobs | submit login
Security on an untrusted client - locking down a javascript library (filepicker.io)
31 points by ananddass 1604 days ago | hide | past | web | 22 comments | favorite

For anyone that kept seeing "HMAC" and thought "What in the hell..." I wrote an article (stream of thought in story format) describing how you might try and secure an API call, how AWS does it and eventually how 2-legged OAuth can be utilized to do it:


NOTE: This is written from the perspective of "My god, what does this all mean?"

NOTE #2: You can do away with almost ALL of this complexity if you just force everyone onto SSL connections, but then you have to be ok with the increased latency introduced connection-(re)negotiation; just depends on what your API needs to do.

NOTE #3: I think the title of this article is misleading... there is no security on an untrusted client using HMAC -- if your client knows your secret AND they are untrusted, then you have problems.

I wasn't clear from the article how the JS library running client side is adding the secret to the digest before sending the request to the server to verify and process.

For those AWS folks out there, that is what your AWS secret is used for -- your request, e.g.: /ec2/launch?cust=bdillon&size=xl&quant=2&sig=akjDjlasdmnDASkljasd

to sign the entire request, so when AWS receives the request, the first thing it does is attempt to re-create the exact same signature using the secret it has on file for "bdillon" (or whatever customer-identifying info was sent)

This requires both the caller and server to know the secret and I am not clear on how filepicker is solving this from this article... very broad strokes, no specific impl details from what I saw.

Yup, didn't want to get into the weeds with the specifics, but we use the same procedure as AWS, where we use the shared secret to recreate the signature provided and then match the two (as well as verifying the method performed is allowed in the policy, and the expiry time is correct). Happy to go into more details if you'd like, also available at https://developers.filepicker.io/docs/security/

In reference to the js library as client-side, the key thing we were looking to solve was how to implement a token-based scheme where even if someone had access to the running javascript via xss or just malicious console behavior, the amount of damage they could do would be limited. Balancing that with the simplicity requirements to not use handshakes and allow for embedding urls within <img> tags resulted in the scheme we implemented

Critical feedback: This article doesn't seem to be grammar-checked and there's at least one paragraph that is incomplete. The entire thing is difficult to read or understand even for someone with crypto knowledge. I recommend getting future articles peer-reviewed by a layman.

Thanks for the feedback folks. Did one more rev and clean it up. Thanks for the suggestion.

There are also some very important facets to Information security that you are missing. You describe security as being "based on knowing, doing, or owning something that no one else can". But this is not quite right. You are speaking to only one aspect of security - confidentiality. There is also integrity and availability. Additionally, you are only speaking to the authentication aspect of confidentiality. Your "knowing, doing, or owning" could be more succinctly described as authorization based off of "something you know, something you have, or something you are" which are the 3 main ways that someone could be identified as you they claim to be. Your signature example would generally fall under something you are - but an argument could be made for it being something you know as well.


You also described Public key cryptography as having "2 different keys. One allows for encryption and the other for decryption. In this case, the decryption key is public so everyone can decrypt." This misses the mark a little bit. The public key could be used to encrypt as well, so that only the holder of the private key can read the information. Using the private key to encrypt is generally used in digital signatures so that the recipient can verify that the sender is who they claim to be. This scenario doesn't attempt to keep the data secret, because anyone with access to the public key can decrypt the data.

Yeah. I had hoped to scope the conversation down to authentication quickly, because, yes, security means a lot of things. I clearly didn't do that well.

You distinguish between "knowing, doing, or owning" and "something you know, something you have, or something you are"? I guess there might be a slight difference between doing and something you are, but I'm not sure I see the difference?

re. Public Key Crypto. Yes. Using the public key to decrypt and the private key to encrypt is how to use Public Key for author verification and you can reverse it for encryption. One validates the author and the other protects the data.

You are right to say that a better way of saying the sentence would be: "in the case of digital signatures, the public key is used to decrypt thus everyone can decrypt."

Thanks for helping me with this. Will have to be more more clear next time I write something.

The something you are (which generally doesn't apply to web-based authentication) are biometrics. So something you are - the pattern of blood vessels in your retina - is something very different from something you "do". The fact that you have "muscle memory" that allows you to sign your name a certain way would again be "something you are". I can't pass that on to someone else - only I can do it.

My syntax checker went crazy with all of those missing periods.

Cool article,

I think as a first step the approach makes sense. I'd propose security is broader than secrets--I think one frame is Authentication, Authorization and Audit (sometimes called the "Gold Standard", because of the repeated "AU" prefixes. Haha, CS meets chemistry humor.).

Anyway... In my mind, Authentication is about secrets, but that can fail. So you use Authorization, so when bad people get access you limit what's compromised. When those two fail, you at least have Audit to either catch the bad actor when they start making trouble, or at worst you can figure out how to stop breaches in future.

And these can mix and match. My two cents.


I like the breakdown between the three. The first two make sense from an API standpoint, hence why we have policies that can specify the range of what a bad actor has access to. We do auditing on our side to keep tabs on anything that seems out of place

TLDR; we use hmac signed requests with expiration a la AWS

"being able to encrypt a message is proof that they are who they say they are"

Not true. All that that proves is that whoever is on the other end knows the secret.

In that sense the title ("Security on an untrusted client") is misleading. The only way anyone's going to secure an untrusted client to a point where the system gains my trust is by using:

- A one-time password [1] to mitgate MITM, key loggers and screen grabbers.

- Identity federation (not OpenId or OAuth) that means I can use credentials other than the credentials I use from a trusted client.

- An application firewall [2] that redacts HTML on the fly so that the disclosure impact of a single GET request is reduced.

- Ideally (although this is taking things to a whole new level of paranoia) a data diode [3] that protects my server.

[Edit] The use case will obviously drive out the requirements, and the shopping list above is for a basic web application that only goes as far as form data. If you're looking to work with files you'd have to write up some code that ensures files don't contain nasties. While AV will go some way to doing that, the only way to really get around that is through conversion. I.e. .DOCX is converted to .PDF, .PNG to .JPG, and so forth. Yes, that limits the file types you can deal with, but if you're this far down your requirements aren't exactly main stream.

[1] RSA SecureId (http://en.wikipedia.org/wiki/RSA_SecurID)or Chip & PIN challenge/response (https://en.wikipedia.org/wiki/Chip_Authentication_Program)

[2] Eg. F5 Big-Ip app security manager (http://www.f5.com/products/big-ip/big-ip-application-securit...) or Microsoft's Unified Access Gateway (http://www.microsoft.com/en-us/server-cloud/forefront/unifie...).

[3] Tenix is a high-end solution used by governments. The old Whale Commuications Intelligent Application Gateway used to be a cheap but very effective alternative (http://en.wikipedia.org/wiki/Unidirectional_network).

Correct. I was not careful enough with all the steps of my logic here.

Being able to encrypt the message proves that the party knows the secret, which if they are the only one who knows it, proves that they are who they say they are.

Indeed, the part about "which if they are the only one who knows it" is important. If you can't trust that, then security starts to break down.

You can sidestep it by instead trusting that they own a device that no one else has, like an one time password. Now, the statement gets a bit longer:

Being able to encrypt the message => the party knows the secret => (If you ask for multiple one, you can beter trust that)=> they have the otp => they are the only one who has it => they are who they say they are.

You can never trust a client you don't have absolute control of. Unless you have such control, you can only assume the client is compromised.

I understand that your scenario calls for trust where none is warranted†. That's risk. And your mitigation is to be clear how you handle a compromise (likelyhood).

† As does probably 99.9% of sites on the Internet.

"being able to encrypt a message is proof that they are who they say they are"

This is not exactly right. Encryption ensures people cannot eavesdrop on a message but it does not ensure you can verify the sender. You need authentication instead, which is what HMAC does in this case.

In general that's true, but specifically referring to public-key encryption only the holder of the private key will be able to create an encrypted message, so it serves as authentication

But what if an attacker intercepts this encrypted message and replays it?

You can either use a timestamp (that is included in the HMAC calculation to ensure it isn't changed) to allow a replay-window (this is what AWS does) or you can utilize a NONCE value retrieved from the server before hand and recorded as "played" once it is used so no other requests can ever be sent using that nonce.

Using a NONCE has some advantages and some disadvantages. There's no need to retrieve the nonce from the server, the client can generate any random value and include it in the signature. However, one of the beautiful properties of HMACs is that the server you're talking to does not need any stored information other than the shared secret to authenticate the request. That makes HMAC-Authentication feasible over a cluster of servers that share no storage if the secret is fixed. Using a NONCE requires that the servers share a storage that updates pretty much immediately, so they all need access to the same datastore that must have practically no replication delay. Otherwise an attacker could still replay the request, just against a different server.

Excellent callouts about the NONCE, thanks for adding them! (great points about how this impacts your backend)

"Security breaks when humans are involved"

Pretty much sums up life. It's gotten to the point that zero-day exploits scare me less then users writing passwords down on sticky notes, clicking on random links, or letting random people in the building.

Since our customers are developers of web and mobile applications we are obviously focused on ensuring that there are no zero-day exploits.

But yes you are right, we have to ensure that we factor in the human angle when designing the solution.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact