【攻防世界】 | Web | wife_wife详细题解WP

进入题目环境,首先进入sign up创建一个admin用户,下方有勾选 is admin,打上勾

随便填写Invite Code,进行抓包

如果是新手看不懂是什么意思无所谓,这是一道JavaScript原型练污染

测试了一会儿,发现加上__proto__ 这个继承对象的属性payload后,不需要管Invite Code是什么,也能注册成功

admin/admin登录进去后就能够看到flag

CatCTF{test_flag_h0w_c@n_I_l1ve_w1th0ut_nilou}

一、下面是对__proto__的解释:

在 JavaScript 中,__proto__ 是一个对象属性,用于实现原型继承(Prototype Inheritance)。它指向该对象的原型对象(即创建该对象的构造函数的 prototype 属性),从而允许对象继承其他对象的属性和方法。以下是其核心作用和详细说明:

一、基本概念与作用

  1. 原型链机制

    • JavaScript 是基于原型的语言,对象通过 __proto__ 链接到其原型对象,形成原型链
    • 当访问一个对象的属性 / 方法时,JavaScript 首先在对象本身查找,若不存在则沿 __proto__ 向上查找,直到原型链末尾(Object.prototype)或找到为止。
  2. __proto__prototype 的区别

    • __proto__实例对象的属性,指向其原型对象(即构造函数的 prototype)。
    • prototype构造函数的属性,是一个普通对象,用于为实例提供共享属性和方法。

    javascript

    const obj = new Object();
    obj.__proto__ === Object.prototype; // true(实例的 __proto__ 指向构造函数的 prototype)

二、__proto__ 的具体用途

  1. 动态修改原型

    • 可通过 __proto__ 为现有对象动态添加或替换原型,改变继承关系。

    javascript

    const animal = { speak() { console.log("Animal sound"); } };
    const dog = {};
    dog.__proto__ = animal; // dog 继承 animal 的方法
    dog.speak(); // 输出: "Animal sound"
  2. 实现继承

    • 在 ES6 之前,常通过 __proto__ 手动实现继承(ES6 后推荐使用 classextends)。

    javascript

    function Animal() { this.type = "animal"; }
    Animal.prototype.speak = function() { console.log("Sound"); }; function Dog() { this.breed = "Labrador"; }
    Dog.prototype.__proto__ = Animal.prototype; // Dog 继承 Animal const dog = new Dog();
    dog.speak(); // 输出: "Sound"
  3. 检查原型链

    • 通过 __proto__ 可逐层访问对象的原型链,用于调试或验证继承关系。

    javascript

    const arr = [];
    arr.__proto__ === Array.prototype; // true
    arr.__proto__.__proto__ === Object.prototype; // true

三、注意事项与替代方案

  1. 性能与兼容性问题

    • 性能开销:动态修改 __proto__ 会影响对象属性查找速度,现代引擎对此有优化但仍需谨慎。
    • 兼容性__proto__ 是历史遗留特性(ES6 才标准化),部分旧环境(如 IE10 及以下)不支持。
  2. 推荐替代方案

    • Object.create()

      :创建新对象时直接指定原型。

      javascript

      const animal = { speak() { console.log("Sound"); } };
      const dog = Object.create(animal); // 等价于 dog.__proto__ = animal
    • ES6 class/extends

      :更简洁的继承语法(本质仍基于原型)。

      javascript

      class Animal { speak() { console.log("Sound"); } }
      class Dog extends Animal {}
    • Object.setPrototypeOf()

      :显式修改原型(不推荐频繁使用)。

      javascript

      Object.setPrototypeOf(dog, animal); // 等价于 dog.__proto__ = animal

四、与现代 JavaScript 的关系

  • __proto__ 的设计初衷:提供一种直观但非标准的方式访问原型(早期 JavaScript 未暴露原型机制)。
  • 现代实践:优先使用 Object.create()classextends 等语法,避免直接操作 __proto__ 以提升性能和代码可维护性。

总结

__proto__ 是 JavaScript 原型链的核心机制,允许对象继承其他对象的属性和方法。尽管它提供了动态修改继承关系的灵活性,但由于性能和兼容性问题,现代开发中更推荐使用标准化的替代方案。理解 __proto__ 有助于深入掌握 JavaScript 的继承原理,但实际编码中应谨慎使用。

二、下面是关于js原型链污染的原理和防御:

一、原型链污染的核心原理

1. JavaScript 原型继承机制

JavaScript 是基于原型的语言,每个对象都有一个内部属性[[Prototype]](可通过__proto__访问),指向其原型对象。当访问一个对象的属性时,JavaScript 会:

  • 先在对象本身查找
  • 如果找不到,沿原型链向上查找
  • 直到Object.prototype为止

例如:

const person = { name: "Alice" };
console.log(person.toString()); // 继承自Object.prototype

这里toString()方法并非person对象自身的属性,而是通过原型链从Object.prototype继承而来。

2. 动态原型修改

