Some scary implementation bugs in ExternalInterface that easily lead to XSS (
These bugs have been around for a long time, but were finally partially patched in the 14.0.0.25 update. Beware that the patch will not help unless you recompile your Flash files with a new target version.
If you don't want to see the actual exploit strings, you can hide them.
If some JavaScript calls a function exported by the Flash file, and that function throws an exception, the exception is re-thrown in JavaScript land by evaluating throw "<string>"
with no escaping whatsoever.
Exceptions can also be thrown in the other direction. When running JavaScript code from Flash, the results are sent back to the plugin as XML; in particular the exception is serialized as <exception>...</exception>
, again with no escaping. This would be vulnerable even if you've removed all "
and \
characters.
This is the well-known backslash bug: parameter are JSON-encoded with a broken JSON-encoder that doesn't escape backslashes. Exploiting this is complicated by the fact that the string is evaluated like this:
Same encoder as the last one, just in a place that is less likely to be caught by a reviewer that knows about ExternalInterface.call()...
The backslash bug has been known for years, so many code bases have workarounds like
return s.replace(/\\/g, '\\\\');
Now this code depends on the fact that the plugin doesn't escape, so if Adobe suddenly starts escaping things properly, this code would now double-escape — which might even introduce new vulnerabilities if there is nested data. As lcamtuf mentions, Adobe decided against patching this bug in 2011.
By 2014, they've apparently changed their mind, and with 14.0.0.25, a version-gated fix was released: Flash files compiled with a version number ≥ 25 get the correct marshalling behavior.
User with old Flash player | User with new Flash player | |
Old file | XSS | XSS |
New file | XSS | OK |
Old file with workaround | OK | OK |
New file with workaround | OK | Garbled |
This is... hardly optimal. If you need to be compatible with both, the easiest way out is probably to assume the channel explodes on \
and apply some kind of transfer encoding that never uses it.