简单开发一个CTF平台
取名为Un1kCTF吧,这次和vaalacat一起开发,我负责做平台的前后端,他负责做动态靶机的有关处理。
本文就作为开发进度文,也顺便督促自己做点东西出来。
2022-05-04
感谢bugku提醒。之前未在文章、网站注明前端主题来源。
目前只是因为主题好用 符合本人审美 并且前端开发比后端开发更繁琐 所以暂时使用了相关的布局
后期如若公司使用源码系统将会单独找美工开发 或者会更换布局 尽可能与bugku官方有差异
不过目前只是开发环境测试 并不会共享源代码传播运行环境
再次感谢bugku官方的提醒
2022-04-23
基本信息配置模块
后面可能还需要加其他选项卡 比如邮箱配置、登录配置、权限配置等等,大致demo先做咯
用户表
已解赛题后期根据api来操作,关闭添加时候操作就可以了
题目列表
先按照静态题目来写 后面需要绑定一下模型 就可以做动态分值、动态靶机的设置了
题目分类关联了 题目分类表 可以下拉指定
2022-04-24
解决多表关联显示问题
原来只能够显示1,2这样的id 需要通过left join 创建虚拟字段 拿到id对应的挑战名
记录一下关联的sql语句
2022-04-25
并根据积分进行排名 以及根据后台添加的题目 显示最新添加的9个
编写轮播图功能
接入公告推送与文章阅读
配置文件状态与平台状态同步生效
2022-04-25
编写题目展示模块
可根据用户选择切换分类
公告、题目做了分页
题目增加提示和writeup两个字段 当后台模式为比赛模式 不显示相关writeup
不做团队模式了 太麻烦了 累了
接着只要做flag提交 后台数据联动修改 用户登录 以及把控相关漏洞即可。
2022-04-26
今天把动态靶机做了 用户可以创建靶机 以及销毁容器
今天学到的东西
当用jquery前端追加html代码的时候 追加的代码无法绑定事件
这个时候需要
$("body").on("click", "#createScene", function() {
//code
}
来绑定到相关操作 由于销毁后 按钮会还原成创建靶机 所以两个事件都需要用这个方法 也不会冲突报错
配置用户只能创建一个动态靶机
刷新界面后 只要该用户下存在未销毁场景 会覆盖到web赛题
当用户开两个界面时 企图绕过前端限制
通过后端用户解决赛题的列表 前端动态渲染
根据已解答赛题 限制提交flag
2022-04-27
增加用户登录功能 注册暂时没做
首页赛题攻克显示
2022-04-28
配置用户个人中心 并配置后台数据图用于统计
配置用户个人设置功能
并check了越权等漏洞是否存在 修复一个xss漏洞
增加pwn题的动态靶机部署 mode选择direct
优化前端用户信息显示菜单
2022-04-30
学习sql语句find_in_set
通过语句
SELECT * FROM `cd_chanllenge` WHERE find_in_set(chanllenge_id,(SELECT chanllenge_id from cd_userinfo where userinfo_id =19))
就可以定位到用户解决赛题所对应的所有题目记录
用户所解赛题是以题目id进行排列的,例如1,2,3,4 通过 find_in_set 就可以找到对应的记录 但是不能用in
原因是用in时 当查询的记录是字符串 就会默认转换成int 取第一个数值 当用户做了四题 他也只显示1题
之后只需要试用sum value就可以拿到总分了
但是这并不能实现我的目的
我们的逻辑是 通过用户的所解赛题字段 去表chanllenge找id 然后通过计算后 进行排序 上面我们只是指定了用户id才知道用户的分数
显然 我们都不知道排序情况 并且这个语句只能查出总分 以及对应id 如果是通过遍历用户id 在排序 拿代码太不够简单了
于是重新学习了下 left join 具体的解决思路如下:
1.通过left join 把用户表设置为主表 题目表设置为副表
2.通过find_in_set 函数,通过题目表的chanllenge_id 去用户表的chanllenge_id 进行查询 例如用户解决了四道赛题 那么 会显示四条记录 用户信息的字段都是一样的 无非是聚合的题目信息分别为 四个他所解赛题的信息
3.之后通过nickname 进行groupby 拿到sum(value)
4.通过sum(value) 进行desc排序
语句如下
select nickname,sum(value) from cd_userinfo a left join cd_chanllenge b on find_in_set(b.chanllenge_id,a.chanllenge_id) group by nickname order by sum(value) desc
没想到第一次翻数据库的书居然是写代码的时候 上课都在玩游戏T T
但是这还是不太行 比如我给用户设置了status 给题目也设置了status 我们可不可以弄一个 只有题目有效 和用户正常的状态下 才显示在排行榜 并设置分数呢?
所以进一步优化我们的sql语句
select nickname,sum(value) as total from cd_userinfo a left join cd_chanllenge b on find_in_set(b.chanllenge_id,a.chanllenge_id) where a.status =1 and b.status =1 group by nickname order by sum(value) desc limit 0,10
这里 进行查询的时候我们需要设置为将nickname和sum设置为查询字段,加上判断条件。a代表userinfo表,b代表题目表,只有两个字段都是1代表都正常的时候,才进行聚合。
前面我们的语句把总分as成count 发现出问题了 原来是表里本来就有count,无法覆盖。
最后排行榜显示成功了 不需要额外给数据表加字段 并且可以实时显示总分 (之前的处理逻辑太蠢了 每次用户做题的时候更新总分、添加用户更新总分 再去进行排序 很蠢)
这也很好的为我们 去除了无分数的用户、当后台题目分值修改后动态修改总分 真是他妈的一举多得 前面的语句还会显示用户名 但是分数为null
设置题目动态flag模式 防止作弊
每个用户对应动态靶机的flag不一样 并且生成flag的算法无法被破解
2022-05-04
新增 语句排序号
优化sql语句 使得内容出现 排序号 而不是mysql每一行取值后渲染
select *,(@i:=@i+1) as i from (select nickname,sum(value) as total,team,gravatar from cd_userinfo a left join cd_chanllenge b on find_in_set(b.chanllenge_id,a.chanllenge_id) where a.status =1 and b.status =1 group by nickname order by sum(value) desc limit 0,10) data,(select @i:=0) t
2022-05-06
假期结束 继续优化
增加赛事标签与选择
前端赛事信息布局根据ctf配置中的当前赛事动态修改
并会自行根据时间判断 是否结束 和是否进行 动态修改状态
增加全题显示配置 (开启代表 用户可以做任何赛事的赛题 任何比赛的赛题)
关闭则表示 只能做当前赛事赛题
关闭
关闭则 只会显示本次比赛下的题目 并且其他赛事的题目无法提交flag或者访问题目信息
接入 RSA流量加密
全平台接入 防止爆破flag、爆破密码、爆破验证码
并设置开关按钮来动态控制是否开启rsa加密
防止因为人数过多 造成更大的加解密数据传输成本
2022-05-07
websocket接入 短消息
调用gateway 使用非轮询方式向指定用户、全体登录用户、全体连接设备推送消息
具体可见另一篇文章
接着就是写定向推送用户信息 和登录用户入组的功能编写了 就不贴图了
总结
至此 Un1kCTF1.0 实训平台就开发完毕了
开发周期:2022-04-23 - 2022-05-07 差不多两个礼拜
功能实现如下:
1.动态靶机(动态flag)实现赛题部署
2.基本的登录注册做题功能
3.websocket接入的短消息提醒
4.赛事选择与模式选择
需要完善的功能:
1.反作弊烽火台
2.动态靶机信息完善 加入自动销毁与手动销毁
3.动态靶机绑定域名
4.个人中心功能完善
5.团队功能丰富 接入密码等
....