Steps to Reproduce
The merge()
function in AngularJS, which is used to combine multiple objects into a single, new object, is vulnerable to this High-level vulnerability. The command can be used to add or modify the properties of Object.prototype
.
Javascript allows all properties of an object to be merged, including the magic properties __proto__
, constructor and prototype. Specifically with this exploit, it’s possible to merge a __proto__
property thereby altering the Object.prototype
and exposing a vulnerability. Because Object.prototype
properties are inherited by all Javascript objects, the attacker has wide latitude to impact code execution. It might lead to remote code execution or even a denial of service via triggering Javascript exceptions.
Read more on GitHub.
Addressing the Issue
The exploit exists in all versions of AngularJS prior to version 1.7.9. For those unable to upgrade, clients of HeroDevs Never-Ending Support for AngularJS have access to a fixed version of AngularJS that is compatible with Angular 1.5. The targets vulnerable to attack are:
- the web server
- the application server
- the web browser.
Learning and Prevention
There are several ways to help prevent this sort of attack:
- Freeze the prototype. Using
Object.freeze(Object.prototype)
is a drastic action that severely curtails flexibility in the program—but it will prevent this type of attack. - Require schema validation. JSON input can be scanned (“sanitized”) so that it does not include the
__proto__
attribute. - Avoid using unsafe recursive merge functions. Though valid, this recommendation has limited applicability because the problem isn’t in the nature of recursive merge functions—the problem lies in the
merge()
functions, whether recursive or not, blindly copying the dangerous attribute toObject.prototype
. - Use objects without prototypes. Consider
Object.create(null)
or proxy objects or a custom class to create an object that does not use prototypes. An object that doesn’t inherit fromObject.prototype
isn’t susceptible to pollution. - Use arrays and map(). Instead of using objects and
merge()
, use arrays and themap()
function to avoid the possibility of prototype pollution completely.
Conclusion
The fix described in this vulnerability is present in 1.7.9 and is also immediately available to HeroDevs AngularJS Never-Ending Support clients who are still on Angular 1.5. If you would like support to avoid potentially costly attacks, contact HeroDevs today.
Resources
NIST BDSA-2019-10768 entry