news 2026/10/15 20:12:28

fbctf 关卡搭建实战:Too Small 弱 RSA 加密题(256 位密钥分解)从生成到上线的完整流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
fbctf 关卡搭建实战:Too Small 弱 RSA 加密题(256 位密钥分解)从生成到上线的完整流程
  • 网络安全
  • 后端
  • 前端

【免费下载链接】fbctf

Platform to host Capture the Flag competitions

项目地址:https://gitcode.com/gh_mirrors/fb/fbctf
点击查看免费下载

本篇技术指南以 fbctf 官方示例关卡demo_levels/too_small的 README.md 为主体,完整讲解如何用 OpenSSL 生成 256 位 RSA 密钥与加密 Flag、在 fbctf 管理后台创建 "Too Small" Flag 关卡并绑定附件、以及该题在玩家视角下"看似无解实则秒破"的弱密钥原理。读完本文,你将掌握 fbctf 平台 Flag 类关卡的从出题脚本到管理后台上线的全流程,并能从源码层面理解关卡的计分、判定与提示扣分机制。

关卡设计意图:一道"劝退"玩家的 RSA 送分题

Too Small 是 fbctf 仓库内置的演示关卡之一,位于 demo_levels/too_small 目录,题目叙事沿用官方 README 的原文:

You've recovered 3 encrypted files and an RSA public key. Since the files are RSA encrypted and RSA hasn't been broken yet, I guess you should just give up now.

题目伪装成"你恢复了 3 个加密文件和一个 RSA 公钥,既然 RSA 还没有被攻破,不如直接放弃"的悲观口吻,实际上是在提示参赛者:这个 RSA 密钥的位数太小了——256 位模数在现代计算能力面前完全不堪一击。题目名 "Too Small" 正是对密钥规模的暗示。

该关卡的最终 Flag 为:

flag{RSA_i5_n00b}

关卡目录下的文件构成如下:

文件作用
README.md出题与上线操作说明
weakrsa.sh一键生成密钥、加密 Flag、打包附件的脚本
tooSmall.tar.gz脚本产出的附件包(公钥 + 3 个密文)
tooSmallflag.txt、tooSmallflag2.txt、tooSmallflag3.txt被拆成三段的 Flag 明文

其中三个明文文件的真实内容分别是flag{RS、A_i5、_n00b},首尾拼接即得到完整 Flag。这也是出题思路的一部分:把 Flag 拆成多段分别加密,迫使参赛者必须完成多次解密/分解才能拼出完整答案。

环境准备与 weakrsa.sh 出题脚本逐行拆解

运行脚本

./weakrsa.sh

该脚本会生成一个 256 位 RSA 密钥,并将三个 Flag 文件加密。完整的脚本内容如下(weakrsa.sh):

#!/bin/bash openssl genrsa -out private_key.pem 256 openssl rsa -in private_key.pem -out public_key.pem -outform PEM -pubout openssl rsautl -encrypt -inkey public_key.pem -pubin -in tooSmallflag.txt -out tooSmallflag.enc openssl rsautl -encrypt -inkey public_key.pem -pubin -in tooSmallflag2.txt -out tooSmallflag2.enc openssl rsautl -encrypt -inkey public_key.pem -pubin -in tooSmallflag3.txt -out tooSmallflag3.enc tar -cvf tooSmall.tar.gz public_key.pem *.enc rm -f *.enc *.pem

各条命令的作用与参数说明

  1. 生成 256 位 RSA 私钥

    openssl genrsa -out private_key.pem 256

    genrsa用于生成 RSA 私钥,最后的256是指模数的位数。现代安全标准要求至少 2048 位,256 位早已被公开的分解挑战远远甩开——作为对比,512 位模数(RSA-155)早在 1999 年就已被公开分解,768 位(RSA-768)也于 2009 年告破,256 位属于"几分钟内可分解"的规模。这正是本题的考点。

  2. 从私钥导出 PEM 格式公钥

    openssl rsa -in private_key.pem -out public_key.pem -outform PEM -pubout

    -pubout表示输出公钥,-outform PEM指定输出格式为 PEM(Base64 编码的 DER 结构),生成public_key.pem供参赛者使用。公钥是公开信息,可以放心打包进附件。

  3. 用公钥分别加密三个 Flag 片段

    openssl rsautl -encrypt -inkey public_key.pem -pubin -in tooSmallflag.txt -out tooSmallflag.enc openssl rsautl -encrypt -inkey public_key.pem -pubin -in tooSmallflag2.txt -out tooSmallflag2.enc openssl rsautl -encrypt -inkey public_key.pem -pubin -in tooSmallflag3.txt -out tooSmallflag3.enc

    rsautl是 OpenSSL 的 RSA 底层工具:-encrypt指定加密,-pubin声明输入的-inkey是公钥,-in/-out分别指定明文输入与密文输出。三个片段分别输出为tooSmallflag.enc、tooSmallflag2.enc、tooSmallflag3.enc。

  4. 打包成附件

    tar -cvf tooSmall.tar.gz public_key.pem *.enc

    注意这里的打包命令使用的是-cvf(普通 tar 归档)而非-czvf(gzip 压缩),只是扩展名带.gz。实际解包时用tar -xvf tooSmall.tar.gz即可(tar会自动识别格式)。仓库自带的附件包内容(经tar -tvf验证)为:

    public_key.pem 138 字节 tooSmallflag.enc 32 字节 tooSmallflag2.enc 32 字节 tooSmallflag3.enc 32 字节

    每个密文恰好 32 字节,与 256 位模数(32 字节)的 RSA 密文长度一致。打包后脚本立即执行rm -f *.enc *.pem清理现场,确保私钥不会留在出题目录里,只保留打包好的附件交给平台。

