By whitelisting specific sources of content and by disabling the use of inline JavaScript, CSP can nearly eliminate the class of attacks known as cross-site scripting (XSS) attacks. So how common is its usage amongst the Internet's most popular websites? Let's take a look:
Result
Count
Percentage
CSP implemented without using 'unsafe-inline' or 'unsafe-eval'
45
.0047%
CSP implemented the same as above, but with default-src 'none'
8
.0008%
CSP header allows style-src 'unsafe-inline'
61
.0064%
CSP header allows script-src 'unsafe-eval'
68
.0071%
CSP header uses http: source on an https site
15
.0016%
CSP header invalid
27
.0028%
CSP header allows script-src 'unsafe-inline'
3392
.3540%
No CSP header
954791
99.62%
Total number of successfully completed scans
958407
Yes, that's correct: only about .37% of the top million sites use CSP at all, and of that tiny percentage, only 3.3% (.012% overall) have strong CSP policies that block the use of inline JavaScript. For a specification that has had wide browser support for over two years, that's almost embarrassingly low. I'm not sure if it's because the CSP specification is too complicated to understand or too complicated to implement, but web security professionals are failing here.
Of that meager .37%, what CSP directives are seeing use?
Directive
Count
Percentage
script-src
2500
69.66%
style-src
2016
56.17%
default-src
1913
53.30%
img-src
1555
43.33%
frame-src
1344
37.45%
font-src
1317
36.70%
connect-src
1203
33.52%
report-uri
1037
28.89%
object-src
980
27.31%
frame-ancestors
916
25.52%
media-src
912
25.41%
child-src
126
3.51%
form-action
70
1.95%
reflected-xss
39
1.09%
referrer
33
0.92%
base-uri
22
0.61%
sandbox
15
0.42%
plugin-types
4
0.11%
manifest-src
1
0.03%
block-all-mixed-content
0
0.00%
upgrade-insecure-requests
0
0.00%
It's interesting to note how common frame-src, referrer, and reflected-xss are, considering they have been deprecated since CSP1. I myself struggled with removing frame-src, simply because child-src is not yet supported everywhere.
Although the HTTP Observatory doesn't currently try to catch errors in CSP policies, they are quite common. In my investigations, I discovered that over 3% of CSP policies contained errors. Here are some of the more common errors I discovered:
I have no idea how the browsers interpret these errors, but it's almost certainly not what the site operator intended. Whoops! The upcoming version of the HTTP Observatory should report on these types of errors so that site operators can be certain that browsers aren't misinterpreting their intentions.
One of unsung heroes out there when it comes to advancing the overall security of the Internet is Scott Helme. In addition to report-uri.io (a CSP/HPKP violation reporting service), he runs securityheaders.io, a site that helps show you if you're utilizing the many available options when it comes to securing your web site.
It was the latter that inspired the creation of the Mozilla HTTP Observatory, a public service that goes a bit deeper and tells you not just whether you are using these headers, but if you're using them correctly and securely.
Having recently gotten the HTTP Observatory to a usable state, I decided to scan the Alexa Top 1M sites to see how well that engineers and developers on the biggest sites on the Internet are doing. As Scott found out, the results are pretty dismal. I'll be doing more detailed posts on each of these sections as I find the time, but even the basic statistics are depressing.
When I decided to rewrite my personal website, I thought to myself, “Hey, April! You're a security professional who focuses on web security. It would be practically embarrassing if you didn't implement Content Security Policy to demonstrate your competence.”
I simply followed my usual procedure: start with default-src 'none', and keep adding sources until all the console errors go away. That lead me to the following CSP header:
I walked away blissfully, knowing that some ne'er-do-well whould be thwarted in their attempts to find any XSS vulnerabilities in my pointless, mostly static personal blog. That is, until I clicked Contact and gasped in horror…
At first, I thought that I had made a mistake with my SVG files, but opening them up directly rendered them in full color. And there was nothing at all in the console log about them, either. After a pile of fruitless Google searches, a tip by my good friend Chuck Harmston led me to consider my CSP policy.
See, SVG files are not just a pile of binary data like most raster images. They're vectors, created mathematically, and defined via XML. The GitHub icon's content looks like this:
Firefox was considering style="fill:rgb(246,188,246)" to be an 'unsafe-inline' style, and therefore blocking it. But it considers it to be an 'unsafe-inline' style inside the SVG's context, hence the lack of console errors. I didn't want to add 'unsafe-inline' to 'style-src' for my entire site, so I ended up creating a completely different CSP directive just for SVGs:
The nice thing about this policy is that it has the added bonus of disabling all script execution inside SVG files, itself a huge security risk. In any case, I thought this madness was crazy enough (and undocumented enough) that I opened up a bug for it.
When my most recent phone got abandoned by T-Mobile, — leaving me with a pile of security vulnerabilities — I finally give up. Despite really enjoying the Android user interface (particularly with Nova Launcher), I just couldn't stomach buying Yet Another Android Phone™ just to have the latest version. So now I'm the proud owner of an iPhone SE, which is delightfully hand-sized.
On Android, the process of installing a ringtone goes roughly as follows:
Plug in your phone
Drag your audio files (midi, mp3, m4a, etc.) to the proper folder
I had assumed it couldn't possibly be that much more difficult on the iPhone. But getting custom ringtones onto an iPhone is a giant pain in the ass. Guides on the internet go roughly as follows:
Open the Kafkaesque nightmare that is iTunes
Drag your audio file into iTunes
Go into Get Info for the song
Set a start and stop time with a max duration of 30 seconds, because of pointless technical limitations
Right-click on the song and create an AAC version
Show in Finder, finding the file on your local filesystem
Drag that file to your desktop
Rename its extension from .m4a to .mpr
Delete the AAC file from iTunes
Drag the .m4r file into the Tones section of iTunes
Plug in your phone, go to the Tones section, and select the new ringtone
Sync it
Of course, this doesn't get you an ascending ringtone, one of my favorite Android features. So I turned to ffmpeg, one of most byzantine command line applications ever created.
$ ffmpeg-i"Android Ringtone.mp3"-ss00:00-t00:30-af"afade=t=in:ss=0:d=10"-fmp4"iOS Ringtone.m4r"ffmpeg version 3.0 Copyright (c) 2000-2016 the FFmpeg developers built with Apple LLVM version 7.0.2 (clang-700.1.81) configuration: --prefix=/usr/local/Cellar/ffmpeg/3.0 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-opencl --enable-libx264 --enable-libmp3lame --enable-libxvid --enable-vda libavutil 55. 17.103 / 55. 17.103 libavcodec 57. 24.102 / 57. 24.102 libavformat 57. 25.100 / 57. 25.100 libavdevice 57. 0.101 / 57. 0.101 libavfilter 6. 31.100 / 6. 31.100 libavresample 3. 0. 0 / 3. 0. 0 libswscale 4. 0.100 / 4. 0.100 libswresample 2. 0.101 / 2. 0.101 libpostproc 54. 0.100 / 54. 0.100[mp3 @ 0x7fee0b80a800] Skipping 0 bytes of junk at 10809.Input #0, mp3, from 'Android Ringtone.mp3': Metadata: title : Oh Yeah That Song artist : That One Gal or Guy album : That Album You Keep Buying Again and Again TT1 : Some Dumb Organizational Tag track : Insert Integer Here genre : Probably my Favorite Genre date : Another Integer that Represents a Good Year in Music Duration: 00:02:01.55, start: 0.011995, bitrate: 167 kb/s Stream #0:0: Audio: mp3, 44100 Hz, stereo, s16p, 166 kb/sOutput #0, mp4, to 'iOS Ringtone.m4r': Metadata: title : Oh Yeah That Song artist : That One Gal or Guy album : That Album You Keep Buying Again and Again TT1 : Some Dumb Organizational Tag track : Insert Integer Here genre : Probably my Favorite Genre date : Another Integer that Represents a Good Year in Music encoder : Lavf57.25.100 Stream #0:0: Audio: aac (LC) ([64][0][0][0] / 0x0040), 44100 Hz, stereo, fltp, 160 kb/s Metadata: encoder : Lavc57.24.102 aacStream mapping: Stream #0:0 -> #0:0 (mp3 (native) -> aac (native))Press [q] to stop, [?] for helpsize= 620kB time=00:00:30.00 bitrate= 169.2kbits/s speed= 21xvideo:0kB audio:614kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.976624%[aac @ 0x7fee0b819400] Qavg: 1646.151
Here are what the switches mean:
-i "Android Ringtone.mp3" the input file
-ss 00:00 the start time (at the beginning, in this case)
-t 00:30 how long of a segment (30 seconds)
-af "afade=t=in:ss=0:d=10" starting at 0 seconds in, fade in over a duration of 10 seconds
-f mp4 treat it as mp4 audio, since ffmpeg doesn't recognize the .m4r extension
"iOS Ringtone.m4r" the output file
Just drag that file into iTunes, sync, and it's done: