网站建设公司南宁wordpress更换IP
news/
2025/9/23 22:58:02/
文章来源:
网站建设公司南宁,wordpress更换IP,网络架构模拟器,filp pdf wordpress原型链污染攻击
prototype 和 _proto_是什么
JavaScript中的类的简历 在JavaScript中#xff0c;我们如果要定义一个类#xff0c;需要以定义“构造函数”的方式来定义#xff1a;
function Foo() {this.bar 1
}new Foo() 解析#xff1a; Foo函数的内容#xff0c;就…原型链污染攻击
prototype 和 _proto_是什么
JavaScript中的类的简历 在JavaScript中我们如果要定义一个类需要以定义“构造函数”的方式来定义
function Foo() {this.bar 1
}new Foo() 解析 Foo函数的内容就是Foo类的构造函数而this.bar就表示Foo类中的一个属性 为了简化编写JavaScript代码ECMAScript 6后增加了class语法但class其实只是一个语法糖 JavaScript中的类中方法的建立 一个类必然有一些方法类似属性this.bar我们也可以将方法定义在构造函数内部
function Foo() {this.bar 1this.show function() {console.log(this.bar)}
}(new Foo()).show() 解析 这样写有一个问题就是每当我们新建一个Foo对象时this.show function()... 就会执行一次这个show方法实际上是绑定在对象上的而不是绑定在“类”中 JavaScript中原型prototype的引用
希望在创建类时只创建一次show方法需要使用原型prototype
function Foo() {this.bar 1
}Foo.prototype.show function show() {console.log(this.bar)
}let foo new Foo()
foo.show() 解析 我们可以认为原型prototype是类Foo的一个属性而所有用Foo类实例化的对象都将有这个属性中的所有内容包括变量和方法。foo对象天生具有foo.show()方法 此时Foo.prototype来访问Foo类的原型但是Foo实例化出来的对象是不能够通过prototype访问原型 JavaScript中__proto__的引用 一个Foo类实例化出来的foo对象可以通过foo.__proto__属性来访问Foo中类的原型
foo.__proto__ Foo.prototype prototype 和 _proto_的定义 prototype --- 是一个类的属性所有类对象在实例化的时候将会拥有prototype中的属性和方法 一个对象的__proto__属性指向这个对象所在类的prototype属性
JavaScript中原型链继承 所有类对象在实例化的时候将会拥有中的prototype属性和方法这个特性被用来实现JavaScript中的继承机制
function Father() {this.first_name Donaldthis.last_name Trump
}function Son() {this.first_name Melania
}Son.prototype new Father()let son new Son()
console.log(Name: ${son.first_name} ${son.last_name}) 解析 Son类继承了Father类的last_name属性最后输出的是Name: Melania Trump JavaScript引擎会进行如下操作: 在对象son中寻找last_name 如果找不到则在son.__proto__中寻找last_name 如果仍然找不到则继续在son.__proto__.__proto__中寻找last_name 依次寻找直到找到null结束。比如Object.prototype的__proto__就是null JavaScript的这个查找的机制被运用在面向对象的继承中被称作prototype继承链 注意 每个构造函数(constructor)都有一个原型对象(prototype) 对象的__proto__属性指向类的原型对象prototype JavaScript使用prototype链实现继承机制 原型链污染是什么
引入 在前面说过 foo.__proto__指向的是Foo类的prototype。那么如果我们修改了foo.__proto__中的值是不是就可以修改Foo类呢
// foo是一个简单的JavaScript对象
let foo {bar: 1}// foo.bar 此时为1
console.log(foo.bar)// 修改foo的原型即Object
foo.__proto__.bar 2// 由于查找顺序的原因foo.bar仍然是1
console.log(foo.bar)// 此时再用Object创建一个空的zoo对象
let zoo {}// 查看zoo.bar
console.log(zoo.bar) 解析 因为前面我们修改了foo的原型foo.__proto__.bar 2而foo是一个Object类的实例所以实际上是修改了Object这个类给这个类增加了一个属性bar值为2 后来我们又用Object类创建了一个zoo对象let zoo {}zoo对象自然也有一个bar属性了 原型链污染定义 在一个应用中如果攻击者控制并修改了一个对象的原型那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染
哪些情况原型链会被污染 我们思考一下哪些情况下我们可以设置__proto__的值呢其实找找能够控制数组对象的“键名”的操作即可 对象merge 结合 拼接 对象clone其实内核就是将待操作的对象merge到一个空对象中 复制
使用merge测试
function merge(target, source) {for (let key in source) {if (key in source key in target) {merge(target[key], source[key])} else {target[key] source[key]}}
} 在合并的过程中存在赋值的操作target[key] source[key]那么这个key如果是__proto__是不是就可以原型链污染呢 使用如下代码进行测试
let o1 {}
let o2 {a: 1, __proto__: {b: 2}}
merge(o1, o2)
console.log(o1.a, o1.b)o3 {}console.log(o3.b) 结果是合并虽然成功了但原型链没有被污染 解析 这是因为我们用JavaScript创建o2的过程let o2 {a: 1, __proto__: {b: 2}}中__proto__已经代表o2的原型了此时遍历o2的所有键名你拿到的是[a, b]__proto__并不是一个key自然也不会修改Object的原型 修改代码
let o1 {}
let o2 JSON.parse({a: 1, __proto__: {b: 2}})
merge(o1, o2)
console.log(o1.a, o1.b)o3 {}console.log(o3.b) 解析 这是因为JSON解析的情况下__proto__会被认为是一个真正的“键名”而不代表“原型”所以在遍历o2的时候会存在这个键 案例
案例一
const express require(express)
var hbs require(hbs);
var bodyParser require(body-parser);
const md5 require(md5);
var morganBody require(morgan-body);
const app express();
//目前user并没有admintoken
var user []; //empty for nowvar matrix [];
for (var i 0; i 3; i){matrix[i] [null , null, null];
}function draw(mat) {var count 0;for (var i 0; i 3; i){for (var j 0; j 3; j){if (matrix[i][j] ! null){count 1;}}}return count 9;
}app.use(express.static(public));
app.use(bodyParser.json());
app.set(view engine, html);
morganBody(app);
app.engine(html, require(hbs).__express);app.get(/, (req, res) {for (var i 0; i 3; i){matrix[i] [null , null, null];}res.render(index);
})app.get(/admin, (req, res) { /*this is under development I guess ??*/console.log(user.admintoken);if(user.admintoken req.query.querytoken md5(user.admintoken) req.query.querytoken){res.send(Hey admin your flag is bflag{prototype_pollution_is_very_dangerous}/b);} else {res.status(403).send(Forbidden);}
}
)app.post(/api, (req, res) {var client req.body;var winner null;if (client.row 3 || client.col 3){client.row % 3;client.col % 3;}matrix[client.row][client.col] client.data;for(var i 0; i 3; i){if (matrix[i][0] matrix[i][1] matrix[i][1] matrix[i][2] ){if (matrix[i][0] X) {winner 1;}else if(matrix[i][0] O) {winner 2;}}if (matrix[0][i] matrix[1][i] matrix[1][i] matrix[2][i]){if (matrix[0][i] X) {winner 1;}else if(matrix[0][i] O) {winner 2;}}}if (matrix[0][0] matrix[1][1] matrix[1][1] matrix[2][2] matrix[0][0] X){winner 1;}if (matrix[0][0] matrix[1][1] matrix[1][1] matrix[2][2] matrix[0][0] O){winner 2;} if (matrix[0][2] matrix[1][1] matrix[1][1] matrix[2][0] matrix[2][0] X){winner 1;}if (matrix[0][2] matrix[1][1] matrix[1][1] matrix[2][0] matrix[2][0] O){winner 2;}if (draw(matrix) winner null){res.send(JSON.stringify({winner: 0}))}else if (winner ! null) {res.send(JSON.stringify({winner: winner}))}else {res.send(JSON.stringify({winner: -1}))}})
app.listen(3000, () {console.log(app listening on port 3000!)
}) 解析 获取flag的条件是 传入的querytoken要和user数组本身的admintoken的MD5值相等且二者都要存在 由代码可知全文没有对user.admintokn 进行赋值所以理论上这个值是不存在的但因为存在一下赋值语句 matrix[client.row][client.col] client.data; 其中data,row,col都是我们post传入的值都是可控的。所以可以构造原型链污染
本地测试
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/914161.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!