[Libwebsockets] Content-Security-Policy

Andy Green andy at warmcat.com
Thu Jan 31 01:31:08 CET 2019



On 31/01/2019 08:04, Alexander Zvyagin wrote:
> Hi,
> 
> I have a question concerning Content-Security-Policy.
> 
> My application is split into two parts. The server is written in a C++
> code with libwebsocket interface (based on minimal-ws-server.c code).
> The client is meteor-react application (which is basically means it
> consists from lots of nodejs packages). The client code after
> "building" stage compiles into two files "index.html" and "index.js".
> And the server successfully serves them and my websocket protocol, so
> I am happy.
> 
> Almost. I had to disable in firefox browser checks for Content-Security-Policy.

Well, it's a good problem... you have some restrictive CSP in place already.

The default is not send anything and then anything is considered fine at 
the client, including script injection, hacks etc.

The one applied by 
LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE is that 
used by libwebsockets.org and the minimal examples, it's extremely 
strict and provides some meaningful secuity improvements.

> Now it is time to fix this little problem, but I am not sure how. The
> "index.js" file is built with webpack. The file is big. It contains
> lots of "eval()" calls from external libraries. Modifying it is not an

When I first started looking at this a couple of years ago I also 
started with that approach... how can I keep this working with some CSP.

However when I started thinking about how lws should promote CSP itself, 
the kind of workarounds I was doing there were clearly usless and 
counterproductive for any real security.

Last year I went through all the minimal examples and test server, and 
libwebsockets.org and warmcat.com (and gitohashi) sources and eliminated 
all the problematic things that stopped me having a super strict CSP. 
Particularly for gitohashi where you can't control what is uploaded and 
rendered, a CSP that totally bans any form of inline script or css, or 
stuff injected outside of head is mandatory.

So I think this is maybe a two-step journey for everyone... just try to 
survive it, and then later adapt what you serve so you can really 
leverage it.

"solving" this with unsafe-eval and friends just means the insecure 
stuff is still served and exploitable, removing a lot of the point of 
CSP.  Really using CSP means to change the stuff you're using so it 
doesn't do insecure things itself, and then use CSP to absolutely ban 
any way to reintroduce those insecure or deceptive things you purged... 
which is by then painless since your own stuff is clean of it.

> option. Most probably I need to apply a different security policy on
> the server side, right? Something with "unsafe-eval", I think. The
> file "./lib/roles/http/header.c" has the code with
> Content-Security-Policy settings, but I am not sure it is a good idea
> to modify it.
> 
> What would you recommended me to do?

The docs for the BEST_PRACTICES_ENFORCE option describe how can roll 
your own headers per-vhost instead

	LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE	= (1 << 28),
	/**< (VH) Send lws default HTTP headers recommended by Mozilla
	 * Observatory for security.  This is a helper option that sends canned
	 * headers on each http response enabling a VERY strict Content Security
	 * Policy.  The policy is so strict, for example it won't let the page
	 * run its own inline JS nor show images or take CSS from a different
	 * server.  In many cases your JS only comes from your server as do the
	 * image sources and CSS, so that is what you want... attackers hoping
	 * to inject JS into your DOM are completely out of luck since even if
	 * they succeed, it will be rejected for execution by the browser
	 * according to the strict CSP.  In other cases you have to deviate from
	 * the complete strictness, in which case don't use this flag: use the
	 * .headers member in the vhost init described in struct
	 * lws_context_creation_info instead to send the adapted headers
	 * yourself.
	 */



	const struct lws_protocol_vhost_options *headers;
		/**< VHOST: pointer to optional linked list of per-vhost
		 * canned headers that are added to server responses */

They're done as pvos because if you are using lwsws or the lejp_conf 
stuff for JSON config, you can add the extra headers there in the vhost 
definition in JSON, eg from the config for warmcat.com vhost

...

                 "headers": [{
                         "content-security-policy": "default-src 'none'; 
img-src 'self' data: https://travis-ci.org https://api.travis-ci.org 
https://ci.appveyor.com https://scan.coverity.com 
https://bestpractices.coreinfrastructure.org https://api.codacy.com; 
script-src 'self'; font-src 'self'; style-src 'self'; connect-src 
'self'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'",
                         "x-content-type-options": "nosniff",
                         "x-xss-protection": "1; mode=block",
                         "x-frame-options": "deny",
                         "referrer-policy": "no-referrer"
                 }],
...


-Andy


> Thanks a lot in advance!
> Alexander.
> _______________________________________________
> Libwebsockets mailing list
> Libwebsockets at ml.libwebsockets.org
> https://libwebsockets.org/mailman/listinfo/libwebsockets
> 


More information about the Libwebsockets mailing list