当前位置: 首页 > news >正文

第三十八天(Node.JS)

#环境搭建-NodeJS-解析安装&库安装

0、文档参考:

Node.js 教程 | 菜鸟教程

1、Nodejs安装

Node.js — Run JavaScript Everywhere

确保输入 node 时 可以输出版本

输入npm时可以显示下面内容 就算安装完成了

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

#功能实现-NodeJS-数据库&文件&执行

1、Express开发

2、实现用户登录

3、加入数据库操作

 先安装mysql 库

npm install mysql

连接数据库和对数据库内容进行查询,这里是查询admin表中 id=1 的数据

var mysql      = require('mysql');
var connection = mysql.createConnection({
    host     : 'localhost',
    user     : 'root',
    password : '654321',
    database : 'phpstudy'
});
 
connection.connect();
 
var sql = 'SELECT * FROM admin where id=1';
 
connection.query(sql, function (error, results, fields) {
    if (error) throw error;
    console.log(results[0]);
});

将id值改成2

将id接收值改成一个可控变量,尝试用sql注入语句测试执行

 
var express =require('express');
var app = express();
 
var mysql      = require('mysql');
var connection = mysql.createConnection({
    host     : 'localhost',
    user     : 'root',
    password : '654321',
    database : 'phpstudy'
});
 
connection.connect();
app.get('/sql', function (req, res) {
    var id = req.query.id;
    var sql = 'SELECT * FROM admin where id='+id;
    connection.query(sql, function (error, results, fields) {
        if (error) {throw error;
        console.log('[SELECT ERROR] -',error.message);
        return;}
        console.log('[SELECT OK] -',results);
        res.send(results);
    });
});
 
var server = app.listen(8032, function () {
 
    var host = server.address().address
    var port = server.address().port
 
    console.log("应用实例,访问地址为 http://%s:%s", host, port)
 
});

正常输入参数值

输入sql 语句,获取参数显示位置

在显示位置中输入sql语句,获取数据库名和用户名

-文件操作

1、Express开发

2、实现目录读取

3、加入传参接受

 先创建一个1.txt文件,往里面输入一些内容

再创建一个js文件,写入下面代码

右键运行该文件,可以看到,这里的console 显示的内容是在程序里面显示而不是在浏览器中的控制台中,这里也说明node.js 可以相当于浏览器

这里访问js文件时不会运行里面的代码,而是直接输出了

如何在node.js中启动网站?如何让node.js运行在网站中?

先安装一个express库

先引入express 库 ,写一个端口监听的,然后启动这个js

在网页中访问这个js文件,网页中可以看到 并未执行上面的读取文件的操作,因为这里要加一个路由关系,比如:访问某个路径时执行这个函数

将要在访问某个地址时执行的代码放在函数里面,这样一访问地址时就会触发,从而执行里面的代码

这里刷新一次就会打印一次数据,但是这里还是将数据显示在js运行框里

如何让代码执行结果输出到浏览器中呢?

只需要加一句代码就可以将数据内容显示到浏览器上面去 ,输入 :res.send(data); 这个res是和上面那个有关的,所以当上面的名字改变时,那么下面的也要跟着改动

接收输入参数 req.query.x 将接收过来的值赋值给name ,res.send(name); 将那么值在浏览器中输出出来

其实req就是接收输入的内容,res就是 返回值

那么将文件名改成一个可控变量不就可以实现任意文本读取,这里用get请求方式

app.get('/file', function (req, res) {
    var name = req.query.file;
    // res.send(name);
 
    fs.readFile(name, 'utf-8', function (err, data) {
        if(err) throw err;
        console.log(data);
        res.send(data);
    });
})

这里在js文件上级创建了一个1.txt文件,将参数值file 加一个../ 跳到上一级,读取1.txt文件,执行成功

这里是读取不了php文件,但是可以读取js文件,应该是不支持读取其他类型文件

将文件读取改成目录读取,用post提交方式请求

app.post('/dir', function (req, res) {
    var name = req.query.dir;
    // res.send(name);
    fs.readdir(name, 'utf-8', function (err, data) {
        if(err) throw err;
        console.log(data);
        res.send(data);
    });
})

打开postman 选择post 提交方式, 将变量名和值输入到网址去,下面就会根据输入内容,将内容以post方式发送

这里就遍历 到了当前目录下的所有文件

遍历上级目录下的所有文件

这里右键源代码是查看不到任何代码的,只能看到执行结果,和之前原生开发时可以看到前端的js代码完全相反

那么可以看到用了node.js 后 ,它既有前端的效果,又有后端的隐蔽性,同时 还是一个运行JavaScript的环境,不用搭建apache,也可以运行到web应用中

-命令执行(RCE)

1、eval

2、exec & spawnSync

 先安装一个 child_process

执行命令测试: exec & spawnSync

const child_process = require('child_process');

child_process.exec('calc');

代码执行测试: eval

#NodeJS安全

1、SQL注入&文件操作

2、RCE执行&原型链污染

 RCE执行

