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

欺骗单页应用(SPA)渲染隐藏路由 -- trouble at the spa b01lersCTF

题目信息:I had this million-dollar app idea the other day, but I can’t get my routing to work! I’m only using state-of-the-art tools and frameworks, so that can’t be the problem… right? Can you navigate me to the endpoint of my dreams?

题目使用 vite

{"name": "src","private": true,"version": "0.0.0","type": "module","scripts": {"dev": "vite","build": "tsc -b && vite build","lint": "eslint .","preview": "vite preview"},"dependencies": {"@tailwindcss/vite": "^4.1.3","react": "^19.0.0","react-dom": "^19.0.0","react-router": "^7.5.0","tailwindcss": "^4.1.3"},"devDependencies": {"@types/react": "^19.0.10","@types/react-dom": "^19.0.4","@vitejs/plugin-react": "^4.3.4","globals": "^15.15.0","typescript": "~5.7.2","vite": "^6.2.0","vite-plugin-javascript-obfuscator": "^3.1.0"}
}

查看路由

// 从 react 库中导入 StrictMode 组件,它可以帮助我们在开发模式下发现潜在问题
import { StrictMode } from 'react';
// 从 react-dom/client 库中导入 createRoot 函数,用于创建 React 根节点
import { createRoot } from 'react-dom/client';
// 从 react-router 库中导入 BrowserRouter、Routes 和 Route 组件,用于实现路由功能
import { BrowserRouter, Routes, Route } from 'react-router';// 导入页面组件
// 导入 App 组件,作为首页展示
import App from './App.tsx';
// 导入 Flag 组件,用于 /flag 路径的页面展示
import Flag from './Flag.tsx';// 导入全局样式文件
import './index.css';/*** 使用 createRoot 函数创建一个 React 根节点,挂载到 id 为 'root' 的 DOM 元素上* 并渲染 React 应用程序*/
createRoot(document.getElementById('root')!).render(// 使用 StrictMode 组件包裹应用,在开发模式下检查潜在问题<StrictMode>{/* 使用 BrowserRouter 组件为应用提供路由功能 */}<BrowserRouter>{/* 使用 Routes 组件来定义一组路由规则 */}<Routes>{/* 定义首页路由,当路径为根路径时,渲染 App 组件 */}<Route index element={<App />} />{/* 定义 /flag 路径的路由,当路径为 /flag 时,渲染 Flag 组件 */}<Route path="/flag" element={<Flag />} /></Routes></BrowserRouter></StrictMode>
);

看看flag

export default function Flag() {return (<section className="text-center pt-24"><div className="flex items-center text-5xl font-bold justify-center">{'bctf{test_flag}'}</div></section>)
}

访问 /flag 返回 404 , 根据题目,我不可能修改服务器端代码,接下来我怎么访问 /flag?

