Missing web security feature: Signed web assets with browser validation

It is finally expected that reputable websites use TLS for all connections. Google, Bing, Facebook, Reddit, many smaller websites, even this blog – we all use HTTPS by default. This protects the privacy and integrity of internet browsing from intrusion near the user, or between the user and server.

At the same time, though, a security threat is encroaching from the server direction. Increasingly, no one except a few large corporations has control over their servers anymore. Even data that needs to conform to HIPAA security requirements is being moved into "the cloud" – which is to say, onto computers managed by a few companies. This is primarily the largest cloud provider, Amazon; trailed by Microsoft, IBM, and Google.

It's not just that the servers reside at these large providers in the form of virtual machines which can potentially be accessed by the provider, or any government that can compel them. It's also that increasingly, servers are being abstracted away. Amazon's Lambda offers a premise where the website author just writes code, deploys it "on the cloud", and does not worry about servers. Google has long offered this with AppEngine.

What does this mean for security against cloud providers? Or for security against governments?

Suppose you run a website and want to protect your users from wholesale monitoring and surveillance without warrants. You cannot achieve this using current cloud infrastructure because a critical security component is missing.
  • If your website stores data in a cloud database without encryption, then obviously, this data is available wholesale. It is accessible both to the cloud provider and to any government that can compel it, and in an easy format.

  • Suppose you encrypt your database. If you store the keys anywhere on your cloud server at any time, the keys are accessible both to the cloud provider and to any government that can compel it. They can decrypt your user data without informing either you or your users.

  • Suppose you encrypt your database, but you use a secret key derived from each user's password, and you do the encryption locally in the browser. You design your application so that neither the password, nor the key, nor the plaintext data are ever sent to the server. Would this be secure?

It's not secure, because the cloud provider – with no choice in the matter, if compelled by the state – can simply replace the JavaScript that you serve to users with their own, which does leak information to the server. The replacement can be targeted to specific users – e.g. IP addresses of known journalists – so that no change would be noticed by your developers or other users. Since the cloud provider operates your TLS certificate, there's no way for a user who's targeted by this trojan to distinguish your authentic website from the slightly modified one with a backdoor.

Currently, the only defense is to maintain your own datacenter. This is cost-prohibitive, and makes it impossible to defend against Distributed Denial of Service attacks. You must choose between:
  • Assurance against DDoS. Requires surrendering your TLS key to CloudFlare or Amazon. A government can compel the cloud provider to backdoor your website, and you'll never notice.

  • Assurance against someone backdooring your website. In this case, your website's load times are worse because it is in one location, and it's vulnerable to DDoS unless you have tremendous resources.

It should be possible to benefit from cost-effective DDoS protection, at the same time as knowing if or when your users' privacy is compromised.

There is a solution. It is to sign website assets using keys that do not have to be online for TLS.

Standard needed: Signed web assets

A new standard is needed, including support in browsers – Chrome, Firefox, Edge, Opera, Safari – allowing website authors to sign all components of a website. This would include HTML, CSS, JavaScript, images, video, and WebAssembly. A new, no-nonsense binary format for signed files could be defined (preferred), or a MIME type such as multipart/signed could be used (complex and inefficient since designed for email). Signing would be done using a private key separate from TLS. There would need to be a new type of signing certificate similar to code signing in Microsoft systems.

This would not work without browser support. It would have to be an initiative spearheaded by implementers of at least two major browsers.


Boris Kolar said…
Service Worker may be a solution for some use cases.

1. Write a service worker that will intercept network requests and check signature.
2. Provide a simple html page installing the service worker (on a site under you control).

Cached version of service worker will be used when/if your site goes offline.
denis bider said…
If I have users who are willing to run arbitrary code, I don't need a browser to begin with. I can just ship downloadable software that provides the service my website would have provided. :-)

The problem is the platform specificity of downloaded software. If I ship an iPhone app, an Android app, and a Windows app, all of those have code signing available. However, if I want to ship a cross-platform app using WebAssembly, there's no code signing available - just TLS.
Boris Kolar said…
Service Worker is a web API (implemented in browsers). Service workers are installed locally (installation is done by the browser) and they can handle every network request, allowing you to implement code signing (and/or encryption). The only danger is if someone takes over your domain, because new domain owner would be able to update service worker.
denis bider said…
Oh, I see. Thanks for the explanation. :-) But yes, I think you've pointed out the issue - the service workers would themselves need to be signed...

Popular posts from this blog

When monospace fonts aren't: The Unicode character width nightmare

Thoughts on Bitcoin - and why I cashed out of BTC at $18k

VS 2015 projects: "One or more errors occurred"