Revision: 5697
Author: [email protected]
Date: Mon Sep 22 22:10:56 2014 UTC
Log: Protect proxy JSONP responses against "Rosetta Flash"
vulnerability.
https://codereview.appspot.com/118640043
The so-called "Rosetta Flash" vulnerability is that allowing arbitrary
yet identifier-like text at the beginning of a JSONP response is
sufficient for it to be interpreted as a Flash file executing in that
origin. See for more information:
http://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
JSONP responses from the proxy servlet now:
* are prefixed with "/**/", which still allows them to execute as JSONP
but removes requester control over the first bytes of the response.
* have the response header Content-Disposition: attachment.
Another recommended mitigation, "X-Content-Type-Options: nosniff", was
already present.
Bug: <https://code.google.com/p/google-caja/issues/detail?id=1923>
[email protected]
https://code.google.com/p/google-caja/source/detail?r=5697
Modified:
/trunk/src/com/google/caja/service/ProxyServlet.java
/trunk/tests/com/google/caja/plugin/test-fetch-proxy.js
/trunk/tests/com/google/caja/service/ServiceTestCase.java
=======================================
--- /trunk/src/com/google/caja/service/ProxyServlet.java Thu Dec 19
19:46:16 2013 UTC
+++ /trunk/src/com/google/caja/service/ProxyServlet.java Mon Sep 22
22:10:56 2014 UTC
@@ -203,6 +203,7 @@
resp.setContentLength(content.length);
resp.setHeader(UMP.a, UMP.b);
resp.setHeader("X-Content-Type-Options", "nosniff");
+ resp.setHeader("Content-Disposition", "attachment; filename=f.txt");
resp.getOutputStream().write(content);
resp.getOutputStream().close();
@@ -430,7 +431,7 @@
output.append(
(jsonpCallback != null)
- ? jsonpCallback + "(" + rendered + ");"
+ ? "/**/" + jsonpCallback + "(" + rendered + ");"
: rendered);
output.flush();
}
=======================================
--- /trunk/tests/com/google/caja/plugin/test-fetch-proxy.js Thu Dec 19
19:46:16 2013 UTC
+++ /trunk/tests/com/google/caja/plugin/test-fetch-proxy.js Mon Sep 22
22:10:56 2014 UTC
@@ -33,6 +33,12 @@
console.log('Response: ' + request.responseText);
assertEquals('response Content-Type', expectedMimeType,
request.getResponseHeader('Content-Type').split(';')[0]);
+
+ // Rosetta Flash vuln mitigation expected
+ assertEquals('nosniff', request.getResponseHeader(
+ 'X-Content-Type-Options'));
+ assertEquals('attachment; filename=f.txt',
request.getResponseHeader(
+ 'Content-Disposition'));
callback(request.responseText);
} else {
fail('Unexpected response: ' + request.statusText);
@@ -42,7 +48,7 @@
request.send();
}
- var JSONP_RE = /^([a-zA-Z_]+)\((\{.*\})\);$/;
+ var JSONP_RE = /^\/\*\*\/([a-zA-Z_]+)\((\{.*\})\);$/;
function docURL(name) {
return location.protocol + '//' + location.host +
=======================================
--- /trunk/tests/com/google/caja/service/ServiceTestCase.java Thu Dec 19
19:46:16 2013 UTC
+++ /trunk/tests/com/google/caja/service/ServiceTestCase.java Mon Sep 22
22:10:56 2014 UTC
@@ -151,7 +151,7 @@
String emitted,
String jsonProperty,
String... expectedSubstrings) throws Exception {
- Pattern p = Pattern.compile("(?s)^[a-zA-Z_]+\\((\\{.*\\})\\);$");
+ Pattern p =
Pattern.compile("(?s)^/\\*\\*/[a-zA-Z_]+\\((\\{.*\\})\\);$");
Matcher m = p.matcher(emitted);
assertTrue(m.matches());
assertSubstringsInJson(m.group(1), jsonProperty, expectedSubstrings);
@@ -160,7 +160,8 @@
protected static void assertCallbackInJsonp(
String emitted,
String jsonpCallback) throws Exception {
- Pattern p = Pattern.compile("(?s)^" + jsonpCallback
+ "\\((\\{.*\\})\\);$");
+ Pattern p = Pattern.compile("(?s)^/\\*\\*/" + jsonpCallback +
+ "\\((\\{.*\\})\\);$");
Matcher m = p.matcher(emitted);
assertTrue(m.matches());
}
--
---
You received this message because you are subscribed to the Google Groups "Google Caja Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.