What I did
So, building on my “Script: not a type-ical tag” article, I tested a few more ways to inject JavaScript into webpages. 1895 more, to be exact,
(and I’m not done yet).
How I did it
Firstly, I changed the way I’m injecting scripts to use a PHP file like Mathias Bynens is in his tests (i.e. page.php?type=blah/blah&do=something). Here’s the end result for that PHP file:
<?php
$ct = preg_replace('/[^a-z\/\-]/', '', $_GET['ct']);
header('Content-Type: ' . $ct);
if (empty($ct)) {
$ct = 'no type';
}
if (isset($_GET['dw'])) {
echo "document.writeln('Content-Type: $ct works!<br>');";
}
else if (isset($_GET['id'])) {
$id = preg_replace('/[^a-z_]/', '', $_GET['id']);
echo <<<EOT
try {
document.getElementById('{$id}').innerHTML
= 'Content-Type: {$ct} works!';
}
catch (e) {
alert("Couldn't find id of {$id}");
}
EOT;
}
else {
die("// Nothing to do");
}
So this allows me to inject the scripts like so:
<script src="js.php?ct=application/javascript&todo"></script>
And they will set the HTTP Content-Type headers for external <script>s and do some stuff.
I also added data URIs, dynamic script creation and dynamic script injection (subtly different).
Data URIs scripts look like this:
<script src="data:X/Y,document.write('oh%20hai!')%3B"></script>
The dynamic script creation I'm doing looks like this:
window.onload = function () {
var c = document.createElement('script');
c.innerHTML = '// do something in JS!';
document.body.appendChild(s);
And dynamic script injection looks like this:
var i = document.createElement('script');
i.src = 'js.php?do=something';
document.body.appendChild(i);
};
Results
NOTE: I will be switching this to use Browserscope sooner or later, but for now the results of my very manual testing can be seen below.
Conclusions / Findings
So, some interesting things I found out from this were:
- Though IE8 supports data URIs in other areas (supposedly), it will not execute a <script> with a data URI as the
srcattribute (verified by Microsoft here). This has been changed in IE9. Go nuts. - IE9 handles data URI encoding much more strictly than other browsers. Without properly encoding various parts of the inline data (i.e.
/->%2F,;->%3B) <scripts> will not execute nor give any particular reason why they didn't (as far as I could find). At first this lead me to believe that data URIs in <script>srcs weren't working in IE8 or IE9 at all! - IE9 accepts many different type attributes on <script> tags like other "good" browsers. This is a large jump above IEs 6-8,
- A browser made by 90,000 geeks over 30 years is now being rivaled by the browser I have in my pocket on my phone (OK, that's not fair - Apple and Google both made Webkit & Chrome).
As always, let me know if you find problems with my results or if you want to contribute some results yourself.