If you have ever been working on a sensitive Documentum environment (they are all sensitive, are they not?!), you might already have worked on hardening your Web Servers. One of these aspects is to have a specific set of HTTP Security Headers. In this blog, I will talk about one in particular, which is the Content-Security-Policy (CSP).
The recommendations are usually to setup a set of headers. Here is an example of header names and values (that are/should be considered secure):
- X-XSS-Protection: 1; mode=block
- X-Content-Type-Options: nosniff
- Content-Security-Policy: default-src ‘none’; script-src ‘self’; connect-src ‘self’; img-src ‘self’; style-src ‘self’;
- X-Frame-Options: SAMEORIGIN
- Cache-Control: no-cache, no-store
- Pragma: no-cache
- Strict-Transport-Security: max-age=63072000; includeSubDomains
In case you have never heard of the CSP, I like the documentation that Mozilla provides, it is very clear and provides all the necessary information for you to understand how things works as well as what you can and cannot configure.
The configuration of the CSP is really application dependent because it controls what the browser should be allowed to execute/fetch/render based on the value of the HTTP Header. With the above example, a lot of things will be disabled completely because the default-src is set to ‘none’ and everything that isn’t specifically defined in the HTTP Header will fallback with the value of the default-src parameter. This means that, for example, the browser will not even allow the load of a font from a ttf file (some application like D2 tries to load ttf files). Everything set with ‘self’ means that if it’s a resource coming from the same server (same scheme, host/dns/domain, and port), then it will be allowed. For other details, I would strongly suggest you look at the Mozilla documentation.
Applying all other HTTP Security Headers to D2 shouldn’t cause too many issues but applying the CSP as depicted in the example will completely break it. Here is a screenshot of the Google Chrome console with the “recommended” settings from a security point of view (Content-Security-Policy: default-src ‘none’; script-src ‘self’; connect-src ‘self’; img-src ‘self’; style-src ‘self’;):
Regarding the CSP, the usage of the ‘unsafe-inline’, ‘unsafe-eval’ or ‘data:’ directives are usually considered insecure. Unfortunately, most application (D2 isn’t an exception) will require some of these directives in order to work, as you can see on the above screenshot. There is always the option to use the ‘nonce-*’ or the hash value but that will require you to configure each and every resource, one by one… When you have hundreds of applications to manage that each tries to load dozens of different resources, that will most likely become an issue. Therefore, you will most probably end-up with a more relaxed configuration. Let’s try D2 with a more realistic CSP based on the above errors (Content-Security-Policy: default-src ‘none’; script-src ‘self’ ‘unsafe-inline’ ‘unsafe-eval’; connect-src ‘self’; img-src ‘self’; style-src ‘self’ ‘unsafe-inline’; font-src ‘self’; manifest-src ‘self’; frame-src ‘self’;):
That’s still not enough and that’s the purpose of this blog. The configuration, until now, is rather simple: you configure your Web Server, reload, and look for errors on the Chrome console. However, as you can see in the second screenshot, there is a problem with the D2 WSCTF plugin.
When D2 is configured to use the WSCTF plugin, it will actually execute a piece of code on your workstation that is being accessed by D2 (by the browser) through a socket using the associated protocol (WebSockets Secure – “wss://”). Therefore, this needs to be added into the allowed connection source using “connect-src wss:”. Unless I’m mistaken, I don’t think it is possible to filter this configuration further. However, doing that isn’t sufficient, it will still fail with the latest error shown in the previous screenshot: Refused to frame ” because it violates the following Content Security Policy directive: “frame-src ‘self'”. The frame ” is actually also because of the WSCTF plugin, to avoid redirections at the browser level when D2 talks to the plugin. Documentum created its own custom protocol that is being used for that purpose and that’s what is still missing.
As shown, the frame being started begins with “dctmctf:” and therefore, allowing the frame source on that scheme is fixing the issue (yes all the messages are in red, meaning it’s an “ERROR” but that’s how D2 prints these info messages…):
Therefore, in case you are using D2 (and a lot of other applications), a more realistic CSP configuration will most probably be something like:
Content-Security-Policy: default-src ‘none’; script-src ‘self’ ‘unsafe-inline’ ‘unsafe-eval’; connect-src ‘self’ wss:; img-src ‘self’ data:; style-src ‘self’ ‘unsafe-inline’; font-src ‘self’; manifest-src ‘self’; frame-src ‘self’ dctmctf:;
As mentioned at the beginning of this blog, CSP is really application dependent. Unfortunately, most apps aren’t built with CSP in mind and therefore you must make concessions to be able to strengthen your Web Servers without breaking your applications.