蓝桥杯-网络安全比赛(5)基础学习-JavaScript原型链的prototype、constructor、object.create()、__proto__

复制代码
JavaScript的prototype、constructor、Object.create()和__proto__通常不直接作为解题的关键,但它们对于理解和分析Web应用的安全性至关重要。
网络安全比赛通常涉及Web应用的漏洞挖掘和攻击,这要求参赛者具备深厚的Web开发知识,包括JavaScript的原型链和继承机制。
  1. 原型链污染 :参赛者可能需要了解prototype__proto__以识别和利用原型链污染漏洞。
    攻击者可能通过修改对象的原型来影响所有继承自该原型的对象,从而执行恶意代码或绕过安全限制。
  2. 对象操作和属性访问 :在网络安全比赛中,参赛者经常需要分析JavaScript对象的结构和属性。
    了解prototypeconstructor可以帮助他们更好地理解对象的来源和行为,从而找到潜在的漏洞。
  3. 代码审计 :参赛者在审计Web应用的源代码时,可能会遇到使用Object.create()创建对象的代码。
    了解这种方法可以帮助他们理解对象的创建过程和属性继承,从而发现潜在的安全问题。
  4. 绕过安全限制 :在某些情况下,攻击者可能会尝试利用JavaScript的原型链和继承机制 来绕过浏览器的安全限制或Web应用的安全机制。
    了解这些概念可以帮助参赛者识别和防御这类攻击。

原型链

复制代码
JavaScript的原型链机制是JavaScript对象继承属性或方法的主要方式。
每个JavaScript对象(除了null)都有一个指向它的原型(prototype)对象的内部链接。
这个原型对象自身也可以有原型,这样一层一层地链接下去,就构成了原型链。

prototype

每个函数都有一个 prototype 属性,它是一个对象,用于存储可以由特定类型的所有实例共享的属性和方法。

当尝试访问一个对象的属性时,如果该对象自身没有这个属性,那么 JavaScript 引擎会在该对象的 __proto__(即其原型)上查找这个属性,这个过程会一直持续到找到属性或者到达原型链的末端(通常是 null)。

javascript 复制代码
function Person(name) {  
  this.name = name;  
}  
  
Person.prototype.greet = function() {  
  console.log(`Hello, ${this.name}!`);  
};  
  
const alice = new Person('Alice');  
const bob = new Person('Bob');  
  
Person.prototype.age = 30; // 所有实例的 age 属性都是 30  
  
console.log(alice.age); // 输出: 30  
console.log(bob.age); // 输出: 30
alice.greet(); // 输出: Hello, Alice!

谨慎扩展内置对象的原型:修改内置对象的原型(如 Object、Array

等)可能会导致不可预见的副作用,因为其他代码可能也依赖于这些内置对象的行为。

constructor

每个对象都有一个 constructor 属性,它指向创建该对象实例的构造函数。

通常,当我们修改 prototype 时,需要确保 constructor 指向正确的构造函数,以避免混淆。

案例:

javascript 复制代码
function Person(name) {  
  this.name = name;  
}  
  
Person.prototype.greet = function() {  
  console.log(`Hello, ${this.name}!`);  
};  
// 忘记设置 constructor,可能导致问题  
const alice = new Person('Alice');  
console.log(alice.constructor === Person); // 输出: false,应该是 true  
  
// 确保 constructor 指向正确的构造函数  
Person.prototype.constructor = Person;  
console.log(alice.constructor === Person); // 输出: true

Object.create()

Object.create() 方法创建一个新对象,使用现有的对象来提供新创建的对象的 __proto__

案例:

javascript 复制代码
const personProto = {  
  greet: function() {  
    console.log(`Hello, ${this.name}!`);  
  }  
};  

const bob = Object.create(null); // 没有原型链  
bob.greet(); // 报错:bob.greet is not a function
  
const alice = Object.create(personProto);  
alice.name = 'Alice';  
alice.greet(); // 输出: Hello, Alice!

proto

__proto__ 是一个内部属性(在大多数现代浏览器中是可访问的),它指向对象的原型。(通常不会直接操作 __proto__,而是使用 Object.create() 或构造函数来设置对象的原型。)

案例:

javascript 复制代码
function Person(name) {  
  this.name = name;  
}  
  
const alice = new Person('Alice');  
  
console.log(alice.__proto__ === Person.prototype); // 输出: true

不要直接修改 prototype __proto__:尽量通过添加属性或方法到原型对象来扩展对象的功能,而不是直接修改原型对象本身。

更好的做法是使用 Object.definePropertyObject.assign 等方法来扩展对象,而不是直接修改 __proto__

例题

题目1

复制代码
创建一个 Animal 构造函数,它有一个 speak 方法。
然后创建一个 Dog 构造函数,它继承自 Animal 构造函数,并有一个 bark 方法。
最后,创建一个 Dog 的实例并调用它的 speak 和 bark 方法。

解答:

javascript 复制代码
function Animal() {}  
  
