030-安全开发-JS应用NodeJS指南原型链污染Express框架功能实现审计

news2025/1/7 20:33:24

030-安全开发-JS应用&NodeJS指南&原型链污染&Express框架&功能实现&审计

Untitled

#知识点:

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%3A//registry.npmmirror.com)
    查看是否更换
    npm config get registry**
    

    Untitled

// 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);
});

Untitled

  • 设置不同的页面渲染
// 引入 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!');
});

Untitled

Untitled

#功能实现-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!');
});

Untitled

Untitled

Untitled

Untitled

2、加入数据库操作

  • 导入mysql ,npm i mysql下载相关依赖
const mysql = require('mysql');
  • 导入 mysql 模块
var connection = mysql.createConnection({
host     : 'localhost',
user     : 'root',
password : 'root',
database : 'dome01'
});
  • 建立与 MySQL 数据库的连接并执行查询语句,查询数据库中的内容

Untitled

// 建立与 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('错误');
    };**
  });
})

Untitled

Untitled

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);**
    });
}

Untitled

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");');

Untitled

Untitled

Untitled

#安全问题-NodeJS-注入&RCE&原型链

1、SQL注入&文件操作

Untitled

Untitled

2、RCE执行&原型链污染
2、NodeJS黑盒无代码分析

黑盒测试和白盒测试区别,以及Payload 定义:

  1. 黑盒测试(Black Box Testing):
    • 黑盒测试是基于功能需求和规格说明的外部测试方法。
    • 测试人员在执行黑盒测试时,对系统内部的实现细节一无所知,只关注系统的输入和输出,以及系统的功能行为。
    • 测试人员将系统视为一个黑盒子,只关注输入数据、预期输出和系统行为,而不考虑内部的代码逻辑和结构。
    • 黑盒测试主要关注系统的功能、界面、性能、安全性等方面,以验证系统是否符合规格说明和用户需求。
    • 测试方法包括等价类划分、边界值分析、场景测试、错误推测等。
  2. 白盒测试(White Box Testing):
    • 白盒测试是基于系统的内部实现、代码结构和逻辑的测试方法。
    • 测试人员在执行白盒测试时,了解系统的内部结构和代码,可以直接检查、分析和测试系统的内部组成部分。
    • 白盒测试主要关注系统的代码覆盖率、逻辑路径、错误处理、性能优化等方面,以验证代码的正确性和质量。
    • 测试方法包括语句覆盖、分支覆盖、路径覆盖、条件覆盖、代码审查等。
  3. Payload 是指在攻击中传递的恶意代码、数据或命令。在进行 Payload 测试时,安全专家会设计和使用各种 Payload 来验证目标系统的安全性,并确定系统是否容易受到攻击或是否存在潜在的漏洞。

实战测试NodeJS安全:

判断:参考前期的信息收集
黑盒:通过对各种功能和参数进行payload测试
白盒:通过对代码中写法安全进行审计分析

  1. 信息收集(Reconnaissance):
    • 收集应用程序的基本信息,如版本号、依赖项版本等。
    • 查看应用程序的公开文档,了解其工作原理和功能。
    • 分析配置文件,查看是否有敏感信息泄漏的风险。
  2. 黑盒测试(Black Box Testing):
    • 通过输入字段,**尝试注入攻击,例如 SQL 注入、XSS(跨站脚本攻击)**等。
    • 测试文件上传功能,确保上传的文件受到适当的限制和验证。
    • 构造恶意请求,测试是否存在拒绝服务(DoS)漏洞。
    • 尝试绕过身份验证和授权,确保访问控制的有效性。
  3. 白盒测试(White Box Testing):
    • 对代码进行审计,查找潜在的安全问题。
    • 检查是否存在明文密码、硬编码的敏感信息等。
    • 确保应用程序对用户输入进行适当的验证和转义,以防止注入攻击。
    • 避免使用不安全的函数和方法,如 evalexec 等。
    • 确保文件上传和下载等操作受到适当的安全限制。
    • 检查是否启用了适当的安全头,如 CSP(内容安全策略)、X-Frame-Options、X-Content-Type-Options 等。
  4. 依赖项安全:
    • 定期审查依赖项的更新和安全漏洞。
    • 使用安全审计工具,如 npm audit,来检查依赖项的安全性。
    • 使用仅允许信任的依赖项,并确保避免使用已弃用或存在漏洞的依赖项。