附件包内的公钥与密文验证

将附件包中的public_key.pem解出可见其 PEM 内容为:

-----BEGIN PUBLIC KEY----- MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhALpU7GeuLcnFLSXsUIObhPCcYmdz7P3g zrbSkgMgmeIvAgMBAAE= -----END PUBLIC KEY-----

该 DER 编码的公钥中模数部分为 32 字节(256 位),与脚本中genrsa ... 256的参数完全吻合,证实这是一把极弱密钥。参赛者拿到附件后,只需要对 256 位模数做整数分解(可使用 YAFU、CADO-NFS、GMP-ECM 等公开分解工具,或针对小公因数/相近素数构造的 Fermat 分解等经典手段),即可重建私钥并逐段解密三个密文,拼出flag{RSA_i5_n00b}。上述分解手段属于通用密码学背景知识,并非仓库代码的一部分,但正是这道题期望参赛者掌握的技能。

在 fbctf 管理后台创建并上线 Flag 关卡

操作步骤(继承自官方 README)

  1. 进入平台管理后台:index.php?p=admin。

  2. 进入Levels: Flags页面。

  3. 点击Add Flag Level按钮。

  4. 填写关卡信息,例如名称Too Small、分值(points)以及想提供给参赛者的提示(hints)。下面给出官方推荐的描述文案:

    You've recovered 3 encrypted files and an RSA public key. Since the files are RSA encrypted and RSA hasn't been broken yet, I guess you should just give up now.

  5. 点击Create按钮创建关卡。

  6. 在刚创建的关卡上点击Edit,为该关卡添加附件。

  7. 点击+ Attachment。

  8. 选择脚本生成的tooSmall.tar.gz文件。

  9. 最后点击Create和Save完成保存。

上线前还需点击关卡卡片左上角的On按钮启用该关卡,之后即可在 Gameboard 上看到它。需要特别注意的是:只有游戏正式开始(game is on)后,玩家才能提交答案。

后台操作背后的源码机制

  • 后台页面入口:AdminController::getPages()明确声明了管理后台支持的页面集合,其中包含'flags'(即 README 所说的 "Levels: Flags")等页面(见 AdminController.php)。
  • 关卡数据落库:创建 Flag 关卡最终调用Level::genCreateFlag(),其内部以类型'flag'调用通用创建逻辑genCreate()(见 Level.php)。从 database/schema.sql 可看到levels表的完整字段:type(varchar(4),取值为flag/quiz/base)、title、description、entity_id(关联国家)、category_id(关联分类)、points、bonus、bonus_dec、bonus_fix、flag、hint、penalty、active等。新创建的关卡active初始为0(未启用),与 README 中"点击 On 按钮启用"的操作一一对应。
  • 启用/停用关卡:Level::genSetStatus()通过UPDATE levels SET active = %d切换状态,并同步生成管理员活动日志与公告("XX enabled!/disabled!")(见 Level.php)。
  • 附件落盘细节:点击 "+ Attachment" 上传文件后,Attachment::genCreate()会将文件移动到/var/www/fbctf/attachments/目录,并以"原文件名_文件 MD5"重命名、强制0600权限与www-data属主,随后在attachments表中写入level_id、filename、type记录(见 Attachment.php 与 database/schema.sql)。也就是说,参赛者从 Gameboard 下载到的正是这份tooSmall.tar.gz。

玩家侧视角:为什么"RSA 还没被攻破"是陷阱

从竞赛出题的角度,Too Small 的立意非常清晰:

  • 叙事反讽:题目描述信誓旦旦地说"RSA 还没被攻破,建议放弃",但前提被悄悄替换成了"256 位密钥"。
  • 密钥规模是全部考点:附件包只给出公钥与密文,没有私钥,参赛者的出路只有分解模数。256 位模数只有 77 位十进制数字左右,属于个人电脑上用公开分解工具即可快速处理的范围,与题目名称 "Too Small" 呼应。
  • Flag 分段增加练习价值:三个密文分别对应flag{RS、A_i5、_n00b},参赛者需要分解密钥后对三段分别做openssl rsautl -decrypt(或用程序语言实现 RSA 解密),最终拼接出flag{RSA_i5_n00b}并提交到平台。

