基于 Swoole 构建的 CTF AWD 比赛环境搭建与实践

Author: Rytia
Date: 20190427
Blog: www.zzfly.net
本人才学疏浅,望君不吝赐教

背景

受学校老师邀请,为学弟学妹举办分享会介绍 AWD 相关经验,本人一时头脑风暴采用 PHP 的 Swoole 扩展搭建了比赛的环境,将分享会变成了友谊赛。php

出题思路

本次题目来自于个人一个外包项目实践。项目里面大体有这么一个需求:客户登陆系统后,由外部设备触发一个 websocket 发送操做(例如嵌入式中常碰见的“打开门禁”、“滴卡”、“按下开关”等),该请求接收方为某个已经登录的某个用户(一般靠 user id 或用户名绑定)。本人在初次开发这类应用时,将用户惟一身份标识的 user id 做为了这个 websocket 通道的名字,如此一来带来的后果即是不管这个用户在哪台电脑登陆,不管用户登录多少次(小项目无重复登录+挤下线判断),只要成功登陆并打开相应网页便会收到这个 websocket 请求,带来了某些非预期的信息泄露。在实际的项目中解决方法有不少,例如重复登录的判断以及 websocket “匿名通道”创建。本次出题,便以此为基础展开html

AWD 运做原理

CTF-AWD 是线下赛中常见的比赛类型,一般由于攻守兼备而广受选手喜好。这里我主要实现了 AWD 两大关键功能:回合制 、 存活检测 与 动态 flag,至于 flag 提交等前端部份内容,则交由我校 GOCTF 平台处理。前端

  • 回合制:比赛以 10 分钟为一回合。在中心服务器方面,事先使用脚本,根据已开启的靶机数量以及 ip 生成 flag 并保存为文件,并于比赛开始时记录开始时间。每次中心服务器接收到选手靶机的请求时,根据靶机的 ip,以及距离比赛开始的时间,计算出当前处于第几个回合,并返回 flag 数组中相应的值。而在 pusher (一个第三方 websocket 工具,能够为 cli 运行的脚本语言提供发送 websocket 的能力,本次出题依赖 pusher 进行),一样以 10 分钟为一回合,主动向选手端推送含有比赛关键内容的消息
  • 存活检测:本次平台存货监控设置的比较简单,主要为 web 服务(靶机 80 端口)的监控。每隔一段时间向靶机发送 http 请求,下载靶机上某个保存着 pusher 密钥的 js 文件,若该文件大小符合预期,则断定靶机存活。选手在比胜过程中须要盗取到对手的密钥,以窃听他方 websocket 内容,并修改己方 pusher 密钥以放泄露
  • 动态 flag:该部分一样由中心服务器与 pusher 完成。中心服务器在被请求时根据时间不一样(回合不一样)向选手返回不一样 flag。pusher 根据时间不一样(回合不一样)主动推送不一样的 flag 到选手的页面上。

AWD 缺陷总结

本次比赛完成以后,发现这套平台想要真正用于平常选手的训练还有几个问题须要克服linux

  • 因为学校 GOCTF 平台截止比赛时仍未能很好的支持动态 flag 功能,所以根据每一回合中心服务器主动通知CTFF平台 flag 变动的功能没法实现,只能暂时让选手记录本身的 flag 233333….TAT

时钟难以统一。由于 pusher 和 AWD 中心服务器不必定运行在同一台服务器上,且中心服务器为被- 动接收数据,pusher 为主动推送,加之启动时间前后有别,所以每一个回合难以作到彻底统一。日后若是须要再次制做 AWD 比赛平台能够加一个定时心跳包以保证时钟统一laravel

Writeup

介绍完比赛平台的基本运做思路,下面简单讲解一下这道 AWD 题目的作法。git