原型链污染

如果攻击者控制并修改了一个对象的原型,(proto)
那么将可以影响所有和这个对象来自同一个类、父祖类的对象。

Untitled

// 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));**

Untitled

#案例分析-NodeJS-CTF题目&源码审计

1、CTFSHOW几个题目

Untitled

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

Untitled

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1430140.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

坚持刷题|二叉树的前、中、后序遍历(递归迭代)

文章目录 题目思考递归实现迭代实现前序遍历后序遍历中序遍历 在前、中、后序的迭代遍历中&#xff0c;为什么都采用栈来模拟递归&#xff0c;而非队列&#xff1f; Hello&#xff0c;大家好&#xff0c;我是阿月。坚持刷题&#xff0c;老年痴呆追不上我&#xff0c;今天刷&…

[SWPUCTF 2021 新生赛]ez_unserialize

根据下面的user_agent和Disallow可以判断这个是在robots.txt 我们看的出来这是一个反序列化需要我们adminadmin passwdctf construct 构造方法&#xff0c;当一个对象被创建时调用此方法&#xff0c;不过unserialize()时却不会被调用 destruct 析构方法&#xff0c;PHP将在对象…

分别用JavaScript,Java,PHP,C++实现桶排序的算法(附带源码)

桶排序是计数排序的升级版。它利用了函数的映射关系&#xff0c;高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效&#xff0c;我们需要做到这两点&#xff1a; 在额外空间充足的情况下&#xff0c;尽量增大桶的数量使用的映射函数能够将输入的 N 个数据均匀的分…

MySQL数据库②_库和表的操作_增删查改_备份恢复

目录 1. 创建数据库 2. 字符集和校验规则 2.1 默认的字符集和校验规则 2.2 支持的字符集校验规则 2.3 校验规则对数据库的影响 3. 库的查看&#xff0c;修改&#xff0c;删除 3.1 查看数据库 3.2 修改数据库 3.3 删除数据库 4. 库的备份和恢复 4.1 备份数据库 4.2 …

在虚拟机上搭建CentOS环境并配置静态IP

在虚拟机上搭建CentOS环境并配置静态IP 在进行Linux系统的学习和实践时&#xff0c;搭建一个本地的CentOS环境是一个非常好的方式。本文将介绍如何使用虚拟机&#xff08;VM&#xff09;搭建CentOS环境&#xff0c;并配置静态IP&#xff0c;以便更好地进行网络管理和测试。 步…

Java开发工具 IntelliJ IDEA 2023中文

IntelliJ IDEA 2023是一款强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;适用于多种编程语言&#xff0c;包括Java、Python、Kotlin等。它提供了许多特色功能&#xff0c;以提高开发效率和代码质量。 Java开发工具 IntelliJ IDEA 2023中文 以下是一些IntelliJ ID…

机器学习复习(4)——CNN算法

目录 数据增强方法 CNN图像分类数据集构建 导入数据集 定义trainer 超参数设置 数据增强 构建CNN网络 开始训练 模型测试 数据增强方法 # 一般情况下&#xff0c;我们不会在验证集和测试集上做数据扩增 # 我们只需要将图片裁剪成同样的大小并装换成Tensor就行 test_t…

跨平台开发:浅析uni-app及其他主流APP开发方式

随着智能手机的普及&#xff0c;移动应用程序&#xff08;APP&#xff09;的需求不断增长。开发一款优秀的APP&#xff0c;不仅需要考虑功能和用户体验&#xff0c;还需要选择一种适合的开发方式。随着技术的发展&#xff0c;目前有多种主流的APP开发方式可供选择&#xff0c;其…

【计网·湖科大·思科】实验七 路由信息协议RIP、开放最短路径优先协议OSPF、边界网关协议BGP

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

nginx初学者指南

一、启动、停止和重新加载配置 前提&#xff1a;先要启动nginx 在Windows上启动nginx的步骤如下&#xff1a; 1. 下载并安装nginx。可以从nginx官网下载适合自己操作系统的版本&#xff0c;一般是zip压缩包&#xff0c;解压到指定目录中。 2. 进入nginx的安装目录&#xff…