JavaScript 允许动态修改对象的原型,包括内置对象的原型。原型链污染攻击就是利用这一点,通过修改Object.prototype或其他原型对象,向其中注入恶意属性或方法。

关键方法包括:

  • 直接修改__proto__属性
  • 使用Object.setPrototypeOf()
  • 利用漏洞函数(如merge()JSON.parse()的自定义解析器)

二、攻击实例解析

1. 经典案例:利用不安全的对象合并函数

许多 JavaScript 库提供对象合并功能(如lodash.mergeObject.assign),但如果实现不当,可能导致原型污染。

漏洞代码示例:

function merge(target, source) {
for (let key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] === 'object' && source[key] !== null) {
if (typeof target[key] !== 'object') {
target[key] = {};
}
merge(target[key], source[key]); // 递归合并
} else {
target[key] = source[key];
}
}
}
return target;
} // 攻击者可控的输入
const payload = JSON.parse('{"__proto__":{"isAdmin":true}}');
const obj = {}; merge(obj, payload); // 合并操作
console.log(obj.isAdmin); // 输出: undefined
console.log({}.isAdmin); // 输出: true!污染了Object.prototype

攻击路径:

  1. 攻击者构造特殊 JSON 数据,包含__proto__
  2. 应用使用有漏洞的合并函数处理该数据
  3. 合并过程中,Object.prototype被修改,添加了isAdmin属性
  4. 所有对象(包括新创建的对象)都会继承这个属性

2. 实际应用场景:绕过权限检查

在 Web 应用中,权限检查可能依赖于用户对象的isAdmin属性:

function checkAdmin(request) {
return request.user.isAdmin === true;
} // 正常情况下
const normalUser = { username: "user" };
checkAdmin({ user: normalUser }); // false // 原型污染后
checkAdmin({ user: {} }); // true!空对象也被认为是管理员

三、防御策略详解

1. 禁止直接修改原型

安全合并函数改进:

