8 ms·
Anyone interested in signed JavaScript? Initiatives like this are great. However, I'm most interested in signed JavaScript. I'm surprised that there isn't more
by jonpaul 13y ago
Anyone interested in signed JavaScript?
Initiatives like this are great. However, I'm most interested in signed JavaScript. I'm surprised that there isn't more of a discussion going about this since JavaScript crypto is near worthless if it's served from an untrusted server.
For example, let's say that you have an application that uses client-side crypto in JavaScript. Then let's assume that the server (that serves up the client-side app) is hacked and the client-side application is modified to send your private keys back to the hacked server, there is currently no way you'd know as the consumer of that client-side application. If signed JavaScript existed, then browsers could alert you that the JavaScript that you're running has been modified and doesn't match the signature, so it refuses to execute it.
- tlrobinson 13y agoYes, however isn't this sort of what HTTPS is supposed to accomplish?
- jonpaul 13y agoNot as far as I know... I could run a server that serves up HTML/JS and if that JS was modified by an attacker who hacked the server, consumers of my HTML/JS wouldn't know regardless of whether it's served up on HTTPS or not. Please correct me if I'm wrong.
- jonknee 13y agoIf the server is compromised you're SOL.
- jonpaul 13y agoExactly. That's why I'm advocating for a signed JavaScript/HTML/webapp standard of some sort.
- bradleyland 13y agoThat is not true if you're using code signing. If someone compromises the server, they can overwrite the files, but they cannot forge code signing without additional access to code signing private keys. Security is achieved through layers. No single layer can protect you from everything, but we lay down the gauntlet in the hopes that an attacker will encounter a road block that they cannot pass.
- untothebreach 13y agoHTTPS just tells you that you are talking to the 'right' server. It doesn't tell you anything about the validity of the javascript that the server is sending you.
- tlrobinson 13y agoIn both cases you're using a private key, which you need to protect, to authenticate you are who you say you are. I suppose the difference is a JS bundle could be signed offline and uploaded to a potentially insecure server/CDN/app store/whatever.
- bradleyland 13y agoThe fact that a private key is used doesn't mean HTTPS and code signing are the same. HTTPS says, "The communications you send to the server cannot be intercepted and changed between the client and server, and the identity of the server you're connecting to has been verified by one of your trusted certificate authorities." HTTPS promises that your communications cannot be snooped on, and the person you're talking to is verified by a mutually agreed upon third-party. Code signing does something entirely different. Code signing says, "The code you're about to run was written by the developer specified in the signing certificate, and has not been modified since it was signed. The identity of the developer has been verified by one of your trusted certificate authorities." So the practical difference is this: Say your browser requests https://domain.com/random.js https://domain.com/random.js. HTTP ensures that you're connecting to domain.com, and that your communications won't be changed or observed in transit. However, it does not guarantee that some malicious third-party didn't overwrite random.js on the server. With code signing, you can accomplish that. An author can "sign" a code package so that any alterations to the code itself would cause a certificate invalidation.
- sdevlin 13y agoIf you don't trust the server, you're screwed anyway.
- jonpaul 13y agoMaybe, maybe not. But if you only rely upon the client-side feature of the app and if code signing is employed, you could safely use the app without fear of potentially your private data being stolen (assuming the original code doesn't send private data to the server).
- sdevlin 13y agoWell, let me explain my thinking. Suppose we sign https://server.com/sjcl.js https://server.com/sjcl.js. That resource is now tamper-proof in the event that server.com is compromised. But what about the rest of the application HTML/js? For example, an attacker could just say: <script src="/sjcl.js"></script> <script>sjcl = ...</script> And overwrite the library on the client side. Ok, suppose the browser support for content-signing prevents this somehow. The attacker can still modify the application-level code to use the library unsafely. I'm not totally familiar with the API sjcl exposes, but consider something like the e=1 RSA bug that was found recently. Even if sjcl's API is so great that it's impossible to misuse, an attacker could simply render application code that doesn't use it at all. Or he could just log keystrokes and phone home the pre-encryption content. What if we sign everything, including application HTML/js? Now we have another problem. We've basically resigned ourselves to serving only static content. We can't render any user input, because this would require a new signature. Probably not a useful web app.
- methehack 13y agoA single page web app might be statically delivered and useful... Further, I think it just means that the page that does the crypt/decrypt has to be statically delivered, not the whole app. EDIT: so..if you had a single page web app, signed or even checksum'd the whole hunk in a known good state, couldn't you then trust the execution of the app? Further if you had an external service (as I propose in a comment below) that validated the signature/checksum couldn't you then trust the whole package?
- tghw 13y agoIt occurred to me the other day that it should be pretty simple to write a script that gets loaded first on the page and removes all subsequent scripts, then loads them itself, checking the MD5/SHA1 of the script against a known good value, stored in that script's attributes. <script src="scriptloader.js"></script> <script src="jquery.min.js" data-md5="a1b2..."></script> Then you could decide to not load scripts that do not match the correct hash. It could even ping the server to alert it to broken scripts.
- sdevlin 13y agoHow would this protect you against a malicious server?
- tghw 13y agoIf the server serving the HTML is pwnd, then it doesn't, but it doesn't really matter then, either. This protects against any external scripts being unexpectedly modified, e.g. someone MITM your jquery source.
- sdevlin 13y agoI guess that's true, but in practice XSS is a much bigger threat to your application than someone MITM'ing an HTTPS connection to Google's (or whomever's) CDN.
- sneak 13y agoIf you don't allow external scripts to be modified, why host them externally at all? Why not just wget them and host them locally alongside the checksum document and skip all this silliness? Oh, also, those scripts can themselves load in other scripts you haven't checksummed. This is madness you're suggesting.
- martin-adams 13y ago>> Why not just wget them and host them locally Because you might be using a CDN for performance and bandwidth benefits. If you relying on a third party piece of code that you allow to change at any time, then it is very difficult to do any release testing to give you a known set of conditions your application should work under.
- ballard 13y agoThere needs to be both signed javascript and signed native code plugins for javascript (similar to JNI). Both of these require significant leadership because of the fragmented nature of existing implementations. The upside is an ability to deliver native crypto libraries and other plugins that remove the potential of having its internals introspected or MITMed. The protections against malicious code have to be there, so it would be the same order-of-magnitude of installing any other browser plugin.
- nadaviv 13y agoIn an Bitcoin-related open-source project I'm currently working on (still in early alpha stages), I'll be using a browser extension that verifies the response using offline signatures (with a way to verify the public key using the Bitcoin network) and compares against builds from the github repository (using travis-ci). Here's some explanation from the website FAQ: #### Browser extension Our browser extension provides improved security by verifying the integrity of the files served by the server. The verification is done using two factors: - **Cold storage signature verification:** In addition to SSL, static files (html/css/javascript) are signed using standard Bitcoin message signatures on an offline machine (the private key was created on that machine, and has no other copies) and appended to the response body as a comment. - **Comparing against the code on GitHub repository:** The source code from the GitHub repository is built on Travis-CI, and the resulting hashes are published publicly on Travis's job page. The extension compares the web server response against those hashes. If a potential attacker gains control over the web server, he still only has access to information the web server already has (which is very little). To get sensitive information, he would have to modify the client-side code to send back more data to the server. For an attacker to succesfully mount such an attack against someone with the browser extension, he would have to: 1. Gain access to the web server 1. Gain access to the personal computer of a developer with commit access to the Github repository 1. Commit his changes to the public GitHub repository, where they can be seen by anyone 1. Gain **physical access** to the offline machine with the private key For users without the extension, he would only have to do the first step. It is highly recommended to install the extension. <a class="btn btn-primary" href="TODO">Install extension</a> #### Public key verification To prevent an attacker from modifying our published Bitcoin public key, its permanently embedded into Bitcoin blockchain in a way that is [nearly impossible](https://en.bitcoin.it/wiki/Weaknesses#Attacker_has_a_lot_of_computing_power) to modify (and becomes exponentially more difficult as time goes by). The public key can be verified by taking the following procedure: 1. Take the SHA256 of the domain name ("****.com") 2. Create a Bitcoin address using that hash as the private key 3. Find the **first** transaction with that address as its *output address* 4. The *input address* of that transaction is our public key If its ever required to change the public key, the announcement will be signed with the old public key.
- sneak 13y agoSigned by whom? Signatures distributed how?