Kalmar CTF 2025 - RWX series
๋ชฉ์ฐจ
0x00. Introduction
FROM ubuntu:latest
RUN apt-get update && \
apt-get install -y python3 python3-pip gcc
RUN pip3 install flask==3.1.0 --break-system-packages
WORKDIR /
COPY flag.txt /
RUN chmod 400 /flag.txt
COPY would.c /
RUN gcc -o would would.c && \
chmod 6111 would && \
rm would.c
WORKDIR /app
COPY app.py .
RUN useradd -m user
USER user
CMD ["python3", "app.py"]
Dockerfile์ ๋ณด๋ฉด would.c๋ฅผ ๋น๋ํด์ / ๋๋ ํ ๋ฆฌ ๋ฐ์ would ๋ฐ์ด๋๋ฆฌ๋ฅผ ์์ฑํ๋ค. flask๋ก ๊ตฌ๋๋๋ ์น ์๋ฒ๋ฅผ ์ฌ๋ฆฌ๋๋ฐ ์ด๋ฅผ ์ด์ฉํด์ flag๋ฅผ ํ๋ํด์ผ ํ๋ค.
Concept
int
would.c๋ฅผ ๋ณด๋ฉด /would you be so kind to provide me with a flag๋ก ๋ฐ์ด๋๋ฆฌ๋ฅผ ์คํํด์ flag๋ฅผ ํ๋ํ ์ ์๋ค.
=
return
return , 400
=
=
return
return , 400
=
return , 400
=
return
return , 400
app.py๋ฅผ ๋ณด๋ฉด user ๊ถํ์ผ๋ก arbitrary read / write๊ฐ ๊ฐ๋ฅํ๊ณ ๋ช
๋ น์ด ์คํ์ ๊ธธ์ด ์ ํ์ด ์๋ค.
์ด๋ฐ ์์ผ๋ก RWX-Bronze, RWX-Silver, RWX-Gold, RWX-Diamond๊ฐ ์๋๋ฐ ๊ธธ์ด๊ฐ ์ ์ ์ค์ด๋ค๊ฑฐ๋ ํ๊ฒฝ์ด ๋ฐ๋๋ ํ์์ด๋ค.
0x01. RWX-Bronze
์ ์ผ ์ฒ์ ๋ฌธ์ ์ธ Bronze์์๋ 7๋ฐ์ดํธ ์ ํ์ด ๊ฑธ๋ ค์๋ค.
=
return , 400
=
return
return , 400
/write ์๋ํฌ์ธํธ๋ฅผ ์ด์ฉํด์ ๋ค์ ๋ด์ฉ์ /home/user/x๋ผ๋ ํ์ผ์ ์ ์ฅํ๋ค.
์ดํ /exec ์๋ํฌ์ธํธ๋ฅผ ํตํด ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํด์ฃผ๋ฉด ๋๋ค.
sh<~x
0x02. RWX-Silver
์ด๋ฒ์๋ 5๋ฐ์ดํธ ์ ํ์ด ๊ฑธ๋ ค์๋ค.
=
return , 400
=
return
return , 400
Bronze์ ๋ง์ฐฌ๊ฐ์ง๋ก /home/user/x๋ฅผ ์์ฑํ๊ณ ๋ค์ ๋ช
๋ น์ด๋ฅผ ์คํํด์ฃผ๋ฉด ๋๋ค.
. ~/x
0x03. RWX-Gold
์ด๋ฒ์๋ 3๋ฐ์ดํธ์ธ๋ฐ ์ฌ๊ธฐ๋ถํฐ๋ ๋ํ์ค์ ๋ชปํ์๋ค.
=
return , 400
=
return
return , 400
. ~, ~/*, ~;* ๋ฑ ๋ค์ํ๊ฒ ์๋๋ฅผ ํด๋ดค๋๋ฐ ๋ค ์คํจํ๋ค.
๋์ค์ writeup์ ๋ณด๋ PGP์ gnu ๋ฒ์ ์ธ GPG(Gnu Privacy Guard)๋ผ๋ ๋๊ตฌ๋ฅผ ์ด์ฉํด์ผ ํ๋ค. ์ด๋ฉด์ ์ฒ์ ๋ค์ด๋ณด๋ ๋๊ตฌ์ธ๋ฐ ๋๋๊ฒ๋ ubuntu์ ๊ธฐ๋ณธ์ผ๋ก ๊น๋ ค์๋ค.
Exploit ์๋๋ฆฌ์ค๋ฅผ ์ํด ์ ์ PGP์ ๋ํ background๋ฅผ ์ค๋ช ํ์๋ฉด,
- PGP ํค๋ ์ฌ๋ฌ ๊ฐ์ ํจํท(packet)์ผ๋ก ๊ตฌ์ฑ
- ๊ณต๊ฐ ํค ํจํท
- ๋น๋ฐ ํค ํจํท
- ์ฌ์ฉ์ ID ํจํท
- ์๋ช ํจํท
- ์ฌ์ง ID ํจํท
- โฆ
gpg.confํ์ผ์ ํตํด GPG์ ๋์ ๋ฐฉ์์ ์ ์ดํ ์ ์์list-options:gpg --list-keys์คํ ์ ์ต์ ์ ์ค์ ํ๋ tagshow-photos: ํค๋ฅผ ๋์ดํ ๋ PGP ํค์ ์ฒจ๋ถ๋ ์ฌ์ง ํ์
photo-viewer: PGP ํค์ ์ฒจ๋ถ๋ ์ฌ์ง์ ํ์ํ ๋ ์ฌ์ฉํ ํ๋ก๊ทธ๋จ์ ์ง์ ํ๋ taglist-keys: ์ด ์ต์ ์ดgpg.conf์ ์์ผ๋ฉดgpg์คํ ์ ์๋์ผ๋ก ํค ๋ชฉ๋ก์ ํ์
์ค๋ช ์ด gpg, pgp๋ฅผ ์๋ค๊ฐ๋ค ํ๋๋ฐ ์๋ก ํธํ๋๊ฒ ๊ตฌํ๋ ๊ฒ์ด๋ฏ๋ก ํ๋ฆฐ ํํ์ ์๋๋ค.
๋ฐ๋ผ์ ๋ค์๊ณผ ๊ฐ์ ๋ด์ฉ์ /home/user/.gnupg/gpg.conf๋ผ๋ ํ์ผ์ ์ ์ฅํ๋ค.
show-photos
/would you be so kind to provide me with a flag > /tmp/x
์ดํ gpg ๋ช
๋ น์ ์คํํด์ฃผ๋ฉด ์ค์ ๊ฐ์ ๋ฐ๋ผ ํค ๋ชฉ๋ก์ ํ์ํ๊ฒ ๋๊ณ , ๊ทธ ๊ณผ์ ์์ ์ฌ์ง์ ์ถ๋ ฅํ ๋ฐ์ด๋๋ฆฌ๊ฐ /would you be so kind to provide me with a flag > /tmp/x์ผ๋ก ์ง์ ๋์ด์์ผ๋ฏ๋ก ์ฌ์ง์ ์ถ๋ ฅํ ๋ ๋ช
๋ น์ด๊ฐ ์คํ๋๋ค.
Payload
=
= +
+= +
return
= +
+= +
return
= +
+= +
return
=
=
=
0x04. RWX-Diamond
๋ง์ง๋ง ๋ฌธ์ ๋ ์คํ๋ ค 4๋ฐ์ดํธ๋ก ๊ธธ์ด๊ฐ ๋์ด๋ฌ๋ค.
=
return , 400
=
return
return , 400
ํ์ง๋ง Dockerfile์ ๋ณด๋ฉด ๋ฌ๋ผ์ง๊ฒ ์๋ค.
...
# RUN useradd -m user
RUN useradd user
USER user
CMD ["python3", "app.py"]
useradd๋ฅผ ํ ๋ -m ์ต์
์ด ์๊ธฐ ๋๋ฌธ์ /home/user ๋๋ ํ ๋ฆฌ๊ฐ ์์ฑ๋์ง ์์์ ๊ธฐ์กด ๋ฐฉ์์ ์ฌ์ฉํ ์ ์๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก ๋ํ์ค์ ๋ชปํ์ด์ writeup์ ํ์ธํด๋ณด๋ race condition์ผ๋ก ํด๊ฒฐํ ์ ์์๋ค.
์ด๋ฐ ์์ผ๋ก ๋ช ๋ น์ด๋ฅผ ์ฐ์์ผ๋ก ์คํํ ๊ฒฝ์ฐ pid๊ฐ 3๋งํผ ์ฆ๊ฐํ๋ฏ๋ก ๋ค์ ํ๋ก์ธ์ค์ pid๋ฅผ ์์ธกํ ์ ์๋ค.
Exploit ์๋๋ฆฌ์ค๋ ๋ค์๊ณผ ๊ฐ๋ค.
| write | exec |
|---|---|
| Create write process | |
| Create exec process | |
Write โ/would you โฆโ to STDIN of sh | |
Execute w|sh |
w|sh ๋ช
๋ น์ ์คํํ๋ ์ด์ ๋ ๊ธธ์ด๊ฐ 4๋ฐ์ดํธ๊น์ง์ด๊ณ sh ํ๋ก์ธ์ค์ STDIN์ ์ค์ผํ๊ธฐ ๋๋ฌธ์ ํ ๋ฐ์ดํธ์ง๋ฆฌ ๋ช
๋ น์ด์ธ w๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. ์กด์ฌํ์ง ์๋ ๋ช
๋ น์ด๋ฅผ STDIN์ผ๋ก ์ค๋ ๋ ๊ฒ ๊ฐ์ง๋ง time window๊ฐ ๋ค๋ฅธ์ง ์กด์ฌํ๋ ๋ช
๋ น์ด๊ฐ ์ฑ๊ณต ํ๋ฅ ์ด ๋๋ค๊ณ ํ๋ค.
์ด ๋ w|sh๋ sh๋ผ๋ ๋ ๋ค๋ฅธ ํ๋ก์ธ์ค๋ฅผ ์์ฑํ๋ฏ๋ก pid๋ฅผ 3์ด ์๋ 4๋งํผ ์ฆ๊ฐ์์ผ์ผ ํ๋ค.
์ปจ์ ์ ๊ฐ๋จํ๋ฐ ๋ฐ์์ด ๋๋จํ ๊ฒ ๊ฐ๋ค.
Payload
=
=
global
global
= .
= +
+= +
return
=
=
+= 4
=
=
break