prototype: Prevent a potential security issue for cross-site ajax requests.
This commit is contained in:
parent
dcada47c6d
commit
02cc9992e9
|
@ -1,5 +1,7 @@
|
|||
*SVN*
|
||||
|
||||
* Prevent a potential security issue for cross-site ajax requests. [Alexey Feldgendler, sam, Tobie Langel]
|
||||
|
||||
* Test for attribute existence before applying more complex CSS3 selectors. Closes #10870. [arty, Tobie Langel]
|
||||
|
||||
* Fix "function $A" declaration inside of a conditional (confuses IE). Closes #10882. [Jacco, Andrew Dupont]
|
||||
|
|
17
src/ajax.js
17
src/ajax.js
|
@ -189,7 +189,7 @@ Ajax.Request = Class.create(Ajax.Base, {
|
|||
|
||||
var contentType = response.getHeader('Content-type');
|
||||
if (this.options.evalJS == 'force'
|
||||
|| (this.options.evalJS && contentType
|
||||
|| (this.options.evalJS && this.isSameOrigin() && contentType
|
||||
&& contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
|
||||
this.evalResponse();
|
||||
}
|
||||
|
@ -207,6 +207,15 @@ Ajax.Request = Class.create(Ajax.Base, {
|
|||
}
|
||||
},
|
||||
|
||||
isSameOrigin: function() {
|
||||
var m = this.url.match(/^\s*https?:\/\/[^/]*/);
|
||||
return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
|
||||
protocol: location.protocol,
|
||||
domain: document.domain,
|
||||
port: location.port ? ':' + location.port : ''
|
||||
}));
|
||||
},
|
||||
|
||||
getHeader: function(name) {
|
||||
try {
|
||||
return this.transport.getResponseHeader(name) || null;
|
||||
|
@ -282,7 +291,8 @@ Ajax.Response = Class.create({
|
|||
if (!json) return null;
|
||||
json = decodeURIComponent(escape(json));
|
||||
try {
|
||||
return json.evalJSON(this.request.options.sanitizeJSON);
|
||||
return json.evalJSON(this.request.options.sanitizeJSON ||
|
||||
!this.request.isSameOrigin());
|
||||
} catch (e) {
|
||||
this.request.dispatchException(e);
|
||||
}
|
||||
|
@ -295,7 +305,8 @@ Ajax.Response = Class.create({
|
|||
this.responseText.blank())
|
||||
return null;
|
||||
try {
|
||||
return this.responseText.evalJSON(options.sanitizeJSON);
|
||||
return this.responseText.evalJSON(options.sanitizeJSON ||
|
||||
!this.request.isSameOrigin());
|
||||
} catch (e) {
|
||||
this.request.dispatchException(e);
|
||||
}
|
||||
|
|
|
@ -410,6 +410,45 @@
|
|||
} else {
|
||||
info(message);
|
||||
}
|
||||
}},
|
||||
|
||||
testIsSameOriginMethod: function() {with(this) {
|
||||
var isSameOrigin = Ajax.Request.prototype.isSameOrigin;
|
||||
assert(isSameOrigin.call({ url: '/foo/bar.html' }), '/foo/bar.html');
|
||||
assert(isSameOrigin.call({ url: window.location.toString() }), window.location);
|
||||
assert(!isSameOrigin.call({ url: 'http://example.com' }), 'http://example.com');
|
||||
|
||||
if (isRunningFromRake) {
|
||||
Ajax.Request.prototype.isSameOrigin = function() {
|
||||
return false
|
||||
};
|
||||
|
||||
$("content").update('same origin policy');
|
||||
new Ajax.Request("/response", extendDefault({
|
||||
parameters: Fixtures.js,
|
||||
onComplete: function(transport) {
|
||||
assertEqual("same origin policy", $("content").innerHTML);
|
||||
}
|
||||
}));
|
||||
|
||||
new Ajax.Request("/response", extendDefault({
|
||||
parameters: Fixtures.invalidJson,
|
||||
onException: function(request, error) {
|
||||
assert(error.message.include('Badly formed JSON string'));
|
||||
}
|
||||
}));
|
||||
|
||||
new Ajax.Request("/response", extendDefault({
|
||||
parameters: { 'X-JSON': '{});window.attacked = true;({}' },
|
||||
onException: function(request, error) {
|
||||
assert(error.message.include('Badly formed JSON string'));
|
||||
}
|
||||
}));
|
||||
|
||||
Ajax.Request.prototype.isSameOrigin = isSameOrigin;
|
||||
} else {
|
||||
info(message);
|
||||
}
|
||||
}}
|
||||
});
|
||||
// ]]>
|
||||
|
|
Loading…
Reference in New Issue