function safeMerge(target, source) {
for (let key in source) {
if (source.hasOwnProperty(key)) {
// 跳过原型属性
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
continue;
}
if (typeof source[key] === 'object' && source[key] !== null) {
if (typeof target[key] !== 'object') {
target[key] = {};
}
safeMerge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
return target;
}

2. 使用不可变对象

通过Object.freeze()防止对象被修改:

// 冻结Object.prototype
Object.freeze(Object.prototype); // 尝试污染
const payload = JSON.parse('{"__proto__":{"isAdmin":true}}');
merge({}, payload); console.log({}.isAdmin); // 输出: undefined(污染失败)

3. 输入验证与过滤

  • 对用户输入进行严格验证,拒绝包含__proto__constructor等敏感键的数据
  • 使用安全的 JSON 解析库(如secure-json-parse
const secureParse = require('secure-json-parse');
const input = '{"__proto__":{"evil":"payload"}}'; try {
const data = secureParse(input); // 自动防御原型链污染
} catch (e) {
console.error('恶意输入:', e.message);
}

4. 框架和库的安全配置

  • 使用经过安全审计的库
  • 避免使用body-parser等易受攻击的中间件(改用express.json()并配置strict: true
  • 定期更新依赖,修复已知漏洞

四、高级渗透测试技巧

1. 自动化检测工具

  • 使用 AST(抽象语法树)分析工具检测潜在的原型链污染点
  • 结合 fuzz 测试,自动生成恶意输入
  • 推荐工具:PrototypePollutedRetire.js

2. 实战中的漏洞挖掘

在代码审计中重点关注

  • 递归合并函数
  • 动态属性赋值
  • 自定义 JSON 解析器
  • 使用eval()Function()动态执行代码的位置

检测代码示例:

// 查找潜在的原型链污染点
const acorn = require('acorn');
const fs = require('fs'); const code = fs.readFileSync('vulnerable.js', 'utf8');
const ast = acorn.parse(code, { ecmaVersion: 2020, sourceType: 'module' }); // 查找所有for...in循环
function findForInLoops(node) {
if (node.type === 'ForInStatement') {
console.log('潜在风险: 未过滤的for...in循环', node.loc);
}
for (let key in node) {
if (typeof node[key] === 'object' && node[key] !== null) {
findForInLoops(node[key]);
}
}
} findForInLoops(ast);

五、总结

JavaScript 原型链污染是一种隐蔽但危害极大的漏洞,利用了 JavaScript 动态原型系统的特性。作为安全工程师,我们需要:

  • 深入理解 JavaScript 原型机制
  • 在开发阶段实施严格的防御措施
  • 在渗透测试中重点关注潜在风险点
  • 持续监控和更新依赖库

【攻防世界】Web | wife_wife 详细题解WP的更多相关文章

  1. 攻防世界Web区部分题解

    攻防世界Web区部分题解   前言:PHP序列化就是把代码中所有的 对象 , 类 , 数组 , 变量 , 匿名函数等全部转换为一个字符串 , 提供给用户传输和存储 . 而反序列化就是把字符串重新转换为 ...

  2. XCTF攻防世界Web之WriteUp

    XCTF攻防世界Web之WriteUp 0x00 准备 [内容] 在xctf官网注册账号,即可食用. [目录] 目录 0x01 view-source2 0x02 get post3 0x03 rob ...

  3. 攻防世界Web刷题记录(进阶区)

    攻防世界Web刷题记录(进阶区) 1.baby_web 发现去掉URLhttp://111.200.241.244:51461/1.php后面的1.php,还是会跳转到http://111.200.2 ...

  4. CTF--web 攻防世界web题 robots backup

    攻防世界web题 robots https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=0&id=506 ...

  5. CTF--web 攻防世界web题 get_post

    攻防世界web题 get_post https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=0&id=5 ...

  6. 攻防世界 web进阶练习 NewsCenter

    攻防世界 web进阶练习 NewsCenter   题目是NewsCenter,没有提示信息.打开题目,有一处搜索框,搜索新闻.考虑xss或sql注入,随便输入一个abc,没有任何搜索结果,页面也没有 ...

  7. 攻防世界web新手区

    攻防世界web新手区 第一题view_source 第二题get_post 第三题robots 第四题Backup 第五题cookie 第六题disabled_button 第七题simple_js ...

  8. XCTF攻防世界web进阶练习—mfw

    XCTF攻防世界web进阶练习-mfw题目为mfw,没有任何提示.直接打开题目,是一个网站 大概浏览一下其中的内容,看到其中url变化其实只是get的参数的变化查看它的源码,看到有一个?page=fl ...

  9. 攻防世界Web刷题记录(新手区)

    攻防世界Web刷题记录(新手区) 1.ViewSource 题如其名 Fn + F12 2.get post 3.robots robots.txt是搜索引擎中访问网站的时候要查看的第一个文件.当一个 ...

  10. 攻防世界 WEB 高手进阶区 csaw-ctf-2016-quals mfw Writeup

    攻防世界 WEB 高手进阶区 csaw-ctf-2016-quals mfw Writeup 题目介绍 题目考点 PHP代码审计 git源码泄露 Writeup 进入题目,点击一番,发现可能出现git ...

随机推荐

  1. 如果在安装32位Oracle客户端组件的情况下64位模式运行, 将出现此问题.

    场景重现 在一台Windows 7 32-bit电脑上 安装了Oracle 11gR2 32-bit的客户端 用 VS2010 写的一个基于数据库驱动的项目 操作Oracle数据库都挺正常的 后来.. ...

  2. Javascript 对象(object)合并 转

    转载了一篇介绍的比较直观的博文.

  3. 解密prompt系列52. 闲聊大模型还有什么值得探索的领域

    在DeepSeek-R1的开源狂欢之后,感觉不少朋友都陷入了技术舒适区,但其实当前的大模型技术只是跨进了应用阶段,可以探索的领域还有不少,所以这一章咱不聊论文了,偶尔不脚踏实地,单纯仰望天空,聊聊还有 ...

  4. Jmeter压测数据库总结

    1.添加MySQL驱动 在测试计划里面添加,操作如下: MySQL驱动自行下载 2.添加线程组 选中测试计划,右键添加->线程(用户)->线程组,页面如下: 3.添加JDBC连接配置 选中 ...

  5. rust程序静态编译的两种方法总结

    1. 概述 经过我的探索,总结了两种rust程序静态编译的方法,理论上两种方法都适用于windows.mac os和linux(mac os未验证),实测方法一性能比方法二好,现总结如下,希望能够帮到 ...

  6. RabbitMQ高级使用

    概述 在支付场景中,支付成功后利用RabbitMQ通知交易服务,更新业务订单状态为已支付.但是大家思考一下,如果这里MQ通知失败,支付服务中支付流水显示支付成功,而交易服务中的订单状态却显示未支付,数 ...

  7. Pycomcad快速绘制参数化多段线的一种方法

    任务: 绘制出不同长度的相同型式的多段线,如上图所示,仅仅是300mm和500mm的区别,3个弯折处都一样,都是圆弧段,对于常规二次开发思路,是通过数学计算,计算出圆弧的圆心的位置,用固定的半径,绘制 ...

  8. linux下使用动态壁纸

    让你的linux桌面动起来(幻梦动态壁纸) 我也是突发奇想,做了这么一个程序,目前在多个linux下可以运行,支持双屏 理论上说支持mpv >=29.0 qt>=5.8.0的系统版本 ub ...

  9. 第1讲、#PyTorch教学环境搭建与Tensor基础操作详解

    引言 PyTorch是当前深度学习领域最流行的框架之一,因其动态计算图和直观的API而备受开发者青睐.本文将从零开始介绍PyTorch的环境搭建与基础操作,适合各种平台的用户和深度学习初学者. 1. ...

  10. DrissionPage.errors.WrongURLError 无效的url,也许要加上"http://"?

    DrissionPage是个强大的工具,使用DrissionPage 读取本地html 报了这个错:"DrissionPage.errors.WrongURLError 无效的url,也许要 ...