GDG Docker 闖關 10 分鐘爆破:用 grep 拿走所有 flag

2026-10-14 · ctf · linux · grep · gdg

2026-09-30 的 GDG 社課是「Docker 踏入初心」,lab 叫社團伺服器搶救行動:用 docker compose 起一個 Ubuntu 容器,進去之後找出散落在系統各處的 6 個 GDG{...} flag,交齊之後社團官網就會活過來。

正規路線是一關一關學 cat、cd、ls -a、nano、sudo apt install tree、mkdir / mv / cp。這篇講的是另一條路:所有 flag 都長得一樣,那就直接搜。

先講結論:一個 grep 拿到 5 個 flag,再一個 grep 拿到第 3 關的解密密碼,最後一個迴圈全部交出去。

觀察

  1. flag 格式固定:hint.txt 開頭就寫了「全部有 6 個 flag,格式長這樣 GDG{...}」。
  2. 關卡檔案都在家目錄:Dockerfile 把 lab/home/ 整包 COPY 到 /home/student/,第 4 關的迷宮也是 build 時在同一個地方生出來的。
  3. 檢查 flag 的程式不存明文:submit 只存 djb2 雜湊,所以 flag 只會出現在各關的檔案裡,不會從 submit 洩漏。反過來說,關卡檔案裡的就是明文。

既然 flag 都是明文、都在 ~ 底下、格式又固定,那就是 grep 的工作。

第一步:進容器

docker compose up -d --build
docker compose exec gdg-lab bash

第二步:一個 grep 掃整個家目錄

grep -roE 'GDG\{[a-z0-9_]+\}' ~ | sort -u
/home/student/club_server/level1/backup/old_stuff/flag.txt:GDG{cd_1s_th3_f1rst_st3p}
/home/student/club_server/level2/.gdg_secret:GDG{d0tf1l3s_4r3_sn34ky}
/home/student/club_server/level4/archive/2020/winter/code/secret/flag.txt:GDG{n1c3_try_but_n0t_th1s_0n3}
/home/student/club_server/level4/archive/2022/summer/photos/raw/hackathon_0713/.cache/thumbs/backup/final_v3_FINAL/flag.txt:GDG{tr33_s33s_3v3ryth1ng}
/home/student/club_server/level5/broken_project/main.py:GDG{pr0j3ct_r3st0r3d_g00d_j0b}
/home/student/hint.txt:GDG{h3ll0_t3rm1n4l_w0rld}

每個參數在做什麼:

一次拿到 level 0、1、2、4、5。其中有兩個值得注意:

第三步:第 3 關,密碼也是 GDG 開頭

第 3 關的 flag 被加密在 level3/secret.enc,所以第二步搜不到。解密程式 decrypt.py 需要一個 key.txt,正規路線是去跑 NPC 腳本問密碼。

但是把搜尋條件放寬,只找 GDG 開頭、後面接大寫和數字的字串:

grep -rnoE 'GDG[A-Z]+[0-9]*' ~
/home/student/todo.txt:9:GDGVIP
/home/student/club_server/npc/senior.sh:43:GDGVIP666
/home/student/club_server/npc/senior.sh:48:GDGVIP

todo.txt 裡寫著「改成 GDGVIP███(這裡有咖啡漬)」,被咖啡漬蓋掉的部分,NPC 腳本 senior.sh 直接把整串印了出來:GDGVIP666。不用跑腳本、不用等對話,密碼就在原始碼裡。

decrypt.py 的作法是讀同一個資料夾裡的 key.txt,所以不用開 nano,一行寫進去就好:

cd ~/club_server/level3 && echo GDGVIP666 > key.txt && python3 decrypt.py
╔══ 解密成功 ══╗
FLAG: GDG{d3crypt3d_th3_l3g4cy}

第四步:全部交出去

把兩個來源接在一起,抽出所有 flag,丟給 submit:

for f in $({ grep -rhoE 'GDG\{[a-z0-9_]+\}' ~; python3 ~/club_server/level3/decrypt.py; } \
           | grep -oE 'GDG\{[a-z0-9_]+\}' | sort -u); do
  submit "$f"
done

打開 http://localhost:8080,官網復活。

為什麼這招會成功

這個 lab 是設計給第一次碰 terminal 的人,重點是每關教一個指令,不是防作弊。flag 以明文放在家目錄,權限也是學生自己的,所以任何能讀遍整個目錄的工具都能一次掃完。

其實出題的人自己也偷偷講了。第 4 關的便條紙最後寫著:

(進階:其實有更快的方法。裝完 tree 之後可以試試 tree -af | grep flag …… 或者根本不用裝 tree: find . -name "flag.txt" 這兩招我大四才學會,你現在就知道了,賺到。)

這篇只是把同樣的想法再推一步:不搜檔名,直接搜內容。

如果想讓這招失效,比較直接的作法是:

指令總整理

# 5 個明文 flag
grep -roE 'GDG\{[a-z0-9_]+\}' ~ | sort -u

# 第 3 關的密碼
grep -rnoE 'GDG[A-Z]+[0-9]*' ~

# 解密第 3 關
cd ~/club_server/level3 && echo GDGVIP666 > key.txt && python3 decrypt.py

# 全部交出去
for f in $({ grep -rhoE 'GDG\{[a-z0-9_]+\}' ~; python3 ~/club_server/level3/decrypt.py; } \
           | grep -oE 'GDG\{[a-z0-9_]+\}' | sort -u); do
  submit "$f"
done

正規路線還是值得走一遍,cd、ls -a、nano、apt、mv 和 cp 的差別,之後每天都會用到。只是當你知道目標長什麼樣子的時候,先 grep 一下永遠是對的第一步。