4 ms·
Please tell me you've seen this before? https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/
by CiPHPerCoder 9y ago
Please tell me you've seen this before? https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/ https://www.nccgroup.trust/us/about-us/newsroom-and-events/b...
- EGreg 9y agoI haven't seen this particular article, but having read it, I can tell you: there are different threat models. You can't be secure against them all on the Web. Of course we have to trust the server to deliver the initial code. The same is true with apps delivered via the appstore etc. But that doesn't mean you should be send and storing password hashes to the server, even if generated by PHP. It doesn't mean you should be using the session cookie alone as a bearer token to access a session. First of all, you have to agree that a security requirement in addition to a cookie doesn't make things less secure. Secondly, with Web Crypto the Web has a way to mark keys "non exportable". If the website is sending you the wrong resources then of course anything can be sent, and web-based code isn't the ultimate way to protect the user. The same is true of other approaches. However if the initial code download wasn't tampered with, then you are far more protected. Because the secret private key won't be exported from the browser website. And it won't be accessible to anyone outside the JS environment that asks for your password or finger to derive a key to decrypt the master key from the local database. And in that JS environment, you can make sure (via closures) that no one gets access to it in "userland". OH AND YOU SHOULD ALSO BE USING A PRIVATE KEY PER USER TO ENCRYPT DATA AT REST ON YOUR DATABASE, AND STORE THIS KEY IN THE DB MULTIPLE TIMES - EACH ONE ENCRYPTED BY THE USER'S DEVICE KEY. You don't store these device keys. Successfully authentication requests from the device send this key. So once again you need to obtain this key in order to unlock user's info needed for the request. And users can send permissions to unlock their information to each other in sidechannels. You can take this security VERY far... So it's strictly more secure than the server side database for passwords, even hashed and salted with key strengthening. BUT, don't advertise it because then it introduces security attacks where people over-rely on this to te detriment of the vectors mentioned in the article. PS: Oh. This was written in 2011, before the Web Crypto standard I am referring to was published and adopted by all web browsers. I do NOT recommend doing the crypto methods in JS! And yes it has a secure RNG now. https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_... Also Object.freeze() is a thing now.
- CiPHPerCoder 9y ago> But that doesn't mean you should be send and storing password hashes to the server, even if generated by PHP. There is prior work in this genre. Something like SPAKE2-EE might be worth looking into here. https://github.com/jedisct1/spake2-ee https://github.com/jedisct1/spake2-ee > It doesn't mean you should be using the session cookie alone as a bearer token to access a session. Well, maybe. A random ID that just tells PHP where to look for the session data, with all the data persisted server-side, is secure as long as it's transferred over HTTPS. Most frameworks/libraries abstract the implementation details away, but generally: <?php use ParagonIE\ConstantTime\Base32; $random = Base32::encode(random_bytes(32)); This value will be unpredictable and doesn't require an HMAC to ensure this property. The only time the HMAC adds value is if you're using the user's computer as a data mule for the entirety of session state rather than "look up this identifier in a database". In those use-cases, you enter the usual JWT abuse territory, as outlined here: http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-for-sessions-part-2-why-your-solution-doesnt-work/ http://cryto.net/~joepie91/blog/2016/06/19/stop-using-jwt-fo... In this genre, we're working on PAST (although this is probably going to be renamed before it's finalized) to solve the cryptography flaws baked into the JWT standards (collectively, JOSE): https://github.com/paragonie/past https://github.com/paragonie/past That doesn't solve the "replay attack" issue (which may be what you were referring to with bearer tokens). > OH AND YOU SHOULD ALSO BE USING A PRIVATE KEY PER USER TO ENCRYPT DATA AT REST ON YOUR DATABASE, AND STORE THIS KEY IN THE DB MULTIPLE TIMES - EACH ONE ENCRYPTED BY THE USER'S DEVICE KEY. I'm not entirely sure what you're getting at here. If I needed to share a key across devices, I'd either use Diffie-Hellman or Shamir Secret Sharing to accomplish the task (depending on use-case and threat model). Perhaps there's a lot of implementation detail that's not being discussed here that I'm missing and what you're saying is a conservative local maximum, but it stuck out a tad bit.
- EGreg 9y agoPerhaps. What I mean is, the session id as a bearer token for example can still be insecure even if sent via https. For example, if PHP scripts use $_REQUEST and session_start() uses the id sent in $_GET from GPC. So you can have session fixation attacks. However, if you additionally require devices to sign all requests with their private key (stored in IndexedDB for the domain and not exportable) then Web Crypto can help mitigate many classes of attacks, including session fixation and CSRF. (It can even increase security over http without https, even though it's an academic point.) Today we wrote up an article about this, actually, referencing your guide: https://qbix.com/blog https://qbix.com/blog It goes into more detail about all this.