Use Object.prototype.propertyIsEnumerable to check for constructors
- context.propertyIsEnumerable can be replaced via __definedGetter__ - This is a fix specific to counter a known RCE exploit. Other fixes will follow. closes #1563
This commit is contained in:
@@ -14,12 +14,20 @@ JavaScriptCompiler.prototype = {
|
|||||||
// alternative compiled forms for name lookup and buffering semantics
|
// alternative compiled forms for name lookup and buffering semantics
|
||||||
nameLookup: function(parent, name/* , type*/) {
|
nameLookup: function(parent, name/* , type*/) {
|
||||||
if (name === 'constructor') {
|
if (name === 'constructor') {
|
||||||
return ['(', parent, '.propertyIsEnumerable(\'constructor\') ? ', parent, '.constructor : undefined', ')'];
|
return ['(', _isEnumerable(), '?', _actualLookup(), ' : undefined)'];
|
||||||
}
|
}
|
||||||
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
|
return _actualLookup();
|
||||||
return [parent, '.', name];
|
|
||||||
} else {
|
function _isEnumerable() {
|
||||||
return [parent, '[', JSON.stringify(name), ']'];
|
return `Object.prototype.propertyIsEnumerable.call(${parent},'constructor')`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _actualLookup() {
|
||||||
|
if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
|
||||||
|
return [parent, '.', name];
|
||||||
|
} else {
|
||||||
|
return [parent, '[', JSON.stringify(name), ']'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
depthedLookup: function(name) {
|
depthedLookup: function(name) {
|
||||||
@@ -339,9 +347,9 @@ JavaScriptCompiler.prototype = {
|
|||||||
params.splice(1, 0, current);
|
params.splice(1, 0, current);
|
||||||
|
|
||||||
this.pushSource([
|
this.pushSource([
|
||||||
'if (!', this.lastHelper, ') { ',
|
'if (!', this.lastHelper, ') { ',
|
||||||
current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params),
|
current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params),
|
||||||
'}']);
|
'}']);
|
||||||
},
|
},
|
||||||
|
|
||||||
// [appendContent]
|
// [appendContent]
|
||||||
@@ -686,16 +694,16 @@ JavaScriptCompiler.prototype = {
|
|||||||
if (!this.options.strict) {
|
if (!this.options.strict) {
|
||||||
lookup[0] = '(helper = ';
|
lookup[0] = '(helper = ';
|
||||||
lookup.push(
|
lookup.push(
|
||||||
' != null ? helper : ',
|
' != null ? helper : ',
|
||||||
this.aliasable('container.hooks.helperMissing')
|
this.aliasable('container.hooks.helperMissing')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.push([
|
this.push([
|
||||||
'(', lookup,
|
'(', lookup,
|
||||||
(helper.paramsInit ? ['),(', helper.paramsInit] : []), '),',
|
(helper.paramsInit ? ['),(', helper.paramsInit] : []), '),',
|
||||||
'(typeof helper === ', this.aliasable('"function"'), ' ? ',
|
'(typeof helper === ', this.aliasable('"function"'), ' ? ',
|
||||||
this.source.functionCall('helper', 'call', helper.callParams), ' : helper))'
|
this.source.functionCall('helper', 'call', helper.callParams), ' : helper))'
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -33,7 +33,7 @@ describe('security issues', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('GH-xxxx: Prevent explicit call of helperMissing-helpers', function() {
|
describe('GH-1558: Prevent explicit call of helperMissing-helpers', function() {
|
||||||
if (!Handlebars.compile) {
|
if (!Handlebars.compile) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -88,4 +88,14 @@ describe('security issues', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('GH-1563', function() {
|
||||||
|
it('should not allow to access constructor after overriding via __defineGetter__', function() {
|
||||||
|
shouldCompileTo('{{__defineGetter__ "undefined" valueOf }}' +
|
||||||
|
'{{#with __lookupGetter__ }}' +
|
||||||
|
'{{__defineGetter__ "propertyIsEnumerable" (this.bind (this.bind 1)) }}' +
|
||||||
|
'{{constructor.name}}' +
|
||||||
|
'{{/with}}', {}, '');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user