深圳建立网站,丽水网站seo,重庆网票app下载,大连平台网站建设目录#xff1a;
目录#xff1a;
一、概念
二、举例
三、 实操了解
总结
四、抛出原题#xff0c;历年原题复现
第一题#xff1a;
五、分析与原理 第二题#xff1a;
八、分析与原理
九、具体操作#xff0c;payload与结果
结果#xff1a; 一、概念 Java…目录
目录
一、概念
二、举例
三、 实操了解
总结
四、抛出原题历年原题复现
第一题
五、分析与原理 第二题
八、分析与原理
九、具体操作payload与结果
结果 一、概念 JavaScript 规定所有对象都有自己的原型对象prototype。一方面任何一个对象都可以充当其他对象的原型另一方面由于原型对象也是对象所以它也有自己的原型。因此就会形成一个“原型链”prototype chain对象到原型再到原型的原型……
cat.color---Animal.prototype---aaa.prototype---xxx.---object.protoype---null
如果一层层地上溯所有对象的原型最终都可以上溯到Object.prototype即Object构造函数的prototype属性。也就是说所有对象都继承了Object.prototype的属性。这就是所有对象都有valueOf和toString方法的原因因为这是从Object.prototype继承的。Object.prototype的原型是null。null没有任何属性和方法也没有自己的原型。因此原型链的尽头就是null。
二、举例 三、 实操了解
在我们了解到了具体的“子类继承父类”的关键点后我们进行实操看一道题
function P() {}
var p new P();console.info(p.constructor P)console.info(p.constructor P.prototype.constructor)console.info(p.hasOwnProperty(constructor))
思路三小问的具体思路 console.info(p.constructor P);: 这行代码比较了对象 p 的构造函数是否等于构造函数 P。由于 p 是通过构造函数 P 创建的所以 p.constructor 应该指向 P因此这里的比较结果为 true。 console.info(p.constructor P.prototype.constructor);: 这行代码比较了对象 p 的构造函数是否等于构造函数 P.prototype.constructor。在这里P.prototype.constructor 默认指向 P因为 P.prototype 是从构造函数 P 继承而来的。因此这里的比较结果也为 true。 console.info(p.hasOwnProperty(constructor));: 这行代码检查对象 p 是否直接拥有自己的属性 constructor。然而constructor 实际上是从 P.prototype 继承而来的因为 p 是通过 new P() 创建的它的原型是 P.prototype。因此这里的比较结果为 false。 总结代码展示了对象 p 与构造函数 P 及其原型之间的关系。对象 p 是通过构造函数 P 创建的它的原型指向了 P.prototype。这些比较和检查操作说明了原型链在 JavaScript 中的工作方式。
总结
从以上的简单抛出和讲解我们不难看出原型链污染玩的就是两个重要的概念1.原型继承2.属性查找机制让我们维持着这两个理念看看题型在题型中理解原型链污染 原型继承 JavaScript中的对象可以通过原型继承从其他对象继承属性和方法。每个对象都有一个指向其原型的链接通过这个链接可以访问原型对象的属性和方法。 属性查找机制 当访问一个对象的属性或方法时JavaScript引擎会首先在对象本身查找如果找不到它会沿着原型链向上查找直到找到属性或方法或者到达原型链的末端。
四、抛出原题历年原题复现
第一题
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();
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 进行赋值所以理论上这个值时不存在的但是下面有一句赋值语句 结果 第二题
use strict;const express require(express);
const bodyParser require(body-parser)
const cookieParser require(cookie-parser);
const path require(path);const isObject obj obj obj.constructor obj.constructor Object;function merge(a, b) {for (var attr in b) {if (isObject(a[attr]) isObject(b[attr])) {merge(a[attr], b[attr]);} else {a[attr] b[attr];}}return a
}function clone(a) {return merge({}, a);
}// Constants
const PORT 8080;
const HOST 0.0.0.0;
const admin {};// App
const app express();
app.use(bodyParser.json())
app.use(cookieParser());app.use(/, express.static(path.join(__dirname, views)));
app.post(/signup, (req, res) {var body JSON.parse(JSON.stringify(req.body)); {__proto__: {admin:1}}var copybody clone(body)if (copybody.name) {res.cookie(name, copybody.name).json({done: cookie set});} else {res.json({error: cookie not set})}
});
app.get(/getFlag, (req, res) {var аdmin JSON.parse(JSON.stringify(req.cookies))if (admin.аdmin 1) {res.send(hackim19{});} else {res.send(You are not authorized);}
});
app.listen(PORT, HOST);
console.log(Running on http://${HOST}:${PORT});
八、分析与原理
分析小例题obj[a][b] value。如果攻击者可以控制a和value,则可以将a的值设置为__proto__并且将使用值value为应用程序的所有现有对象定义属性b
分析整个代码首先定义一个函数merge,关于合并两个对象的设计是非常不安全的。由于执行merge()的库的最新版本已经打了补丁这道题目使用了旧方法合并对象从而易受到攻击。 在上面的代码中我们可以快速注意到的一点是将2 个“admins”定义为const admin和var admin。理想情况下js中不允许将const变量再次定义为var所以在题目中有一个需要我们搞懂的点便是其中一个是正常的a而另一个是其他的a(同形异义字)。
原理对象递归合并、按路径定义属性、对象克隆
九、具体操作payload与结果
从源代码入手 Merge()函数是以一种可能发生原型污染的方式编写的。这是问题分析的关键。 易受攻击的函数是在通过clone(body)访问/signup时被调用的因此我们可以在注册时发送JSON有效负载这样就可以添加admin属性并立即调用/getFlag来获取Flag。 如前所述我们可以使用__proto__(points to constructor.prototype)来创建值为1的admin属性。 执行相同操作的最简单的payload
{__proto__: {admin: 1}}
结果