Implementing CSP on a WordPress blog

Written on 16 February 2018, 06:34pm

Tagged with: , , ,

In the previous post I briefly described the CSP concept, along with other nice security features like SRI or CORS.
I am trying to implement the concept here, and I am describing the steps I take along the way. I am using securityheaders.io to scan the website and validate the results; and this website is hosted on Cloudflare over HTTPS.

The first impression is – WordPress doesn’t make it easy to have a proper Content Security Policy. But let’s dig into it!

Session 1

The quick wins
– Edit the .htaccess file to add the quick and dirty security headers:
X-Frame-Options, X-XSS-Protection, X-Content-Type-Options, Referrer-Policy
– Strict-Transport-Security was already enabled via CloudFlare since October 2017.

Just do it!
– add the CSP directive in the .htaccess file. Start with default-src, whitelist all the usual suspects (Twitter, Google Analytics, Cloudflare, Flickr, etc)
– at this stage, some problems are evident, but at least securityheaders.io already reports an A+ score
– the basic functionality is still there, so progressive enhancement FTW

Session 2

Now refine and iterate
– check the results on result-uri.com, or, even easier, using DevTools
– disable the syntax highlighter and the image highlighter plugins, will find something CSP-friendly later
– whitelist even more in CSP (youtube.com, among others)
– disable the report-uri, the errors are building up quickly
– finding the main problem: inline content