The site configured at this address does not contain the requested file.If this is your site, make sure that the filename case matches the URL as well as any file permissions.  
For root URLs (like `http://example.com/`) you must provide an `index.html` file.[Read the full documentation](https://help.github.com/pages/) for more information about using **GitHub Pages**.
import Header from './Header.tsx';
import AdCard from './AdCard.tsx';
import Footer from './Footer.tsx';function App() {const sponsors = ['microsoft.svg', 'google.svg', 'amazon.svg', 'netflix.svg', 'meta.svg', 'apple.svg'];return (<><Header /><section className="text-center pt-24"><h1 className="text-7xl mb-4 font-bold">Quantum b01lerchain</h1><p>Quantum-computing based blockchain technology at scale, automatically secured by cutting-edgeAI threat-assessment models.</p></section><section className="pt-14 pb-2 mb-20"><div className="w-full mx-auto -z-10 bg-gradient-to-r from-yellow-500 via-pink-400 to-red-500 transform -skew-y-3 flex flex-row"><div className="transform skew-y-3 mx-auto -my-4 flex flex-row space-x-12"><AdCardtitle="Quantum powered"src="/0f5146d5ed9441853c3f2821745a4173.jpg">Leveraging distributed quantum compute power, b01lerchain technology achieves energyefficiency where other blockchains fail.</AdCard><AdCardtitle="Blockchain at scale"src="/0bee89b07a248e27c83fc3d5951213c1.jpg">All b01lerchain transactions are backed up across 10 different blockchains,ensuring data security.</AdCard><AdCardtitle="AI++"src="/5ab557c937e38f15291c04b7e99544ad.jpg">Leveraging scalable quantum compute power, b01lerchain technology achieves energy efficiencywhere other blockchains fail.</AdCard></div></div></section><section className="mb-8"><p className="text-sm text-center text-secondary mb-3">Proudly powered by</p><div className="flex gap-x-10 gap-y-2 items-center flex-wrap justify-center px-6">{sponsors.map((l) => (<imgsrc={l}className="h-12"key={l}/>))}</div></section><h3 className="font-bold text-xl text-center mb-8">Join 1,200+ investors sharing in b01lerchain's vision.</h3><section><p className="max-w-5xl px-8 mx-auto mb-8">View our demo below:</p><imgsrc="/483032a6422b3ba7005dfa12dda874b5.jpg"className="w-full h-[30rem] object-cover object-center opacity-50"/></section><Footer /></>)
}
'use client'import { useScroll } from '../hooks/useScroll';export default function Header() {const scroll = useScroll();return (<header className={`sticky top-0 z-50 ${scroll > 0 ? 'bg-midnight/90 shadow-md backdrop-blur-sm' : 'bg-midnight hover:bg-midnight/90 hover:shadow-md hover:backdrop-blur-sm'} transition-shadow duration-300 ease-in-out`}><nav className="px-8 py-4 flex gap-4 items-center"><a href="/" className="flex items-center gap-2"><imgsrc="/icon.svg"alt="b01lerchain logo"className="size-6"/><h3 className="font-semibold">b01lerchain</h3></a><a href="/#" className="ml-auto text-inherit hover:no-underline">About</a><a href="/#" className="text-inherit hover:no-underline">FAQ</a><a href="/flag" className="text-inherit hover:no-underline">Flag</a></nav></header>)
}

查一手漏洞

Report Summary┌───────────────────┬──────┬─────────────────┬─────────┐
│      Target       │ Type │ Vulnerabilities │ Secrets │
├───────────────────┼──────┼─────────────────┼─────────┤
│ package-lock.json │ npm  │        1        │    -    │
└───────────────────┴──────┴─────────────────┴─────────┘
Legend:
- '-': Not scanned
- '0': Clean (no security findings detected)package-lock.json (npm)Total: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 0, CRITICAL: 0)┌─────────┬────────────────┬──────────┬────────┬───────────────────┬──────────────────────────────────────┬───────────────────────────────────────────────────────────┐
│ Library │ Vulnerability  │ Severity │ Status │ Installed Version │            Fixed Version             │                           Title                           │
├─────────┼────────────────┼──────────┼────────┼───────────────────┼──────────────────────────────────────┼───────────────────────────────────────────────────────────┤
│ vite    │ CVE-2025-32395 │ MEDIUM   │ fixed  │ 6.2.5             │ 6.2.6, 6.1.5, 6.0.15, 5.4.18, 4.5.13 │ vite: Vite has an `server.fs.deny` bypass with an invalid │
│         │                │          │        │                   │                                      │ `request-target`                                          │
│         │                │          │        │                   │                                      │ https://avd.aquasec.com/nvd/cve-2025-32395                │                                                                                                             
└─────────┴────────────────┴──────────┴────────┴───────────────────┴──────────────────────────────────────┴───────────────────────────────────────────────────────────┘

复现与修复指南:Vite再次bypass(CVE-2025-32395)

但是服务器没有 /@fs

放弃 ------------------------------------------------------------------------------------------------------------

赛后

1. SPA 是什么?
  • 定义
    SPA(单页应用)是一种通过动态重写当前页面内容(而非加载新页面)实现交互的 Web 应用。所有逻辑(路由、数据获取、渲染)均在浏览器中运行,只需加载一次 index.html,后续通过 JavaScript 与 API 交互更新内容。

  • 核心特点

    • 无整页刷新:页面切换时仅局部更新内容,体验更流畅。
    • 前端路由:通过 react-routerVue Router 等库管理 URL 路径与组件的映射。
    • 前后端分离:后端仅提供 API 接口,前端独立处理业务逻辑与渲染。
  • 技术依赖
    依赖现代前端框架(React、Vue、Angular)及工具链(Webpack、Vite)。

2. SPA 的工作原理
  1. 首次加载
    • 用户访问网站时,服务器返回 index.html 和打包后的 JS/CSS 文件。
    • 浏览器解析并执行 JS,渲染初始页面(如登录页或主页)。
  2. 后续交互
    • 用户点击链接或按钮时,前端路由库拦截请求,根据 URL 匹配对应组件。
    • 前端通过 API 异步获取数据,动态更新 DOM(无需整页刷新)。
  3. URL 管理
    • 使用 history.pushState()window.location.hash 修改 URL,避免浏览器向服务器发送请求。

我们可以使用,有效负载欺骗前端js渲染隐藏路由

以下代码实现了 修改 URL + 触发路由更新 的核心逻辑:

history.pushState(null, '', '/flag');                  // Step 1: 修改 URL
window.dispatchEvent(new PopStateEvent('popstate'));   // Step 2: 触发事件
Step 1: history.pushState 的作用
  • 底层行为
    调用浏览器 History API 的 pushState 方法,向浏览器的 会话历史栈(Session History) 中添加一条新记录。

  • 关键细节

    1. 修改 URL 但不刷新页面:仅更新地址栏显示,不触发 HTTP 请求(对比 window.location.href = '/flag' 会触发页面跳转)。
    2. 关联状态数据:第一个参数 state 允许存储任意 JSON 序列化对象(如 { page: 'flag', auth: true }),绑定到新历史记录条目。
    3. 同源策略限制:新 URL 必须与当前页面同源(Same Origin),否则抛出安全错误。
  • 数据结构示例

    history.pushState({ timestamp: Date.now(), user: 'guest' }, // 有效负载(状态数据)'',                                       // 标题(忽略)'/flag'                                   // 新 URL
    );
    
Step 2: PopStateEvent 的触发机制
  • 事件本质
    popstate 是浏览器原生事件,通常在 用户点击后退/前进按钮 或调用 history.back()/history.go() 时触发。

  • 手动触发的意义
    通过 dispatchEvent 主动派发 popstate 事件,模拟浏览器历史导航行为,欺骗前端路由库(如 React Router)执行路由更新逻辑。

  • 事件对象细节

    new PopStateEvent('popstate', {state: history.state,  // 必须与当前历史条目的 state 一致bubbles: true,         // 事件是否冒泡(默认 false)cancelable: true       // 事件是否可取消(默认 false)
    });
    
    • state 字段的强制一致性
      若手动传递的 statehistory.state 不一致,React Router 等库可能忽略此次事件(视为非法状态变更)。
http://www.xdnf.cn/news/261595.html

相关文章:

  • Ubuntu 24.04 完整Docker安装指南:从零配置到实战命令大全
  • NuttX 与 PX4 系统开发全流程详解
  • 《AI大模型应知应会100篇》第46篇:大模型推理优化技术:量化、剪枝与蒸馏
  • 基于 SAFM 超分辨率上采样模块的 YOLOv12 改进方法—模糊场景目标检测精度提升研究
  • 一、大模型原理:第一步分词Tokenization
  • MySQL数据操作全攻略:DML增删改与DQL高级查询实战指南
  • hadoop存储数据文件原理
  • 微服务设计约束
  • 介绍 PHP-FPM 和 Python WSGI
  • 【Bootstrap V4系列】学习入门教程之 组件-按钮(Buttons)
  • 宝塔docker拉取仓库失败
  • Nginx发布Vue(ElementPlus),与.NETCore对接(腾讯云)
  • list的迭代器详讲
  • Linux之基础开发工具(yum,vim,gcc,g++)
  • 基于 Dify + vLLM插件 + Qwen3 构建问答机器人Docker版
  • 【计算机视觉】三维重建: OpenMVS:工业级多视图立体视觉重建框架
  • ActiveMQ 集群搭建与高可用方案设计(二)
  • 生成对抗网络(GAN, Generative Adversarial Network)​
  • More Effective C++学习笔记
  • ShaderToy学习笔记 08.阴影
  • 力扣:24两两交换链表的节点
  • 搭建一个 gRPC 服务端和客户端
  • 【Java学习】关于springBoot的自动配置和起步依赖
  • CSS 预处理器 Sass
  • 【2025软考高级架构师】——案例分析总结(13)
  • 如何写好大模型提问提示词:从入门到精通的实战指南
  • 华为云Flexus+DeepSeek征文|快速搭建Dify LLM应用开发平台教程
  • 启发式算法-蚁群算法
  • 2.2 矩阵
  • 前端跨域问题怎么在后端解决