作为出题人,这个例子反向说明了安全出题红线:真实环境中的 RSA 密钥必须使用足够大的模数(OpenSSL 建议至少 2048 位),且应使用 OAEP 等带随机填充的加密方案(rsautl默认使用 PKCS#1 v1.5 填充,若用-raw直接加密短明文则存在更多已知弱点)。

提交判定与计分机制的源码级验证

当玩家在 Gameboard 上提交答案后,fbctf 的判定与计分逻辑值得出题人深入了解(以下均可在 Level.php 中查到实现):

  • 答案判定:genCheckAnswer()对flag类型关卡执行trim($level->getFlag()) === trim($answer)的大小写敏感精确比较;而quiz类型则转为大写后再比较(不区分大小写)。因此出题时 Flag 的写法必须与玩家提交完全一致(见 Level.php)。
  • 计分:genScoreLevel()中得分 =points + bonus,即"基础分 + 当前动态加分"。关卡首次被攻克后,genAdjustBonus()会执行UPDATE levels SET bonus = GREATEST(bonus - bonus_dec, 0),让 bonus 随攻克次数逐步衰减直至 0(见 Level.php 与 Level.php)——这是 fbctf 经典的"先到先得多得分"动态计分玩法。
  • 防重复得分:genScoreLevel()会先查询ScoreLog中该队是否已攻克此关卡,已得分则直接返回false,并通过flock文件锁保证并发提交时计分的原子性。
  • 提示扣分:genLevelHint()会在玩家查看提示时从队伍总分中扣除penalty分;若该队已拿过提示或已得分,则提示免费;若队伍当前分数不足以支付扣分,则拒绝返回提示(见 Level.php)。

常见问题与实战注意事项

  • 附件包名是.tar.gz但其实是普通 tar:脚本用tar -cvf打包,扩展名带有误导性。玩家侧tar -xvf tooSmall.tar.gz即可正常解包;出题人若希望真正压缩,应改用tar -czvf。
  • Flag 明文分片与行尾换行:三个明文片段文件是拼接出完整 Flag 的原材料,出题脚本直接对它们做 RSA 加密,因此出题时务必保证三个片段的拼接顺序与内容正确,并记得在提交判定时使用与flag{RSA_i5_n00b}完全一致的写法(判定大小写敏感)。
  • 附件目录权限:上传的附件存放在/var/www/fbctf/attachments/,若后台上传报错,可优先检查该目录是否可写以及 Web 服务用户(www-data)的权限(见 Attachment.php 的attachmentsDir常量定义)。
  • 与交互型题目的区别:Too Small 是纯"提交答案"型 Flag 关卡,玩家下载附件后本地解题,平台只负责判定与计分,无需额外部署服务;对比之下,同仓库的 babys_first_bof 演示关卡是二进制漏洞利用题,出题人还需用socat TCP4-LISTEN:4000,fork,reuseaddr exec:./babys_first_bof单独托管二进制供玩家连接。两类关卡的"部署"边界在出题时需区分清楚。

小结

Too Small 是 fbctf 仓库中最适合学习"Flag 关卡全流程"的示例:一条 weakrsa.sh 完成出题物料的生成,管理后台按 README.md 的 9 步操作即可上线,而 Level.php 与 Attachment.php 的源码则揭示了判定、计分、提示扣分与附件存储的完整底层逻辑。对出题人而言,它是理解平台机制的最小闭环;对参赛者而言,它则是一道"别被 RSA 吓住,先看看密钥多大"的经典入门密码学题目。

  • 网络安全
  • 后端
  • 前端

【免费下载链接】fbctf

Platform to host Capture the Flag competitions

项目地址:https://gitcode.com/gh_mirrors/fb/fbctf
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 20:12:15

手写微型Vue:深入响应式系统与虚拟DOM实现

三年前我第一次把 Vue 的响应式原理图背得滚瓜烂熟,觉得 Proxy、依赖收集、虚拟 DOM 这些东西我算是懂了。直到有一次在代码评审里被问到“一次状态变更后,从 setValue 到页面重绘,中间到底发生了哪几步”,我发现自己只能说出个大…

作者头像 李华
网站建设 2026/10/15 20:11:24

ROS TF坐标变换核心机制与多传感器系统实战避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/15 20:09:58

MyBatis-Plus自动填充实战:从时间戳到多租户的数据治理基石

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/15 20:09:42

Celery分布式任务队列实战:原理、配置与踩坑全解析

做后端开发这几年,我最烦的就是“同步阻塞”带来的一堆烂摊子。用户注册完,验证邮件卡了十来秒;后台导出一份报表,请求一直转圈;每天凌晨要跑的统计任务,总得人肉定闹钟去服务器敲命令。后来把 Celery 用起…

作者头像 李华
网站建设 2026/10/15 20:05:00

2串电池组均衡方案:基于MP2642GR-Z与STM32的备用电源设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华