Release v2.0.0
Code 面板從一個「能一行讀走 flag、登入狀態留不住、一個無窮迴圈就鎖死整個分頁」的半成品,變成真正可用且與題目隔離的解題環境;題目頁不再因為靜置或多開分頁而毫無訊息地失效;並新增三題商業邏輯黑箱練習題。
🔒 安全性 (Security)
- Code 面板不再能一行讀走 flag:面板改跑在與題目完全隔離的獨立 Python 環境,在面板內讀取 flag 檔或列出題目原始碼一律得到找不到檔案。先前面板與題目共用同一份虛擬檔案系統,所有宣告可用 Code 工具的題目都能用一行讀檔繞過 (#29)
- 關閉一個只存在於本實驗室的非預期解:cookie 值原本以分隔字元串接傳遞,題目若把使用者輸入接進 Set-Cookie,送一個控制字元就能把一個 cookie 切成兩個。改為逐值編碼 (#32)
✨ 新增 (Added)
- 三題全新的商業邏輯黑箱練習題:〈不問原因〉授權經銷商客戶入口(超額購買旗艦授權)、〈每人限用一次〉售票平台(把高價訂位壓到免付款)、〈須經核准〉門禁申請系統(以無權限帳號取得管制區門禁碼)。三題採不同的經濟模型與情境,解題動作刻意不重疊,補上既有三題(資訊洩漏、IDOR、SQLi)未涵蓋的類別。委託書中英雙語齊備,題目卡片標籤只標情境不標漏洞類別,避免點進去前就看到答案 (#28)
- Code 面板新增 Stop 按鈕:執行中隨時中止,且停止前已印出的內容完整保留——列舉或爆破跑到一半印出的那幾行往往就是答案 (#33)
- 題目端單次請求加上十秒執行期限:逾時終止該題執行環境並回應 HTTP 508,題目頁同時告知狀態已重置。用專屬的 508 而非 500/503/504,是為了不讓學生把它誤判成別的故障 (#33)
- Code 面板刻意不設自動執行期限:列舉、爆破、fuzz 都是預期中的解題路徑,任何自動上限都會誤殺正在正確解題的人 (#33)
- 編輯器內容自動保存:重整或下次回到同一題都接得上;草稿依題目分開,清空後重整維持空白而不是被塞回樣板 (#30)
- 執行紀錄下拉:列出本題歷次執行的時間、首行摘要與有無出錯,選一筆把原始碼載回編輯器(不直接執行,Cmd+Z 可退回)。天生依題目分隔,不必命名也不必刪除 (#30)
- 編輯器設定:工具列齒輪按鈕可調整自動完成、括號自動閉合與字型大小(10–24px,可重設)。設定存在本機、跨重整保留、所有題目共用;調整時不重建編輯器,游標與 undo 歷史都留著 (#31)
- PHP 題目終於能出真的題:可設定回應標頭、HTTP 狀態碼與 Set-Cookie,並使用 PHP 原生 session 跨請求保存資料;出題者另有把題目檔案系統還原成初始狀態的出口 (#32)
- 執行環境自身出錯時,Network 面板顯示診斷橫幅:沿用站台警告配色,淺色與深色皆達 WCAG AA,讓出題者分得出是題目邏輯錯還是執行環境掛了 (#32)
- 瀏覽器資料庫開不起來時顯示不可關閉的警示橫幅:說明筆記、執行紀錄與攻擊紀錄皆未儲存也匯不出,並給出處置方式(關掉本站其他分頁再重整)。橫幅不擋操作 (#30)
🔄 變更 (Changed)
- Code 面板的 Python 環境改為第一次點開 Code 分頁時才載入:載入期間顯示進度並暫時停用執行按鈕。沒用到的學生不再多付載入時間與記憶體,用到的首次約多等三秒 (#29, #33)
- Code 面板輸出改為邊跑邊出現:長時間的列舉腳本看得到進度 (#33)
- 環境載入失敗時直接顯示錯誤並保持執行按鈕停用:不再退回改用題目本身的執行環境——讓失敗看得見,也避免退路重新打開讀 flag 的缺口 (#29)
- 網址形式統一由建置設定決定:一般文件頁無副檔名,題目頁這類目錄型頁面保留尾斜線,兩者都是伺服器認定的正規網址。教室短網址
/c/:slug目標不變,出題者不需要改既有連結 (#25) - 自動完成候選改用本平台自維護的模組清單:新增 requests、保留 os,並加上在真實 Python 環境逐一驗證候選符號的檢查 (#31)
- 這次作業完全沒有被記錄下來時,匯出按鈕直接不出現:而不是出現卻按了沒反應 (#30)
- 匯出的攻擊紀錄一併帶上當下尚未執行的草稿並標明未執行過;沒有草稿時該欄位明確為
null,讓讀取者分得出「沒有草稿」與「舊版格式」 (#30) - 題目驗證與分析指令的報告少了終端機指令那一項,其餘項目與格式不變 (#26)
🐛 修復 (Fixed)
- 題目頁不再無訊息卡住:三個來源一次補齊——靜置約一分鐘後所有請求固定回「challenge not registered」,現在會在下一個請求自動重新接上中繼機制;同一題開多分頁、關掉其中一個後存活分頁無限期轉圈,現在等待有固定期限、逾時明確回報並淘汰失效連線;別的分頁開著本站時,Code 面板有版面卻永不出現編輯器、筆記重整後消失、匯出按了沒檔案而主控台一行錯誤都沒有,現在開資料庫有時間上限並主動讓路給其他分頁完成升級 (#30, #32)
- 在 Code 面板送出無窮迴圈不再讓整個分頁失去回應:執行已搬離主執行緒,頁面維持可互動。先前同執行緒的逾時機制一個都救不了——同步的 WebAssembly 迴圈佔住 event loop,
setTimeout、Promise.race、AbortController全都不會執行 (#33) - 用 Python 登入題目後 session 會被記住:後續請求帶著登入狀態,不再被踢回登入頁。先前 cookie jar 永遠是空的,大多數需要登入的題目無法用 Code 面板求解 (#29)
- 一次回應多個 Set-Cookie 全線修好:Code 面板端不再把多個 cookie 串成一個字串(cookie 到期時間本身含逗號,串接後無法還原);Service Worker 端不再併成一個,整個回應也不再被瀏覽器拒絕 (#29, #32)
- 同時送出的多個請求不再互相混流:先前兩個並行請求會各自收到兩份回應主體的串接,未授權路由的回應夾帶授權路由的內容——學生可以完全不靠題目要教的漏洞就解出答案。請求現在排隊,一次服務一個 (#32)
- PHP 題目不再從第二個請求開始就掛掉:先前整題共用同一直譯器,題目只要宣告任何函式,下一個請求就是致命錯誤,全域變數、常數與已送出的標頭也會殘留。現在每個請求都從乾淨狀態開始,只有題目虛擬檔案系統刻意跨請求保留 (#32)
- PHP 題目收到含 null byte 的參數不再整個請求崩潰:先前參數以字串拼接組進程式碼,一個 null byte 就讓前置程式碼語法錯誤——而那正是 PHP 最經典的 payload 之一 (#32)
- PHP 題目印出伺服器變數時不再露出執行環境的真實資訊:家目錄、路徑、使用者名稱等主機環境變數不再外流,以資訊洩漏為主題的題目不會直接穿幫 (#32)
- 題目回應不再被靜默改寫:先前執行環境讀不回題目設定的標頭與狀態碼時,會把「回 403 並設 cookie」降級成「200 且沒有 cookie」,學生因此去 debug 一個題目從未產生過的回應。範圍外與不該帶主體的狀態碼也不再弄死請求,改為明確回報 (#32)
- 執行環境被重置後立刻重建:重建期間三個發送請求的面板暫時停用,這段時間送達的請求排隊等待而不是直接收到錯誤 (#33)
- 執行環境起不來時直接告訴你原因:不再留下永遠轉圈的載入畫面。先前只有成功路徑會回報,之後每個請求都卡在同一個就緒狀態,最後回報的還是與真正原因無關的訊息 (#33)
- 按下 Stop 之後 Run 維持不可用並顯示載入中,直到替代環境真的就緒。先前 Stop 完 Run 立刻可按,但背後的 Python 發行版還要再下載約四十秒 (#33)
- 離開題目頁時一併關掉該頁的執行緒:搬進 Worker 之後,被丟棄的執行環境是一條活著、扛著整份 WebAssembly runtime 的執行緒,不關分頁就會一直累積 (#33)
- 輸入單引號或雙引號時不再自動補上另一個:輸入幾個字元就是幾個字元,即使括號自動閉合開著也一樣。先前 Python 語法套件把引號也當成要成對補齊的對象,手打長 payload 會被無聲改壞 (#31)
- 自動補上的成對括號按一次 Backspace 就整對刪掉,不必刪兩次 (#31)
- 用鍵盤關閉設定面板後焦點回到齒輪按鈕:不會被丟回頁面最開頭重新 Tab。並修正設定文案的大括號被誤判為變數插值、每次繪製都在主控台留錯誤的問題 (#31)
- Code 面板載入期間,左欄題目說明可選取、flag 也送得出去:先前載入覆蓋層在畫面上只蓋住面板,實際可點擊範圍卻橫跨整個視窗並吃掉所有點擊 (#29)
- 站台內點導覽連結後,網址列停在乾淨的無副檔名網址(
/challenges而非/challenges.html),複製出去的連結不會再多繞一次伺服器導向 (#25) - 手寫、未經驗證的題目設定不再能叫出終端機分頁:先前版面直接讀原始設定組分頁列、不查白名單;現在只從四個正式分頁中挑選,寫了也不會出現、也不會報錯 (#26)
🗑️ 移除 (Removed)
- 終端機面板全套下架:面板、指令系統、使用者虛擬檔案系統與指令解析元件全部移除,平台只剩 Browser/Network/Repeater/Code 四個面板。它的對外表面更早之前已停用,只有實作留著,讓後續每一項改動都得繞過一個學生用不到的工具 (#26)
- 題目設定中開放終端機指令的欄位已從出題契約移除:舊題目留著它,驗證仍會判定成立、也照常建置,且不會有任何作用,但建議直接刪掉 (#26)
- Code 面板的「Save」按鈕與「Load script…」下拉移除:先前存下的具名腳本升級後無法取回。舊做法不記錄題目歸屬——A 題存的會出現在 B 題的下拉、存了沒有介面可刪、同名重存變兩筆——因此任何自動搬移都只能用猜的,選擇不搬移。改用執行紀錄還原與草稿自動保存 (#30)
- 不再自動把非同步的 requests 替身塞進 Code 面板環境:一律使用真正的 requests,寫法與一般 Python 腳本一致。先前是否用到替身取決於學生有沒有打上 import 那一行,而兩者用法不相容 (#29)
💥 Breaking Changes
給學生
- 具名腳本無法取回:先前用 Save 存下的腳本在升級後取不回來 → 想留就在升級前自行複製出來,之後改用執行紀錄還原或草稿自動保存 (#30)
- 非同步的 requests 寫法失效:對
requests做await的舊寫法會失敗 → 改成一般同步寫法即可,不需要額外加 import (#29) - 直接讀 flag 檔的取巧解法不再有效:靠它拿分的紀錄會失效 → 那本來就是要修掉的缺口 (#29)
- 程式碼草稿、攻擊 session 與滲透筆記都保留,含終端機事件的舊存檔仍能載入與匯出。瀏覽器內殘留的終端機指令紀錄會被清除,但本站歷史上沒有任何題目啟用過終端機分頁,該紀錄必為空——你不會失去任何東西 (#26, #30)
給出題者
- 單次請求超過十秒的題目會被終止:回應 HTTP 508,題目狀態(含登入 session 與請求寫進去的檔案)一併重置,沒有豁免途徑 → 必須把單次請求壓進十秒內 (#33)
- 題目自行送出
X-Wxlsh-前綴的回應標頭現在會被丟棄並回報 → 該命名空間保留給平台,請改用其他標頭名稱 (#32) - 不使用 session 的 PHP 題目恢復真實網站語意(
headers_sent()、ob_get_level())→ 依賴舊行為的題目行為會改變,請重新驗證 (#32) - 既有六題不受影響:全是 Python 後端、不經過 PHP 執行環境,且本批完全沒有動到
docs/challenge/任何檔案,題目的 frontmatter 與內容一行未改
給 fork 維護者(本版真正的破壞對象)
- 終端機相關程式碼整套移除 → 仍在使用終端機面板、終端機指令欄位或指令解析元件,或沿用
PyodidePublicAPI型別匯入的 fork,合併後建置失敗,必須整套移除或改由 Code 面板取代 (#26) - 腳本儲存 API 移除:
useChallengePersistence()的saveScript/listScripts/loadScript/deleteScript與ScriptEntry型別消失;exportSession()新增一個沒有預設值的必填第二參數 → 呼叫端要跟著改 (#30) - PHP 執行環境介面改變:
run()的回傳移除headers欄位、新增五個必填方法、建構子多一個選用的診斷回呼參數 → 自行建構或替換 PHP 執行環境者要跟著改 (#32) - Set-Cookie 的傳輸編碼契約改變:由分隔字元串接改為逐值編碼 → 自行解析該標頭的下游要改用新編碼 (#32)
- Code 面板的 props 改名:
pyodide/pyodideLoading/pyodideError改為runner/runnerLoading/runnerError,型別改為ToolsRuntimeHost;loadToolsPyodide具名匯出已移除且沒有別名 → 自訂過題目頁版面或 Code 面板的 fork 要跟著改接線,否則 Code 面板拿不到可用的執行環境 (#33) - 執行紀錄回呼的
output語意改變:由「執行結束後的最終全文」變成「累積到中止為止」;被 Stop 中止的執行也會回報且不標記為錯誤 → 既有存檔的欄位型別與還原路徑未變,只有讀取語意要調整 (#33) - 不需要動的:題目 frontmatter 的欄位集合與語意、攻擊 session/滲透筆記/程式碼草稿的儲存結構、本機儲存鍵,以及教室短網址規則
What's Changed
- 🔧 chore: 加入 handoff 技巧,與既有技巧採同一套目錄結構 by @CXPhoenix in #8
- ✨ feat: 把題目敘述改寫為滲透測試委託書,並退役兩題 by @CXPhoenix in #9
- 🐛 fix: 讓 browser panel 的上一頁與下一頁按鈕真的有作用 by @CXPhoenix in #10
- 🔧 chore: 把 1.3.0 的版本 bump 與 CHANGELOG entry 同步回 staging by @CXPhoenix in #12
- 🔧 chore: 把專案身分 URL 由上游模板改為本 fork by @CXPhoenix in #13
- ♻️ refactor: 退役 Terminal 的對外表面,並移除導覽列的 GitHub social link by @CXPhoenix in #14
- 🐛 fix: 題目頁導覽列的語系連結與切換器,並讓網址成為語系的唯一權威 by @CXPhoenix in #15
- 🏗️ build: binaryen 改由固定版本的 GitHub release 安裝,取代會卡住的 apt by @CXPhoenix in #17
- 📝 docs: archive pinned-binaryen-installer 並套用 ci-quality-gates 的 delta by @CXPhoenix in #18
- 🚀 release: 1.4.0 的版號 bump 與 CHANGELOG entry by @CXPhoenix in #16
- 🔧 chore: 把 main 併回 staging,解除 release PR 的內容分岔 by @CXPhoenix in #20
- 🔧 chore: 讓 staging 成為 main 的父節點,終結每次 release 的假衝突 by @CXPhoenix in #23
- 🐛 fix: 讓語系導向交給 router 一個它不會改寫成 .html 的路徑形狀 by @CXPhoenix in #24
- 🐛 fix: 網址列的形式改由 cleanUrls 決定,並移除上一輪那個推不動它的修法 by @CXPhoenix in #25
- ♻️ refactor: 退役 wxlsh terminal 實作,並修好一個會靜默毀掉規格的工具缺陷 by @CXPhoenix in #26
- 🐛 fix: 修好三份 live spec 的區段標頭,讓針對它們的 delta 不再靜默失效 by @CXPhoenix in #27
- ✨ feat: 新增三題 business logic 漏洞題目 by @CXPhoenix in #28
- 🐛 fix: 修好 Code 面板的三個既有缺陷(讀得到 flag、登不了入、覆蓋層吃掉點擊) by @CXPhoenix in #29
- ♻️ refactor: Code 面板改用執行紀錄還原與草稿 autosave,取代具名腳本 by @CXPhoenix in #30
- ✨ feat: Code 面板加上編輯器設定,並讓引號永不自動閉合 by @CXPhoenix in #31
- 🐛 fix: 修好瀏覽器內 runtime 與 Service Worker relay 的三類必然失敗 by @CXPhoenix in #32
- ✨ feat: 三個 runtime 搬進 Web Worker,無窮迴圈不再鎖死分頁 by @CXPhoenix in #33
- 🚀 release: 2.0.0——Code 面板成為真正可用的解題環境,並新增三題商業邏輯練習題 by @CXPhoenix in #34
- 🚀 release: 2.0.0 上 production——Code 面板成為真正可用的解題環境,並新增三題商業邏輯練習題 by @CXPhoenix in #35
Full Changelog: v1.4.0...v2.0.0