FEAT:🚩 Daily-AlpacaHack 「Catrunner 2」Easy
連続したスラッシュ記号の取り扱いを利用したパストラバーサル
FEAT:🚩 Daily-AlpacaHack 「Catrunner 2」Easy
20260618-daily_alpaca-misc-easy-catrunner_2
Summary
本問は,連続したスラッシュ記号の取り扱いを利用したパストラバーサル問題です.
- Category: Misc
- Description: 🐈️ 💨💨💨 🐈️ 💨💨💨💨💨💨
- Tools & TechStack:
- Python
- Release: 2026/06/18
階層構造
1
2
3
4
5
6
7
8
9
.
├── app.py
├── compose.yaml
├── Dockerfile
├── flag.txt
├── hello.txt
└── thanks.txt
1 directory, 6 files
ソースコードの調査
ソースコードの一連の処理フローは以下のようになっていました.
- 入力されたパス
pathをabspath()で絶対パスに正規化. - 正規化されたファイルパスが実際に存在しているかを,シンボリックリンク含め確認.
"/flag.txt"という文字列が含まれていればアクセス拒否.- 権限内かつ,
"/flag.txt"でなければそのファイルをcatに渡す.
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import os
import subprocess
path = input("Example: /app/hello.txt\n$ cat ")
path = os.path.abspath(path) # 絶対パス
print("Path: " + path, flush=True) # DEBUG
if not os.path.isfile(path): # ファイルのみ
print("File not found")
exit(1)
# "/flag.txt" という固定文字列を介さずにアクセスすればいい
if path == "/flag.txt" or "/proc" in path:
print("Not permitted")
exit(1)
subprocess.run(["cat", path])
連続したスラッシュ記号に対する挙動を利用した Path Traversal
まず,POSIX系システム において,連続する / 記号は1つとして扱う ただし,2つのみ連続している / 記号は正規化しない という例外ルールがあります.(これは,ネットワーク機能などの名残だと思われます) os.path.abspath() は,この仕様に従います.
そのため,以下の挙動を示します.
- 通常:
os.path.abspath('/flag.txt')->/flag.txt //から始まる絶対パス:os.path.abspath('//flag.txt')->//flag.txt(例外ルールによりそのまま残る)/記号が3つ以上:os.path.abspath('///flag.txt')->/flag.txt(3つ以上はPOSIXの例外に当たらないため正規化される)
この挙動と,"/flag.txt" という固定の文字列だけでバリデーションチェックを行っている事を利用すれば,文字列比較をバイパスすることが可能になります.
- Python側:
//flag.txtでバイパスされる. - Linux側:
subprocess.run()で OS (Linux) に渡される.そこでも,//を/と同一のパスとして扱うため,catコマンドが実行される.
1
2
3
4
5
nc localhost 1337
Example: /app/hello.txt
$ cat //flag.txt
Path: //flag.txt
Alpaca{REDACTED}
Post-Mortem & Dead ends
References
This post is licensed under CC BY 4.0 by the author.