Before talking about this vulnerability, let’s understand Javascript. Unlike other languages, JS did not have classes before Es6. It was more of a prototype language. There is a famous saying in JS - "Everything is an object".
What is a prototype language
1. Only objects, no classes; objects inherit objects, rather than classes inheriting classes.
2. "Prototype object" is the core concept. The prototype object is the template for the new object, which shares its properties with the new object. An object can not only enjoy the properties defined when it is created and run time, but also can enjoy the properties of the prototype object.
3. Each object has its own prototype object, and all objects form a tree-like hierarchical system. The top-level object of the root node is a language-native object. Only it has no prototype object. All other objects inherit its properties directly or indirectly.
About Function.prototype and Object.__proto__
1. The object has the __proto__ attribute, and the function has the prototype attribute;
2. The object is composed of Function generation;
3. When generating an object, the __proto__ attribute of the object points to the prototype attribute of the function.
When the pointing of the __proto__ attribute is not manually modified, the above three items are the JavaScript default prototype chain pointing logic. If you want to understand this more vividly, you can look at the structure in the picture below:
What is JavaScript prototype chain pollution
The prototype chain pollution comes from a CVE (https://github.com/jquery/jquery/pull/4333). This CVE is a vulnerability fixed in jquery, but this If the vulnerability is broadly promoted, the affected scope should be all applications that use ecmascript, regardless of front-end or back-end. Regarding this vulnerability, the $.extend(true...)
method of jQuery is fixed. In jQuery, this method is used to merge the contents of one or more objects into the target object. So you never know if someone will write some code similar to the following
When we can control the parameters of $.extend, we can override the __proto__ or prototype method of the object to control The top method of the entire prototype chain. Overriding this method will overwrite the methods of sub-objects or functions, thus polluting the original method intent.
You can see a lot of object operation libraries in npmjs official search, such as "xtend
", "deepmerge
", "webpack-merge"
", "merge2
", "lodash.merge
". Suppose some applications use these methods but do not do any processing on the parameters.
Vulnerability Scope Impact
The author who proposed this Javascript prototype chain pollution attack wrote a pdf. In this pdf, the author not only analyzed the causes of the vulnerability, but also To analyze the scope of the vulnerability, he searched for some components on github. These components are all operable objects. They are generally operated by object merging and are relatively low-level. Therefore, there will be a large number of applications based on these components. For example, "hoek", "lodash", "defaults-deep", etc. have fixed the possibility of contamination of the prototype chain. Of course, there are some components that he has not counted, such as "xtend" and the like. The number of weekly downloads alone is "12,097,425".
The author searched for some applications based on xtend on npm and found a component like language-exec. This component is based on xtend, but this component seems to be in disrepair and not used by many people. After reading the source code, there is a sentence like
, and you can see that similar writing methods have problems ( Mainly because I couldn't find any specific affected applications based on xtend).
So based on this, don’t you have the idea of brushing CVE? That's right...as long as you dare to take the time to crawl all dependencies, you can have a chance to obtain javascript pollution attack CVE.
Case 1 Remote Command Execution
The author searched for an application called ghost cms on github. Of course, this vulnerability has been fixed. When the hacker sends the following request, Implement control of any method or any property of an object. Of course, it is also rce
In JavaScript where everything is an object, all objects can call the toString and valueOf methods. When you rewrite these two methods through __proto__, it is easy to use express and other web DOS is generated in the framework, causing the service to fail to run normally. Writing something like the following can easily cause a denial of service.
Case 2 DOS
In JavaScript where everything is an object, all objects can call the toString and valueOf methods. When you pass __proto_ _When rewriting these two methods, it is easy to generate DOS in web frameworks such as express, causing the service to fail to run normally. Writing like the following can easily cause a denial of service
Case 3 Arbitrary file reading
If you can pollute the prototype chain If you rewrite some "private attributes" (Javascript does not have private attributes), you may be able to rewrite the attribute values used to define rendering template files in the WEB, and it is possible to read arbitrary files, such as the following picture:
How to defend
Here we learn about this type of attack, how to write code more securely, and better defend against this type of attack. Class vulnerability. The author of the vulnerability discovery gave 2 solutions. Let’s take a look at how I defended myself first.
If I were to solve this problem, I would choose to iterate the attributes of the object until I find the two attribute names __proto__ and prototype, and kill them if they appear. However, this method still has flaws. One is that it is based on a blacklist, and there are too many attributes that need to be included. For example, in Dos, methods such as tostring and valueof must be included, and if private attributes are overridden, how to ensure that parameters and interfaces are covered? a lot of.
The original author put forward 3 points:
1. Use Object.freeze to freeze objects. Almost all JavaScript objects are instances of Object. So just freeze Object.prototype. Specifically, you can learn about the new Object.freeze method in es5. Using this method, hackers will not be able to add or rewrite methods on the corresponding prototype chain. However, this may lead to some hidden bugs. , and may not know what went wrong.
2. Use map data structure to replace the built-in object structure. Es6 has a map structure. The difference between this map and Object is that the key of map can be any object type, whether it is an array or an object.
3. Use Object.create(null) (strongly recommended). Using this method can better defend against prototype chain pollution attacks, because Object.create(null) makes the new objects created without any The prototype chain is null and does not have any inheritance relationship. When you accept a client's parameters and plan to merge, you can use this method to merge. Such objects are relatively safe. The client cannot pass the prototype chain. Pollution attack (because there is no prototype chain leading to other objects). We can simply look at it through an experiment.
Recommended related articles and tutorials: web server security
The above is the detailed content of JavaScript prototype chain pollution attack. For more information, please follow other related articles on the PHP Chinese website!