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-...