什么是原型污染?如何防止原型污染?

在 JavaScript 中,原型污染(Prototype Pollution) 是一种通过修改对象的原型链,向所有继承该原型的对象注入或覆盖属性的安全漏洞。这种操作可能导致代码行为异常、数据篡改甚至远程代码执行(RCE)等风险。


原型污染的原理

JavaScript 的原型链继承机制允许对象通过 __proto__(或 Object.getPrototypeOf())访问原型对象。如果攻击者能修改原型对象的属性(如 Object.prototype),所有继承该原型的对象都会继承这些修改。

示例:原型污染的产生
javascript 复制代码
// 直接修改 Object.prototype
Object.prototype.isAdmin = true;

const obj = {};
console.log(obj.isAdmin); // true(原型链被污染)

如何防止原型污染?

1. 避免直接操作 __proto__ 或原型
  • 关键点:禁止外部数据直接修改对象的原型链。

  • 代码示例

    javascript 复制代码
    // 安全做法:避免动态设置 __proto__
    function safeMerge(target, source) {
      for (const key in source) {
        if (key === '__proto__' || key === 'constructor') {
          continue; // 忽略敏感属性
        }
        target[key] = source[key];
      }
    }
2. 使用 Object.create(null) 创建无原型对象
  • 关键点 :创建的对象不继承 Object.prototype,天然免疫原型污染。

  • 代码示例

    javascript 复制代码
    const safeObj = Object.create(null); // 无原型链
    safeObj.name = "Safe";
    console.log(safeObj.toString); // undefined(无法访问 Object.prototype 的方法)
3. 冻结原型对象
  • 关键点 :使用 Object.freeze() 禁止修改原型。

  • 代码示例

    javascript 复制代码
    // 冻结 Object.prototype
    Object.freeze(Object.prototype);
    
    // 尝试污染原型会失败(严格模式下报错)
    Object.prototype.isAdmin = true; 
    console.log(Object.prototype.isAdmin); // undefined
4. 安全处理对象合并操作
  • 关键点 :在合并对象属性时,过滤敏感键(如 __proto__constructorprototype)。

  • 代码示例

    javascript 复制代码
    function safeAssign(target, source) {
      Object.keys(source).forEach(key => {
        if (key in Object.prototype) return; // 忽略原型上的键
        target[key] = source[key];
      });
    }
5. 使用 Map 替代普通对象
  • 关键点Map 的键可以是任意类型,且不会继承原型链属性。

  • 代码示例

    javascript 复制代码
    const map = new Map();
    map.set("isAdmin", true);
    console.log(map.get("isAdmin")); // true
    console.log(map.isAdmin); // undefined(无法通过原型链污染)
6. 使用安全的第三方库
  • 关键点 :避免手写不安全的对象操作,选择经过安全审计的库(如 Lodash 的 _.merge 默认过滤原型键)。

  • 代码示例

    javascript 复制代码
    const _ = require('lodash');
    const safeObj = _.merge({}, maliciousPayload); // 自动忽略 __proto__
7. 启用严格模式(Strict Mode)
  • 关键点:严格模式下,修改只读属性(如冻结后的原型)会抛出错误。

  • 代码示例

    javascript 复制代码
    'use strict';
    Object.prototype.isAdmin = true; // 报错:Cannot add property isAdmin

原型污染的常见攻击场景

  1. 解析不安全的 JSON 数据

    javascript 复制代码
    const data = JSON.parse('{ "__proto__": { "isAdmin": true } }'); // 可能污染原型链
  2. 用户输入合并到对象
    如 HTTP 请求参数、表单数据等未经验证直接合并到对象中。

  3. 第三方库漏洞
    未正确处理用户输入的库可能成为污染入口。


总结

防御方法 适用场景 优点
过滤敏感键 对象合并、深拷贝 直接阻断污染路径
使用 Object.create(null) 高频操作或敏感数据存储 彻底免疫原型链污染
冻结原型 全局防护 防止所有原型修改
使用 Map 键值对存储 无原型链,天然安全

核心原则

  • 永远不要信任外部输入,始终验证和清理数据。
  • 最小化原型操作,优先使用无原型对象或安全数据结构。
相关推荐
xlp666hub4 分钟前
【Linux驱动实战】:字符设备驱动之内核态与用户态数据交互
linux·面试
AlienZHOU8 分钟前
从零开始,跟着写一个产品级 Coding Agent
前端
RichardZhiLi11 分钟前
大前端全栈实践课程:章节二(前端工程化建设)
前端
毕设源码-赖学姐14 分钟前
【开题答辩全过程】以 基于VUE的环保网站设计为例,包含答辩的问题和答案
前端·javascript·vue.js
ZTrainWilliams16 分钟前
swagger-mcp-toolkit 让 AI编辑器 更快“读懂并调用”你的接口
前端·后端·mcp
伊步沁心29 分钟前
深入 useEffect:为什么 cleanup 总比 setup 先跑?顺手手写节流防抖 Hook
前端
小J听不清34 分钟前
CSS 字体样式全解析:字体类型 / 大小 / 粗细 / 样式
前端·javascript·css·html·css3
500佰35 分钟前
pencil on claude 让设计师和程序员少吵架的一种可能
前端
Jane-lan38 分钟前
NVM安装以及可能的坑
前端·node·nvm
幽络源小助理42 分钟前
Typecho大前端新闻博客主题源码下载:资讯门户风格模板安装教程 | 幽络源
前端