今天挑戰:
這題是典型的「讀原始碼就能拿到答案」題,作者把密碼直接寫在 checkPassword 函式裡,程式會把輸入的 picoCTF{...} 取出中間部份再比對,所以直接從原始碼讀出字串並把它包回 picoCTF{} 就是 flag。
解題步驟與思路
一、下載題目所需:
wget -O VaultDoorTraining.java "https://jupiter.challenges.picoctf.org/static/1afdf83322ee9c0040f8e3a3c047e18b/VaultDoorTraining.java"
二、檢視原始碼:
head -n 120 VaultDoorTraining.java
重點看到:
String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
...
public boolean checkPassword(String password) {
return password.equals("w4rm1ng_Up_w1tH_jAv4_eec0716b713");
}
三、從原始碼抽出 flag:
grep -n "password.equals" VaultDoorTraining.java \
| sed -E "s/.*password.equals\\(\"([^\"]+)\"\\).*/picoCTF{\1}/"
輸出會是 picoCTF{w4rm1ng_Up_w1tH_jAv4_eec0716b713}
即得到答案啦啦啦!!
原理分析
程式要求輸入格式是 picoCTF{...},它會把大括號內的內容取出(substring)再傳給 checkPassword。
checkPassword 直接用 equals() 比對一個硬寫在程式裡的字串常數。
也就是密碼被明文寫在原始碼中 —— 任何能看到原始碼的人都能直接讀出密碼。
小小心得
看到原始檔先閱讀 main 與輸入,找 main、equals、MessageDigest、char[]、byte[] 等關鍵字會很快定位密碼來源。
善用小工具:head、grep、sed 可以快速抽出常數;遇到陣列常數可以用小段 Python 把數字轉回字元。
先不要盲目跑程式:先看原始檔再決定要不要編譯執行,避免不必要操作或安全風險。
這題其實是提醒我們,絕不要把密碼或機密硬寫在原始碼裡,公開原始碼或被偷走後,所有密碼就會暴露。
實務上應該把敏感資訊放在安全的 secret manager、或至少以環境變數/加密方式管理,並用適當的雜湊存放密碼雜湊而非明文。