Author: Rytia
Date: 20190427
Blog: www.zzfly.net
本人才学疏浅,望君不吝赐教
受学校老师邀请,为学弟学妹举办分享会介绍 AWD 相关经验,本人一时头脑风暴采用 PHP 的 Swoole
扩展搭建了比赛的环境,将分享会变成了友谊赛。php
本次题目来自于个人一个外包项目实践。项目里面大体有这么一个需求:客户登陆系统后,由外部设备触发一个 websocket 发送操做(例如嵌入式中常碰见的“打开门禁”、“滴卡”、“按下开关”等),该请求接收方为某个已经登录的某个用户(一般靠 user id 或用户名绑定)。本人在初次开发这类应用时,将用户惟一身份标识的 user id 做为了这个 websocket 通道的名字,如此一来带来的后果即是不管这个用户在哪台电脑登陆,不管用户登录多少次(小项目无重复登录+挤下线判断),只要成功登陆并打开相应网页便会收到这个 websocket 请求,带来了某些非预期的信息泄露。在实际的项目中解决方法有不少,例如重复登录的判断以及 websocket “匿名通道”创建。本次出题,便以此为基础展开html
CTF-AWD 是线下赛中常见的比赛类型,一般由于攻守兼备而广受选手喜好。这里我主要实现了 AWD 两大关键功能:回合制 、 存活检测 与 动态 flag,至于 flag 提交等前端部份内容,则交由我校 GOCTF 平台处理。前端
本次比赛完成以后,发现这套平台想要真正用于平常选手的训练还有几个问题须要克服linux
时钟难以统一。由于 pusher 和 AWD 中心服务器不必定运行在同一台服务器上,且中心服务器为被- 动接收数据,pusher 为主动推送,加之启动时间前后有别,所以每一个回合难以作到彻底统一。日后若是须要再次制做 AWD 比赛平台能够加一个定时心跳包以保证时钟统一laravel
介绍完比赛平台的基本运做思路,下面简单讲解一下这道 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
https://github.com/zzfly256/C...
AWD 平台部分:PHP 7 + Swoole 4
靶机部分:任意版本 docker
server:AWD 中心服务器,运行于 docker 母机,负责根据提供每一个回合的 flag:flag3
docker ps
命令中的启动的容器的 ip,为容器生成不一样的 flag 并保存为 flags.json
80
端口,根据不一样回合返回 flags.json
文件中的相应值pusher:Pusher.js
的服务端,运行于 docker
母鸡或任何一台电脑。关于 pusher 的介绍可移步官网:www.pusher.com
websocket
,包含一个 flag :flag2)pusher.js
文件大小)pusher
密钥,以及 flag2 的值(flag1的值为固定值,每一个选手同样)web:比赛赛题企业网站部分, 是为 laravel 5.8
框架,采用 sqlite
数据库
/app/Http/Controllers/HomeController.php
/resources/views
目录下更多关于本项目的介绍,能够移步:http://www.zzfly.net/build-a-...