The modern web model permits remote domain
<script> inclusion with no restrictions. If the remote data, which does not have to be script, has an effect on the evil domain doing the inclusion, you have a cross-domain data leak.

The idea was to use JavaScript error messages combined with 302 redirect. In general, modern browsers replace JavaScript error messages with a generic message like “Script error” to prevent leaking of error messages to remote domain. In case of same domain, detailed JavaScript error messages can be read.

I’ve found the same issue in IE 11 but with a peculiar prerequisite;
– The loading page (more precisely- Tab) must have its Developers Tools open (or previously opened)

Yes, it’s weird but it doesn’t work if Developers Tools is not open or previously opened. Few other prerequisites which are essential for script inclusion attacks are;
– The values must form valid JavaScript variable names
– The included data, as a whole, must form valid JavaScript code

The best error message to target is “blah is not defined”, referring to a textual name that is not currently bound to a variable. You can cross-domain steal data that is a single word in this manner. If the cross-domain data is CSV, e.g. “a, b, c”, you can steal the text of all three words by iteratively sourcing the script, noting the undefined variable name, defining it and repeating.

So, basically, we can steal contents of any CSV file as long as it meets above prerequisites. In fact, we can steal any type of data as long as it meets above prerequisites, not only CSVs. It is also possible to use different charsets to steal data as long as the included page doesn’t specify its own charset. This is shown in Gareth‘s post which I’ve added in REFERENCES.

To remediate the issue, developers or website owners can do one or any combination of;
– Switch to POST method
– Use secret tokens as in CSRF Protection
– Make URL unpredictable
– Strict referer checking

If the data is supposed to be retrieved via ajax requests for further processing, one can also;
– Use Parser-Breaking syntax like
for(;;)
– Use custom HTTP header

Also, specifying correct
Content-Type header and
X-Content-Type-Options: nosniff would suffice to remediate the issue for this particular case. However, I wouldn’t consider it a strong fix as there are browsers which still don’t support
X-Content-Type-Options.

Thanks
Special thanks to @albinowax for his feedback and thorough proof-reading.