Animal.prototype.speak = function() {  
  console.log('The animal speaks.');  
};  
  
function Dog() {}  
  
// Dog 继承自 Animal  
Dog.prototype = Object.create(Animal.prototype);  
Dog.prototype.constructor = Dog;  
  
Dog.prototype.bark = function() {  
  console.log('The dog barks.');  
};  
  
const myDog = new Dog();  
myDog.speak(); // 输出: The animal speaks.  
myDog.bark(); // 输出: The dog barks.

题目2

复制代码
创建一个Vehicle基类,它有一个move方法。
接着创建两个派生类Car和Bicycle,它们继承自Vehicle类,
并且各自添加了自己的特性方法(Car有honk方法,Bicycle有pedal方法)。
最后,创建这两个派生类的实例,并调用它们的方法。

要求:

  1. 使用原型链来实现继承。
  2. 确保每个对象的constructor属性指向正确的构造函数。
  3. 使用Object.create()来设置原型。

解答:

javascript 复制代码
// 1. 创建 Vehicle 基类  
function Vehicle() {  
  // 构造函数内容(如果有的话)  
}  
  
Vehicle.prototype.move = function() {  
  console.log('The vehicle is moving.');  
};  
  
// 2. 创建 Car 类,继承自 Vehicle  
function Car() {}  
  
// 使用 Object.create() 设置原型  
Car.prototype = Object.create(Vehicle.prototype);  
Car.prototype.constructor = Car; // 确保 constructor 指向正确的构造函数  
  
Car.prototype.honk = function() {  
  console.log('The car honks.');  
};  
  
// 3. 创建 Bicycle 类,继承自 Vehicle  
function Bicycle() { }  
  
// 使用 Object.create() 设置原型  
Bicycle.prototype = Object.create(Vehicle.prototype);  
Bicycle.prototype.constructor = Bicycle; // 确保 constructor 指向正确的构造函数  
  
Bicycle.prototype.pedal = function() {  
  console.log('The bicycle is being pedaled.');  
};  
  
// 4. 创建实例并调用方法  
const myCar = new Car();  
myCar.move(); // 输出: The vehicle is moving.  
myCar.honk(); // 输出: The car honks.  
  
const myBicycle = new Bicycle();  
myBicycle.move(); // 输出: The vehicle is moving.  
myBicycle.pedal(); // 输出: The bicycle is being pedaled.  
  
// 5. 验证原型链和 constructor  
console.log(myCar.__proto__ === Car.prototype); // 输出: true  
console.log(myCar.__proto__.__proto__ === Vehicle.prototype); // 输出: true  
console.log(myCar.constructor === Car); // 输出: true  
  
console.log(myBicycle.__proto__ === Bicycle.prototype); // 输出: true  
console.log(myBicycle.__proto__.__proto__ === Vehicle.prototype); // 输出: true  
console.log(myBicycle.constructor === Bicycle); // 输出: true

总结

通过今天的学习,你应该能够更好地理解JavaScript的原型链和继承机制,并能够在实际开发中灵活运用这些概念。

同时,你也应该意识到这些概念在Web应用安全性分析中的重要性,这对于参与网络安全比赛或从事Web安全相关工作的人来说是非常有价值的。

系列文章

蓝桥杯-网络安全比赛(4)基础学习-JavaScript同步与异步、宏任务与微任务
蓝桥杯-网络安全比赛(3)基础学习- JavaScript的闭包与this
蓝桥杯-网络安全比赛(2)基础学习-正则表达式匹配
蓝桥杯-网络安全比赛(1)基础学习-使用PHP、PYTHON、JAVA

相关推荐
网安INF1 小时前
ElGamal加密算法:离散对数难题的安全基石
java·网络安全·密码学
眼镜哥(with glasses)3 小时前
蓝桥杯 国赛2024python(b组)题目(1-3)
数据结构·算法·蓝桥杯
kite01215 小时前
浏览器工作原理06 [#]渲染流程(下):HTML、CSS和JavaScript是如何变成页面的
javascript·css·html
крон5 小时前
【Auto.js例程】华为备忘录导出到其他手机
开发语言·javascript·智能手机
DevSecOps选型指南7 小时前
2025软件供应链安全最佳实践︱证券DevSecOps下供应链与开源治理实践
网络·安全·web安全·开源·代码审计·软件供应链安全
coding随想7 小时前
JavaScript ES6 解构:优雅提取数据的艺术
前端·javascript·es6
年老体衰按不动键盘7 小时前
快速部署和启动Vue3项目
java·javascript·vue
恰薯条的屑海鸥7 小时前
零基础在实践中学习网络安全-皮卡丘靶场(第十六期-SSRF模块)
数据库·学习·安全·web安全·渗透测试·网络安全学习
灵感__idea7 小时前
JavaScript高级程序设计(第5版):无处不在的集合
前端·javascript·程序员
喜欢吃燃面8 小时前
C++刷题:日期模拟(1)
c++·学习·算法