简单几步,借助Aapose.Cells将 Excel 工作表拆分为文件

近年来&#xff0c;Excel 文件已成为无数企业数据管理的支柱。然而&#xff0c;管理大型 Excel 文件可能是一项艰巨的任务&#xff0c;尤其是在高效共享和处理数据时。为了应对这一挑战&#xff0c;大型 Excel 工作簿被拆分为较小的工作簿以增强电子表格管理。Aspose提供了这样…

electron项目在内网环境的linux环境下进行打包

Linux需要的文件: electron-v13.0.0-linux-x64.zip appimage-12.0.1.7z snap-template-electron-4.0-1-amd64.tar.7z 下载慢或者下载失败的情况可以手动下载以上electron文件复制到指定文件夹下&#xff1a; 1.electron-v13.0.0-linux-x64.zip 复制到~/.cache/electron/目录下…

Blender使用Rigify和Game Rig Tool基础

做动画需要的几个简要步骤&#xff1a; 1.建模 2.绑定骨骼 3.绘制权重 4.动画 有一个免费的插件可以处理好给引擎用&#xff1a;Game Rig Tool 3.6和4.0版本的 百度网盘 提取码&#xff1a;vju8 1.Rigify是干嘛用的&#xff1f; 》 绑定骨骼 2.Game Rig Tool干嘛用的&#xf…

LVGL部件8

一.按钮矩阵部件 1.知识概览 2.函数接口 1.lv_btnmatrix_set_btn_ctrl 在 LVGL&#xff08;LittlevGL&#xff09;中&#xff0c;lv_btnmatrix_set_btn_ctrl() 函数用于设置按钮矩阵&#xff08;Button Matrix&#xff09;中单个按钮的控制选项。该函数可以用来定制按钮矩阵中…

寒假作业2月3号

第二章 引用内联重载 一&#xff0e;选择题 1、适宜采用inline定义函数情况是&#xff08;C&#xff09; A. 函数体含有循环语句 B. 函数体含有递归语句 C. 函数代码少、频繁调用 D. 函数代码多、不常调用 2、假定一个函数为A(int i4, int j0) {;}, 则执行“A (1);”语句…

【蓝桥杯】环形链表的约瑟夫问题

目录 题目描述&#xff1a; 输入描述&#xff1a; 输出描述&#xff1a; 示例1 解法一&#xff08;C&#xff09;&#xff1a; 解法二&#xff08;Cpp&#xff09;&#xff1a; 正文开始&#xff1a; 题目描述&#xff1a; 据说著名犹太历史学家 Josephus 有过以下故事&a…

UE4 C++ 枚举类型

先在UCLASS()前写入&#xff1a; //定义枚举变量&#xff1a;方法一 UENUM(BlueprintType) //BlueprintType&#xff1a;在蓝图中可显示、创建该枚举变量 namespace MyEnumType //namespace&#xff1a;命名空间&#xff0c;支持同样的变量命令、便于访问//MyEnumType&#xf…

如何保证MySQL和Redis中的数据一致性?

文章目录 前言一、缓存案例1.1 缓存常见用法1.2 缓存不一致产生的原因 二、解决方案2.1 先删除缓存&#xff0c;再更新数据库2.2 先更新数据库&#xff0c;删除缓存2.3 只更新缓存&#xff0c;由缓存自己同步更新数据库2.4 只更新缓存&#xff0c;由缓存自己异步更新数据库2.5 …

【MybatisPlus篇】查询条件设置(范围匹配 | 模糊匹配 | 空判定 | 包含性判定 | 分组 | 排序)

文章目录 &#x1f384;环境准备⭐导入依赖⭐写入User类⭐配置启动类⭐创建UserDao 的 MyBatis Mapper 接口&#xff0c;用于定义数据库访问操作⭐创建配置文件&#x1f6f8;创建测试类MpATest.java &#x1f354;范围查询⭐eq⭐between⭐gt &#x1f354;模糊匹配⭐like &…

力扣之2629.复合函数(reduceRight )

/*** param {Function[]} functions* return {Function}*/ var compose function(functions) {return function(x) {return functions.reduceRight((result, func) > func(result), x);} };/*** const fn compose([x > x 1, x > 2 * x])* fn(4) // 9*/ 说明&#x…