Keep calm and avoid inline content
– I don’t want to whitelist ‘data’, ‘inline’ and ‘eval’, which would defeat half of the purpose, so keep iterating
– as I said, WordPress makes it really difficult by inlining several things (WP emoji being one of them)
Unless you really know your web site inside and out, I would caution you to use CSP together with WordPress at the moment. (https://walterebert.com/blog/using-csp-wordpress/) Turns out, I really want to know
– removing inline content (https://www.denisbouquet.com/remove-wordpress-emoji-code/), or trying to move it inside files
– Akismet, you too? 🙁
– OK, it’s not only WordPress embedding inline content, it’s also Twitter (well, technically it was me, because I wanted my Twitter feed on the blog)
– hey, the WordPress Admin is impacted too, cannot upload images!!
– {angry+emoji} (I disabled the WP emoji above, remember?)

Session 3

– remember WP-Admin and CSP? Yeah, forget about that {sad-emoji}
– Twitter timeline and follow button embed without inline scripts – done https://publish.twitter.com/
Aksimet, really? why would you inline that?

(function(){if(window===window.parent) {document.getElementById('_wp_unfiltered_html_comment_disabled').name= '_wp_unfiltered_html_comment';}})();

– Nevermind, it was not Akismet. Just WordPress
– it looks like the admin-ajax.php inline call was trigerred by my WordPress theme for the ‘like’ system. I removed it and now the red heart is beating. Not functional, but way cooler than before B-)

End of the session 3. Kids, be very careful with CSP!

Session 4

– Who needs a syntax highlighter WordPress plugin when you have prismjs.com? Doesn’t support ColdFusion language, but I can always contribute the syntax file myself. I have to replace the code in all the previous posts, but I can automate that and the result will be semantically correct.
– Who needs to click images to make them bigger? HighSlide was nice, but it did not bring too much value.
– Ok, so 98% of cases I don’t need the images to be clickable. I can live with the rest of 2%

End of session 4. CSP enabled, securityheaders.io still indicate A+, I load no inline and eval content. Still allow ‘data’ in CSP, not ideal.
Next steps:
– some posts to be updated for the syntax highlighting and clickable images.
– add SRI to some of the JS libraries
– understand why CloudFlare automatically loads Google Analytics and try to get around their data: embedding

Session 5

– I will always write semantic code in WordPress.
– I will always write semantic code in WordPress.
– I will always write semantic code in WordPress.
– There. That’s 2 hours spent replacing custom [code] tags with <code> tags.
– Most of the images should also be ok, in case a small minority of them is still clickable it will simply open the full-size image in the same tab.
– Why does CloudFlare load Google Analytics?
– D’uh, turns out I had enabled it a few years ago. Along with two other CloudFlare apps (Earth Hour and Net Neutrality). And that was the reason why CloudFlare was inlining scripts. The explanation was in front of my eyes all the time:

If you use certain Cloudflare features, you will need to allow inline scripts in your policy. We include scripts on your domain and add some inline code when you enable Rocket Loader, Cloudflare Apps, or ScrapeShield.
If you do use any of these features, you will need to add the following to your Content Security Policy:
script-src 'self' 'unsafe-inline'
January 31, 2018: What is Content Security Policy (CSP), and how can I use it with Cloudflare?

– Next stop: some images inlined as data: elements:

Refused to load the image 'data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width....' 
because it violates the following Content Security Policy directive ... 

– This time it was Twitter. So either I accept ‘data:’ in the CSP for images, or I turn off the Twitter timeline… {thinking_emoji} I asked @TwitterDev if there is any workaround
– Remaining steps: rewrite the CSP to make it more restrictive (I started by putting everything inside default-src) and use SRI for a few remote scripts (jQuery maybe?)

End of session 5.

Session 6

– SRI done thanks to SRI Hash Generator:


<script type='text/javascript' src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" integrity="sha384-aBL3Lzi6c9LNDGvpHkZrrm3ZVsIwohDD7CDozL0pk8FwCrfmV7H9w8j3L7ikEv6h" crossorigin="anonymous">

– Made the CSP header more restrictive and very verbose (newlines added for readability):


img-src data: https://colorblindprogramming.com https://*.twitter.com https://*.twimg.com https://*.flickr.com https://*.staticflickr.com https://*.gravatar.com https://*.yahoo.com; 
script-src https://colorblindprogramming.com https://ajax.googleapis.com https://*.gstatic.com https://*.youtube.com https://*.yahoo.com https://*.twitter.com https://*.flickr.com https://*.twimg.com; 
style-src 'unsafe-inline' https://colorblindprogramming.com https://fonts.googleapis.com https://platform.twitter.com https://ton.twimg.com https://*.youtube.com; 
frame-src https://*.youtube.com https://*.twitter.com; 
report-uri https://colorbind.report-uri.com/r/d/csp/enforce;
The final CSP rules

Testing

A quick way to test the SRI is to alter the hash in the integrity attribute. As soon as you do this, the browser will report the error:

To test the CSP, I connected to the database and manually added some Javascript in a comment:

With the CSP allowing script-src 'unsafe-inline', the code executed:

With the CSP not allowing script-src 'unsafe-inline', the code did not execute and the browser reported the problem:

Next step is to keep monitoring report-uri.com for the CSP violations.

The takeaways

– use the DevTools to validate your CSP rules
– start with validate-only to ‘test in production’
– avoid inline content at all costs
– think about all the plugins that you use: are they really needed?
– make sure you create WordPress content by writing semantically correct code

That’s it! 6 different sessions and about 10 hours allocated to this little project, but I’m happy with the results 🙂

CSP, SRI and CORS

Written on 13 February 2018, 09:10pm

Tagged with: , , ,

Content Security Policy (CSP)

The modern browsers are able to interpret the Content-Security-Policy HTTP header that defines which dynamic assets are allowed to load on a given website. Alternatively, the CSP content can be sent using meta HTML tags.

Example:


// allow everything but only from the same origin:
default-src 'self'; 
// allow JS but only from example.eu and from the same origin:
script-src 'self' https://example.eu/myapp; 
// allow XMLHttpRequests but only from example.eu and the same origin:
connect-src 'self' https://example.eu/myapp; 

You can find all the possible directives here and a tool that can generate your CSP header here.

The amazing thing about CSP is the Report-URI attribute, which will report the deviations from the policy to the specified URL:

Content-Security-Policy: default-src 'self'; 
report-uri http://reportcollector.example.com/collector.cgi 

One of the services collecting such reports is report-uri.com.

Subresource_Integrity (SRI)

SRI is a very simple and effective concept: the modern browsers load a given asset only if its hash matches the one defined in the ‘integrity’ attribute.

So instead of doing this:

<script src="//www.example.com/script.js" type="text/javascript"></script>;

it’s recommended to do this:

<script src="//www.example.com/script.js" type="text/javascript"
integrity="sha256-Abhisa/nS9WMne/YX+dqiFINl+JiE15MCWvASJvVtIk="
crossorigin="anonymous"></script>;

or even better, link each version of the remote asset with its own URL and hash:

<script src="//www.example.com/1.0.1/script.js" type="text/javascript"
integrity="sha256-Cng8gUe98XCqh5hc8nAM3y5I1iQHBjzOl8X3/iAd4jE=" 
crossorigin="anonymous"></script>

Cross-Origin Resource Sharing (CORS)

Problem:
– a script on client.com wants to access some data from server.com (ex. XMLHttpRequest)
– by default, the same-origin browser policy blocks this request

Solution:
– but by adding some special response headers, server.com can allow the script client.com to access the data.

The modern browsers have implemented a mechanism allowing scripts (like XMLHTTPRequest) to make cross-domain requests. This is Cross-Origin Resource Sharing and it uses a relatively less used HTTP request method (OPTIONS) plus several response headers (Access-Control-Request-Method, Access-Control-Request-Headers, etc)

Resources from Mozilla Development Network (MDN):

Glossary: CSP, SRI, CORS

Technical details: CSP, SRI, CORS

Context

Over the weekend, hackers injected thousands of websites—including UK and US government sites—with code that hijacked visitors’ computers to mine cryptocurrency.

The attack, noticed on Sunday by security researcher Scott Helme, was pulled off by compromising a single plugin that was used by all of the affected sites: Browsealoud, a reputable suite of accessibility and translation tools. According to Helme, the plugin was edited by attackers to embed a script that uses a site visitor’s computer to do the complex math that generates new digital coins (in this case, Monero). This process, known as “mining,” can slow down the victim’s computer.

The attack loaded malicious Javascript onto visitors’ computers. The hackers behind the attack chose to mine cryptocurrency, but they had the power to do almost whatever they wanted.
Cryptocurrency Mining Hack That Compromised Thousands of Sites ‘Could Have Been a Catastrophe’

Scott Helme: Protect your site from Cryptojacking with CSP + SRI
Troy Hunt: Trust in Third Party Libraries

FaceID: convenience and security

Written on 18 November 2017, 11:53pm

Tagged with: , , ,

Convenience

In one of the most watched reviews of the iPhone X, Marques Brownlee was showing in a side-by-side comparison that the new FaceID is still slower than the TouchID, but it will eventually get better with software improvements. I think that in the most cases, FaceID is faster: by tapping the screen or pressing the power button to unlock your iPhone, you’re actually creating an extra step when you don’t need one. If you simply pick up the phone, then swiping up will already unlock it. Definitely faster than TouchID.
But what’s even more important, FaceID represents an important milestone in the history of biometric authentication: it’s for the first time when this process is done seamlessly, without even thinking about it. Even Brownlee admits that “facial recognition on a phone is closer to secure, seamless authentication than a separate fingerprint reader will ever be“.
After using FaceID to unlock my phone for more than two weeks I can feel that it works so well that it becomes easy to forget that the authentication actually happens. The closest to this feeling is the Apple Watch authentication model: once you put it on your hand and unlock it, it’s easy to forget that you’re authenticated (by keeping it tied to your hand) and you can receive notifications on it. The fact that the FaceID authentication is now tied to something that you’re doing with the phone anyway – that is, looking at it – makes the experience feel close to magic.

This experience can be technically described as ‘continuous authentication’: you no longer have to make a conscious gesture in order to authenticate (ex. type a PIN or put your finger on the TouchID); by simply looking at the phone you are already authenticated. Some examples:
– expand notifications and show the the control center on the lock screen
– apps using FaceID for authentication, like LastPass: after opening them, you’re already authenticated (without the need to type a password or put your finger).
– Safari browser auto-filling the passwords

Face ID is the most compelling advancement in security I have seen in a very long time. It’s game-changing not merely due to the raw technology, but also because of Apple’s design and implementation. […] The real Face ID revolution: since you’re almost always looking at your iPhone while you’re using it, Face ID enables what I call “continuous authentication.”
Rich Mogull: Face ID’s Innovation: Continuous Authentication

Security

I described above the convenience of using FaceID and how it slowly moves us to a new era where we no longer realize we’re using biometric authentication. But how secure is it?
Before we dive into the main security concerns, it’s worth noting that before TouchID (that is a mere 4 years ago), most of us did not use a passcode on our smartphones. “Before Touch ID, about half of our users had a passcode set. Now, 9 out of 10 do.” (WWDC June 2016). With the introduction of TouchID and now FaceID, the number of people enjoying the security benefits of using a passcode is much higher.

Here are the main concerns related to FaceID:

– accidental in-app buy or download; accidental use of Apple Pay: not possible, you have to double tap the power button to enable the FaceID in order to download an app or to make a purchase
– false positive rate (security concern) / false negative rate (convenience concern): according to Apple, both fare better than TouchID
– somebody clones your face: still possible, and a valid concern if you have a high profile. But FaceID is more secure than TouchID: fabricating a 3D mask is arguably more complicated than a 3D finger.
– law enforcement forces you to unlock your iPhone using your face: the security level here is the same as for Touch ID. If you are concerned about this aspect, then simply don’t use FaceID/TouchID and rely on a strong passcode instead. If you are a just a little bit concerned, then know that holding the power and one of the volume buttons together (‘squeeze’ your iPhone) will immediately require the passcode to unlock
– somebody unlocks your phone while you are asleep: you can enable ‘require attention’. But if you are concerned about this, you have bigger issues that the security on your smartphone 🙂
More about these concerns here: Face ID, Touch ID, No ID, PINs and Pragmatic Security

The only valid concern for me is the following: a thief steals your iPhone, makes you look at it to unlock, then runs away with the unlocked phone.
In this scenario, FaceID is actually worse than TouchID – because it requires no physical contact between you and the thief. The only solution for this is to ‘Find your iphone’ and remotely wipe it, but this can take time during which valuable data can be extracted from your stolen phone. A better solution would be to immediately lock the iPhone from your Apple Watch.

Conclusions

There is always a trade-off between security and convenience. Sometimes compromises need to be made: security requires pragmatism. But FaceID just proved how it can address the most security concerns while providing a seamless user experience. With time, software and hardware updates, it will get even better, and we will see FaceID on other computing devices like tablets or laptops.
And from there it’s easy to imagine a keyless future. How long until you unlock your car by looking at it? Or you unlock your house by simply approaching the door and disarm your house alarm system by stepping into the hallway?
FaceID is not only an important milestone for biometric authentication, but it has the potential to change the way we interact with technology forever.