node.js原型链污染小结

之前已经写到一些原型链污染的原理和原型链原理

这里再补充一些

1.利用:如何判断是否存在原型链污染?

·字符串可以被解析为对象或方法。例如:Json.parse进行解析、shvl库使用点对属性操作。

·对象的键和值都可控。target[key]=value,其中value和key均可控制。

常见有用merge方法

这里就不再赘述了

实例1:在antCTF中,使用shvl库对键值进行操作

email: async function (req, res) {
    let contents = {};

    // 遍历请求参数中所有的 key
    // 将键和值赋值为 contents(shvl 库的 set 函数)
    Object.keys(req.body).forEach((key) => {
      shvl.set(contents, key, req.body[key]);
    });

    contents.from = '"admin" <admin@8-bit.pub>';

    try {
      await send(contents);
      return res.json({
        message: "Success."
      });
    } catch (err) {
      return res.status(500).json({
        message: err.message
      });
    }
  }

 2.常见的原型链污染方法有哪些?

function.__proto__polluted

function.prototype.polluted

obj.__proto__.polluted.例如:shvl只禁用了__proto__

obj.constructor.polluted

前端的有extend

Lodash 模块原型链污染

lodash.defaultsDeep

lodash.merge

lodash.mergeWith

lodash.setWith

lodash.template

function person(fullName) {
    this.fullName = fullName;
}
var person1 = new person("Satoshi");
// function:prototype, __prototype
person.prototype.sayHello = 1
console.log(person1.__proto__);
person.prototype.newConstant = 2
console.log(person1.__proto__); 

// object: __prototype__, constructor
person1.__proto__.sayHi= 3
console.log(person1.__proto__);
person1.constructor.prototype.oldConstant = 4
console.log(person1.__proto__);
/*
person { sayHello: 1 }
person { sayHello: 1, newConstant: 2 }
person { sayHello: 1, newConstant: 2, sayHi: 3 }
person { sayHello: 1, newConstant: 2, sayHi: 3, oldConstant: 4 }
*/
 

 3.原型链怎么挖掘?

1.寻找JavaScript中的危险关键字(危险函数)。如:

        ·模块:child_process

        ·函数:eval,spwn,exec,setTimeout,setInteval,Function

2.寻找调用关系和可控的参数,并且确定如何进行传参

        先确定危险函数和调用方式,就是头部和尾部,再去找中间过程看具体的使用

 3.充分利用危险函数和能控制的参数.(读取文件或者反弹shell)

        `目标机器环境如果有bash可以反弹shell

        `目标机器环境如果有Python等,可以反弹shell

        `目标机器环境如果只有sh,将readflag执行写入到其他地方,再利用其他方式读取.

4.如何防御原型链污染?如何绕过防御?

        如果系统中有键值的操作,并且健和值来自外部输入,可以考虑进行过滤:

                `禁止操作constructor

                `禁止操作prototype

                `禁止操作__proto__

        绕过防御:

                `思考测试是否过滤完全,参考antCTF的8-bit-pub中的shvl库绕过

 最后

补充一下之前没有提到的

prototype是[方法特有的](大概了解一下)

        `方法:类似C++中的类.除了有属性__proto__,还有属性prototype,prototype指向该方法的原型对象.prototype指定其他对象之后,会包含所有原型对象的属性和方法

        `对象:类似C++中的对象.对象只有属性__proto__指向该对象的构造函数的原型对象.对象有constructor里面包含该类的prototype.

// 让我们从一个函数里创建一个对象o,它自身拥有属性a和b的:
let f = function () {
   this.a = 1;
   this.b = 2;
}
/* 这么写也一样
function f() {
  this.a = 1;
  this.b = 2;
}
*/
let o = new f(); // {a: 1, b: 2}

// 在f函数的原型上定义属性
f.prototype.b = 3;
f.prototype.c = 4;

// 不要在 f 函数的原型上直接定义 f.prototype = {b:3,c:4};这样会直接打破原型链
// o.[[Prototype]] 有属性 b 和 c
//  (其实就是 o.__proto__ 或者 o.constructor.prototype)
// o.[[Prototype]].[[Prototype]] 是 Object.prototype.
// 最后o.[[Prototype]].[[Prototype]].[[Prototype]]是null
// 这就是原型链的末尾,即 null,
// 根据定义,null 就是没有 [[Prototype]]。

// 综上,整个原型链如下:

// {a:1, b:2} ---> {b:3, c:4} ---> Object.prototype---> null

console.log(o.a); // 1
// a是o的自身属性吗?是的,该属性的值为 1

console.log(o.b); // 2
// b是o的自身属性吗?是的,该属性的值为 2
// 原型上也有一个'b'属性,但是它不会被访问到。
// 这种情况被称为"属性遮蔽 (property shadowing)"

console.log(o.c); // 4
// c是o的自身属性吗?不是,需要看它的原型上有没有
// c是o.[[Prototype]]的属性吗?是的,该属性的值为 4

console.log(o.d); // undefined
// d 是 o 的自身属性吗?不是,需要看它的原型上有没有
// d 是 o.[[Prototype]] 的属性吗?不是,需要看它的原型上有没有
// o.[[Prototype]].[[Prototype]] 为 null,停止搜索
// 找不到 d 属性,返回 undefined

 0x01__proto__属性有什么用?

每个'对象'都有__proto__属性,指向了创建该对象的构造函数的原型.其实这个属性指向了[[prototype]],但是[[prototype]]是内部属性,我们并不能访问到,所以使用__proto__来访问.

简单来说:用prototype无法直接访问,需要使用__proto__访问.prototype是一个指针属性.

注意:

        `__proto__:指向原型对象的构造器.

         `constructor:指向当前对象的构造器

 

                                        __proto__箭头指向原型对象的构造器 

 

                                                 constructor箭头指向原型对象的构造器 

好了 开摆!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值