访问 80 端口,注册多个用户,登录系统后,发现 User ID 为1的用户已经注册,且系统提示必定要以 User ID 为 2 的用户登陆
登陆到 User ID 为 2 的用户后,发现页面启动了 websocket ,隧道名称为 user.2。切换到其余用户后均发现隧道名称为 user.为当前用户登陆 id) 的 websocket 连接
每一回合,发现被主动以弹窗形式提醒了“比赛消息”,且“比赛消息”中包含 flag1,可是弹窗出现后2秒内强制跳转到了用户注销页面(暗示含有XSS)
登陆服务器后台,修改视图文件( home.blade.php ),将底部 JS 部分中当前用户 ID 的输出 user.{{Auth::user()->id}} 修改成 user.1 (表示强制接收 user.1 隧道的消息)
下一回合推送,接收到了 user.1 的消息,获得 flag2,且 flag2 以 = 结束,像 base64 编码,解码后得出 (保密) 帐户的密码的 rot13 值,从新进行 rot13 旋转后获得正确密码
以 (保密) 管理员身份登陆后,发现有头像上传的模块,且仅作了前端校验,burpsuit 修改请求中的文件名便可上传PHP“菜刀”,获得系统 shell,且用户为 root
了解整个过程后,发现 pusher.js 中含有 pusher 帐户的密钥,且这个文件能够在80端口轻松下载,所以每台靶机都存在泄露问题。获得对手的 pusher 密钥后,修改到本身的服务器上便可接收到对手的 user.1 隧道中的消息,获取到对手的 (保密) 管理员帐号密码,从而利用文件上传漏洞 get shell。github

除了常规的备份、上监控、源码审计外,主要有如下几点解题思路。web

主线

/root 目录下存在 readme.txt,提示从历史命令记录里寻找入口点
发现如下两条命令可疑:curl 172.17.0.1 和 php artisan tinker
使用 `ip addr 命令发现与前条命令处于同一网段,猜想是向中心服务器发起请求
进行 curl 测试发现无此命令,且 apt、yum 等工具均为无效,使用 cat /etc/issue 查看到当前系统为 alpine linux,所以使用 apk add curl 命令安装 curl 工具,正常请求后获得 flag3
根据比赛规则,flag3 为动态 flag,每回合变更一次,且不能提交本身靶机上的,所以能够按照这个思路去配合负责进攻部分的队友完成对方靶机的渗透
php artisan tinker 命令为赛题所用 Laravel 框架对 psy shell 的封装,能够直接进入 psy shell 经过 ORM 操做修改管理员帐户的密码,从而获取本身靶机的管理员权限,与上文所述修改 user id 以窃听 websocket 的效果类似,可是难度比较大,也不太符合预期关于 websocket 的考点sql

副线

每一个回合接收到弹窗,都会被强制跳转到“注销”页面,推测有 XSS 漏洞,进行源码审计后,将 resources/views/home.blade.php 文件中 $(“”).html(data.message) 修改成 $(“”).text(data.message) 便可不解析推送内容以放推送 XSS 投毒(仰天大笑~)
源码审计发现存在 upload() 方法用于处理 /upload 这个 url 下的文件上传操做,且不对扩展名、mine type 等进行判断, 能够给对手的服务器尝试强制上传文件。可是 Laravel 框架默认开启 csrf 拦截,须要在对手服务器上注册一个帐号以获取 csrf tokendocker

Github 项目地址

https://github.com/zzfly256/C...

运行环境

AWD 平台部分:PHP 7 + Swoole 4
靶机部分:任意版本 docker

项目文件介绍

  • server:AWD 中心服务器,运行于 docker 母机,负责根据提供每一个回合的 flag:flag3

    • getFlag 文件为 php 可执行文件,根据 docker ps 命令中的启动的容器的 ip,为容器生成不一样的 flag 并保存为 flags.json
    • server 文件为 php 可执行文件,监听 80 端口,根据不一样回合返回 flags.json 文件中的相应值
    • flags.json 保存生成的 flag
  • pusher:Pusher.js 的服务端,运行于 docker 母鸡或任何一台电脑。关于 pusher 的介绍可移步官网:www.pusher.com

    • pusher-admin 文件为 php 可执行文件,为赛题中管理员用户推送消息(供选手窃听 websocket,包含一个 flag :flag2)
    • pusher-user 文件为 php 可执行文件,为赛题中(ID为 2 )的普通注册用户推送消息(包含一个 flag : flag1)
    • monitor 文件为 php 可执行文件,用于监控选手靶机是否存活(监控 web 服务/ pusher.js 文件大小)
    • pusher-server 文件为 php 可执行文件,按照回合(时间)推送消息以及存活检测
    • getFlag 文件为 php 可执行文件,生成管理员消息(flag2)所用
    • pusher-key.json 保存各个靶机的 pusher 密钥,以及 flag2 的值(flag1的值为固定值,每一个选手同样)
  • web:比赛赛题企业网站部分, 是为 laravel 5.8 框架,采用 sqlite 数据库

    • 业务逻辑主要在 /app/Http/Controllers/HomeController.php
    • 视图文件在 /resources/views 目录下
  • docker:靶机 docker 镜像

更多

更多关于本项目的介绍,能够移步:http://www.zzfly.net/build-a-...

相关文章
相关标签/搜索