030-安全开发-JS应用&NodeJS指南&原型链污染&Express框架&功能实现&审计
#知识点:
1、NodeJS-开发环境&功能实现
2、NodeJS-安全漏洞&案例分析
3、NodeJS-开发指南&特有漏洞
演示案例:
➢环境搭建-NodeJS-解析安装&库安装
➢功能实现-NodeJS-数据库&文件&执行
➢安全问题-NodeJS-注入&RCE&原型链
➢案例分析-NodeJS-CTF题目&源码审计
➢开发指南-NodeJS-安全SecGuide项目
#环境搭建-NodeJS-解析安装&库安装
0、文档参考:
https://www.w3cschool.cn/nodejs/
1、Nodejs安装
https://nodejs.org/en
2、三方库安装
- express
Express是一个简洁而灵活的node.js Web应用框架 - body-parser
node.js中间件,用于处理 JSON, Raw, Text和URL编码的数据。 - cookie-parser
这就是一个解析Cookie的工具。通过req.cookies可以取到传过来的cookie,并把它们转成对象。 - multer
node.js中间件,用于处理 enctype=“multipart/form-data”(设置表单的MIME编码)的表单数据。 - mysql
Node.js来连接MySQL专用库,并对数据库进行操作。
安装命令:
npm i express
npm i body-parser
npm i cookie-parser
npm i multer
npm i mysql
-
创建sql.js文件并粘贴实例代码
- 发现代码不能运行,需要安装需要的库
- 注意如果网速太慢,可以设置国内的镜像
- 换上 阿里巴巴开源镜像站-OPSX镜像站里的淘宝 NPM 镜像
- 发现展示出Hello World。
复制**npm config set registry [https://registry.npmmirror.com](https://link.zhihu.com/?target=https://registry.npmmirror.com) 查看是否更换 npm config get registry**
// express_demo.js 文件 // 引入 Express 框架 var express = require('express'); // 创建 Express 应用程序实例 var app = express(); // 处理根路径的 GET 请求,返回 'Hello World' app.get('/', function (req, res) { res.send('Hello World'); }); // 启动服务器,监听端口 3000 var server = app.listen(3000, function () { // 获取服务器地址和端口 var host = server.address().address; var port = server.address().port; // 输出服务器访问地址信息到控制台 console.log("应用实例,访问地址为 http://%s:%s", host, port); });
复制
- 设置不同的页面渲染
// 引入 Express 框架 const express = require('express'); // 创建 Express 应用程序实例 const app = express(); // 处理 '/login' 路径的 GET 请求,返回简单的登录页面 app.get('/login', function(req, res) { res.send('<hr>登录页面</hr>'); }); // 处理根路径的 GET 请求,发送名为 'sql.html' 的文件 app.get('/', function(req, res) { res.sendFile(__dirname + '/' + 'sql.html'); }); // 启动服务器,监听端口 3001 const server = app.listen(3001, function() { console.log('Web 服务器已经启动,监听端口 3001!'); });
复制
#功能实现-NodeJS-数据库&文件&执行
1、实现用户登录
req.query
用于处理 URL 查询字符串参数**GET请求
**,而req.body
用于处理 **POST 请求
**中的表单数据。- 还需要下载
**const bodyParser = require('body-parser');
相关库 npm i body-parser** - 并且post请求还需要创建一个解析**
URL编码
**的bodyParser**中间件实例**
- 还需要下载
// 引入 Express 框架 const express = require('express'); const bodyParser = require('body-parser'); // 创建 Express 应用程序实例 const app = express(); 创建一个用于解析 URL 编码的 bodyParser 中间件实例 **const urlencodedParser = bodyParser.urlencoded({ extended: false });** **// 处理 '/login' 路径的 GET 请求,返回简单的登录页面 app.get('/login', function(req, res) {** // 从请求中获取用户名和密码 **const u = req.query.username; const p = req.query.password;** console.log(u); console.log(p); // 检查用户名和密码是否为 admin 和 123456 if (u === 'admin' && p === '123456') { res.send('欢迎进入后台管理页面'); } else { res.send('登录用户或密码错误'); } }); **// 处理 '/login' 路径的 POST 请求,使用 bodyParser 解析表单数据 app.post('/login', urlencodedParser, function(req, res) { // 从请求中获取表单提交的用户名和密码 const u = req.body.username; const p = req.body.password;** console.log(u); console.log(p); // 检查用户名和密码是否为 admin 和 123456 if (u === 'admin' && p === '123456') { res.send('欢迎进入后台管理页面'); } else { res.send('登录用户或密码错误'); } }); // 处理根路径的 GET 请求,发送名为 'sql.html' 的文件 app.get('/', function(req, res) { res.sendFile(__dirname + '/' + 'sql.html'); }); // 启动服务器,监听端口 3001 const server = app.listen(3001, function() { console.log('Web 服务器已经启动,监听端口 3001!'); });
复制
2、加入数据库操作
- 导入mysql ,npm i mysql下载相关依赖
const mysql = require('mysql');
复制
- 导入 mysql 模块
var connection = mysql.createConnection({ host : 'localhost', user : 'root', password : 'root', database : 'dome01' });
复制
- 建立与 MySQL 数据库的连接并执行查询语句,查询数据库中的内容
// 建立与 MySQL 数据库的连接 connection.connect(); // 定义从 'admin' 表中选择所有列的 SQL 查询 const sql ='select * from admin'; // 执行 SQL 查询 connection.query(sql, function(error, data){ // 检查查询执行中是否存在错误 if(error){ console.log('数据库连接失败!'); } // 记录从查询中检索到的全部数据 console.log(data); // 记录结果集中第一行的用户名 console.log(data[0]['username']); // 记录结果集中第一行的密码 console.log(data[0]['password']); });
复制
- 将mysql的内容添加至登录验证中
// 处理 '/login' 路径的 POST 请求,使用 bodyParser 解析表单数据 app.post('/login', urlencodedParser, function(req, res) { // 从请求中获取表单提交的用户名和密码 const u = req.body.username; const p = req.body.password; // 输出获取到的用户名和密码,用于调试 console.log(u); console.log(p); // 创建与 MySQL 数据库的连接 var connection = mysql.createConnection({ host : 'localhost', user : 'root', password : 'root', database : 'dome01' }); **// 建立数据库连接 connection.connect(); // 构建 SQL 查询,检查数据库中是否存在匹配的用户名和密码 const sql = 'select * from admin where username="'+u+'" and password="'+p+'"'; console.log(sql); // 执行 SQL 查询 connection.query(sql, function(error, data){ // 检查查询执行中是否存在错误 if(error){ console.log('数据库连接失败!'); } try { // 检查用户名和密码是否匹配数据库中的数据 if(u == data[0]['username'] && p == data[0]['password']){ // 如果匹配,发送欢迎消息到前端 res.send('欢迎进入后台管理页面'); } } catch { // 捕获异常,如果没有匹配的数据或其他错误,发送错误消息到前端 res.send('错误'); };** }); })
复制
3、文件操作
- 导入fs ,npm i fs下载相关依赖npm i fs
const fs = require('fs');
复制
- 调用文件管理函数,传递目录参数
- http://127.0.0.1:3000/file?dir=./
- http://127.0.0.1:3000/file?dir=…/
// 引入文件系统和 Express 框架 const fs = require('fs'); const express = require('express'); const app = express(); // 处理 '/file' 路径的 GET 请求 app.get('/file', function (req, res) { // 从请求中获取目录参数 const dir = req.query.dir; console.log(dir); **// 调用文件管理函数,传递目录参数 filemanage(dir);** }); // 启动 Express 应用监听在3000端口 var server = app.listen(3000, function () { console.log('Web应用已启动在3000端口!'); }); // 文件管理函数,接收一个目录参数 function filemanage(dir) { **// 使用 fs.readdir 读取目录下的文件 fs.readdir(dir, function (error, files) { // 打印目录中的文件列表 console.log(files);** }); }
复制
1、Express开发
2、实现目录读取
3、加入传参接受
4、命令执行(RCE)
- 导入child_process ,npm i child_process下载相关依赖
const rce=require('child_process');
复制
- exec & spawnSync调用系统命令
- eval调用代码命令执行,将字符串当做代码解析
// 引入child_process模块 const rce = require('child_process'); // 使用exec方法调用系统命令'notepad',打开记事本 rce.exec('notepad'); // 使用spawnSync方法调用系统命令'calc',打开计算器 rce.spawnSync('calc'); // 使用eval调用代码命令执行,将字符串当做代码解析 // 请注意:避免在生产环境中使用eval,可能存在安全风险 eval('require("child_process").exec("calc");');
复制
#安全问题-NodeJS-注入&RCE&原型链
1、SQL注入&文件操作
2、RCE执行&原型链污染
2、NodeJS黑盒无代码分析
黑盒测试和白盒测试区别,以及Payload 定义:
- 黑盒测试(Black Box Testing):
- 黑盒测试是基于功能需求和规格说明的外部测试方法。
- 测试人员在执行黑盒测试时,对系统内部的实现细节一无所知,只关注系统的输入和输出,以及系统的功能行为。
- 测试人员将系统视为一个黑盒子,只关注输入数据、预期输出和系统行为,而不考虑内部的代码逻辑和结构。
- 黑盒测试主要关注系统的功能、界面、性能、安全性等方面,以验证系统是否符合规格说明和用户需求。
- 测试方法包括等价类划分、边界值分析、场景测试、错误推测等。
- 白盒测试(White Box Testing):
- 白盒测试是基于系统的内部实现、代码结构和逻辑的测试方法。
- 测试人员在执行白盒测试时,了解系统的内部结构和代码,可以直接检查、分析和测试系统的内部组成部分。
- 白盒测试主要关注系统的代码覆盖率、逻辑路径、错误处理、性能优化等方面,以验证代码的正确性和质量。
- 测试方法包括语句覆盖、分支覆盖、路径覆盖、条件覆盖、代码审查等。
- Payload 是指在攻击中传递的恶意代码、数据或命令。在进行 Payload 测试时,安全专家会设计和使用各种 Payload 来验证目标系统的安全性,并确定系统是否容易受到攻击或是否存在潜在的漏洞。
实战测试NodeJS安全:
判断:参考前期的信息收集
黑盒:通过对各种功能和参数进行payload测试
白盒:通过对代码中写法安全进行审计分析
- 信息收集(Reconnaissance):
- 收集应用程序的基本信息,如版本号、依赖项版本等。
- 查看应用程序的公开文档,了解其工作原理和功能。
- 分析配置文件,查看是否有敏感信息泄漏的风险。
- 黑盒测试(Black Box Testing):
- 通过输入字段,**尝试注入攻击,例如 SQL 注入、XSS(跨站脚本攻击)**等。
- 测试文件上传功能,确保上传的文件受到适当的限制和验证。
- 构造恶意请求,测试是否存在拒绝服务(DoS)漏洞。
- 尝试绕过身份验证和授权,确保访问控制的有效性。
- 白盒测试(White Box Testing):
- 对代码进行审计,查找潜在的安全问题。
- 检查是否存在明文密码、硬编码的敏感信息等。
- 确保应用程序对用户输入进行适当的验证和转义,以防止注入攻击。
- 避免使用不安全的函数和方法,如
eval
、exec
等。- 确保文件上传和下载等操作受到适当的安全限制。
- 检查是否启用了适当的安全头,如 CSP(内容安全策略)、X-Frame-Options、X-Content-Type-Options 等。
- 依赖项安全:
- 定期审查依赖项的更新和安全漏洞。
- 使用安全审计工具,如 npm audit,来检查依赖项的安全性。
- 使用仅允许信任的依赖项,并确保避免使用已弃用或存在漏洞的依赖项。
原型链污染
如果攻击者控制并修改了一个对象的原型,(proto)
那么将可以影响所有和这个对象来自同一个类、父祖类的对象。
// foo是一个简单的JavaScript对象 let foo = {bar: 1} //1=1 0 __proto__= x // 原型链污染 // foo.bar 此时为1 console.log(foo.bar)//输出为1 // 修改foo的原型(即Object) foo.__proto__.bar = '2' // // 由于查找顺序的原因,foo.bar仍然是1 console.log(foo.bar)//输出为1 // // 此时再用Object创建一个空的zoo对象 let zoo = {} // 查看zoo.bar,此时bar为2 console.log(zoo.bar)//输出为2
复制
利用原型链污染,调用系统计算器
// 创建一个包含属性 bar 的对象 foo,并将 bar 设置为 1 let foo = {bar: 1}; // 输出 foo 对象的 bar 属性,预期输出为 1 console.log(foo.bar); // 输出: 1 **// 修改 foo 对象的原型链上的 bar 属性,将其设置为执行命令 'require(\'child_process\').execSync(\'calc\');' //调用计算机 foo.__proto__.bar = 'require(\'child_process\').execSync(\'calc\');';** // 输出 foo 对象的 bar 属性,预期输出仍为 1,因为直接属性优先于原型链上的属性 console.log(foo.bar); // 输出: 1 // 创建一个空对象 zoo let zoo = {}; **// 使用 eval 执行 zoo 对象的 bar 属性,由于 zoo 对象没有 bar 属性,会导致 ReferenceError //调用计算机 console.log(eval(zoo.bar));**
复制
#案例分析-NodeJS-CTF题目&源码审计
1、CTFSHOW几个题目
https://ctf.show/ Web334-344
https://f1veseven.github.io/2022/04/03/ctf-nodejs-zhi-yi-xie-xiao-zhi-shi/
2、YApi管理平台漏洞
https://blog.csdn.net/weixin_42353842/article/details/127960229
#开发指南-NodeJS-安全SecGuide项目
https://github.com/Tencent/secguide