构建网站:

const child_process = require('child_process');
var express =require('express');
var app = express();
// 命令执行
// child_process.exec('calc');
// child_process.spawnSync('calc');
// 代码执行
// eval('child_process.exec(\'calc\');');
 
app.get('/rce', function (req, res) {
    const cmd = req.query.cmd;   //定义一个变量接收参数值
    child_process.exec(cmd);
 
 
})
 
var server = app.listen(8032, function () {
    var host = server.address().address
    var port = server.address().port
    console.log("应用实例,访问地址为 http://%s:%s", host, port)
 
});

将cmd值输入 calc ,成功弹出计算器

原型链污染

原理:在一个应用中,如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染

当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象(object)都有一个私有属性(称之为 proto )指向它的构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(proto),层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。

意思:原型链污染是只要污染了object对象中的proto 就相当于把所有的对象都污染了,因为object是所有对象的顶级父类;

举例:

在 JavaScript 中,当访问对象的某个属性(如 obj.prop)时,查找顺序是:

  1. 先在对象自身上查找该属性,如果存在则直接返回其值。
  2. 如果自身不存在,就沿着 __proto__ 指向的原型对象查找。
  3. 如果原型对象也没有,就继续沿着原型的 __proto__ 向上查找(即原型链),直到找到 Object.prototype。
  4. 若整个原型链都没有该属性,则返回 undefined。

这里foo 的第二次输出bar值时仍是1,因为查询规则 先查 foo 自身,发现有 bar: 1,直接返回;

foo.__proto__.bar = 2;   //foo.__proto__ 指向 Object.prototype(因为 foo 是普通对象,原型是 Object.prototype
这行代码实际是给 Object.prototype 添加了一个属性 bar,值为 2

新建的zoo 是一个空对象,自身没有 bar 属性

zoo 的 __proto__ 同样指向 Object.prototype(所有普通对象的原型都是 Object.prototype) 所以会输出2

// foo是一个简单的JavaScript对象
let foo = {bar: 1}
 
// foo.bar 此时为1
console.log(foo.bar)
 
// 修改foo的原型(即Object
foo.__proto__.bar = 2
 
// 由于查找顺序的原因,foo.bar仍然是1
console.log(foo.bar)
 
// 此时再用Object创建一个空的zoo对象
let zoo = {}
 
// 查看zoo.bar,此时bar为2
console.log(zoo.bar)

原型链污染配合RCE

有原型链污染的前提之下,我们可以控制基类的成员,赋值为一串恶意代码,从而造成代码注入。

运行代码之后会弹出计算器

let foo = {bar: 1}
 
console.log(foo.bar)
 
foo.__proto__.bar = 'require(\'child_process\').execSync(\'calc\');'
 
console.log(foo.bar)
 
let zoo = {}
 
console.log(eval(zoo.bar))

效果

2、NodeJS黑盒无代码分析

实战测试NodeJS安全:

判断:参考前期的信息收集

黑盒:通过对各种功能和参数进行payload测试

白盒:通过对代码中写法安全进行审计分析

-原型链污染

如果攻击者控制并修改了一个对象的原型,(proto)

那么将可以影响所有和这个对象来自同一个类、父祖类的对象。

http://www.lryc.cn/news/623956.html

相关文章:

  • AUTOSAR ARXML介绍
  • gin结合minio来做文件存储
  • Oracle Undo Tablespace 使用率暴涨案例分析
  • UE5多人MOBA+GAS 49、创建大厅
  • java设计模式之迪米特法则使用场景分析
  • ​​Vue 3 开发速成手册
  • PHP现代化全栈开发:测试驱动开发与持续交付实践
  • MCP原理与开发及与大模型交互流程
  • 最小路径和
  • 【JAVASE】-9- 接口语法基础
  • Android中切换语言的方法
  • DNS总结
  • 【Linux内核】Linux信号机制
  • linux 常用代码
  • nodejs 错误处理
  • Collections.synchronizedList是如何将List变为线程安全的
  • vs studio 2017项目不支持studio vs2022
  • 【k8s】Kubernetes核心概念与架构详解
  • 从0实现系统设计
  • Leetcode 15 java
  • GitHub Copilot:AI编程助手的架构演进与真实世界影响
  • 浜掕仈缃戝ぇ鍘侸ava姹傝亴鑰呴潰璇曠幇鍦猴細褰撲弗鑲冮潰璇曞畼閬囦笂鎼炵瑧绋嬪簭鍛樿阿椋炴満
  • Conda 环境 在AI 私有化部署 有怎么用?
  • 电力设备状态监测与健康管理:基于多源异构数据融合的技术实现
  • 五、redis入门 之 客户端连接redis
  • 计算机网络 HTTP1.1、HTTP2、HTTP3 的核心对比及性能分析
  • ReactNode 类型
  • Java项目中短信的发送
  • 密码学系列 - 零知识证明(ZKP) - 多种承诺方案
  • Java ConcurrentHashMap 深度解析